diff options
Diffstat (limited to 'src/intersim2/power/power_module.cpp')
| -rw-r--r-- | src/intersim2/power/power_module.cpp | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/src/intersim2/power/power_module.cpp b/src/intersim2/power/power_module.cpp new file mode 100644 index 0000000..e319f4b --- /dev/null +++ b/src/intersim2/power/power_module.cpp @@ -0,0 +1,532 @@ +// $Id: power_module.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "power_module.hpp" +#include "booksim_config.hpp" +#include "buffer_monitor.hpp" +#include "switch_monitor.hpp" +#include "iq_router.hpp" + +Power_Module::Power_Module(Network * n , const Configuration &config) + : Module( 0, "power_module" ){ + + + string pfile = config.GetStr("tech_file"); + PowerConfig pconfig; + pconfig.ParseFile(pfile); + + net = n; + output_file_name = config.GetStr("power_output_file"); + classes = config.GetInt("classes"); + channel_width = (double)config.GetInt("channel_width"); + channel_sweep = (double)config.GetInt("channel_sweep"); + + numVC = (double)config.GetInt("num_vcs"); + depthVC = (double)config.GetInt("vc_buf_size"); + + //////////////////////////////////Constants///////////////////////////// + //wire length in (mm) + wire_length = pconfig.GetFloat("wire_length"); + //////////Metal Parameters//////////// + // Wire left/right coupling capacitance [ F/mm ] + Cw_cpl = pconfig.GetFloat("Cw_cpl"); + // Wire up/down groudn capacitance [ F/mm ] + Cw_gnd = pconfig.GetFloat("Cw_gnd"); + Cw = 2.0 * Cw_cpl + 2.0 * Cw_gnd ; + Rw = pconfig.GetFloat("Rw"); + // metal pitch [mm] + MetalPitch = pconfig.GetFloat("MetalPitch"); + + //////////Device Parameters//////////// + + LAMBDA = pconfig.GetFloat("LAMBDA") ; // [um/LAMBDA] + Cd = pconfig.GetFloat("Cd"); // [F/um] (for Delay) + Cg = pconfig.GetFloat("Cg"); // [F/um] (for Delay) + Cgdl = pconfig.GetFloat("Cgdl"); // [F/um] (for Delay) + + Cd_pwr = pconfig.GetFloat("Cd_pwr") ; // [F/um] (for Power) + Cg_pwr = pconfig.GetFloat("Cg_pwr") ; // [F/um] (for Power) + + IoffN = pconfig.GetFloat("IoffN"); // [A/um] + IoffP = pconfig.GetFloat("IoffP"); // [A/um] + // Leakage from bitlines, two-port cell [A] + IoffSRAM = pconfig.GetFloat("IoffSRAM"); + // [Ohm] ( D1=1um Inverter) + R = pconfig.GetFloat("R"); + // [F] ( D1=1um Inverter - for Power ) + Ci_delay = (1.0 + 2.0) * ( Cg + Cgdl ); + // [F] ( D1=1um Inverter - for Power ) + Co_delay = (1.0 + 2.0) * Cd ; + + + Ci = (1.0 + 2.0) * Cg_pwr ; + Co = (1.0 + 2.0) * Cd_pwr ; + + Vdd = pconfig.GetFloat("Vdd"); + FO4 = R * ( 3.0 * Cd + 12 * Cg + 12 * Cgdl); + tCLK = 20 * FO4; + fCLK = 1.0 / tCLK; + + H_INVD2=(double)pconfig.GetInt("H_INVD2"); + W_INVD2=(double)pconfig.GetInt("W_INVD2") ; + H_DFQD1=(double)pconfig.GetInt("H_DFQD1"); + W_DFQD1= (double)pconfig.GetInt("W_DFQD1"); + H_ND2D1= (double)pconfig.GetInt("H_ND2D1"); + W_ND2D1=(double)pconfig.GetInt("W_ND2D1"); + H_SRAM=(double)pconfig.GetInt("H_SRAM"); + W_SRAM=(double)pconfig.GetInt("W_SRAM"); + + ChannelPitch = 2.0 * MetalPitch ; + CrossbarPitch = 2.0 * MetalPitch ; +} + +Power_Module::~Power_Module(){ + + +} + + +////////////////////////////////////////////// +//Channels +////////////////////////////////////////////// + +void Power_Module::calcChannel(const FlitChannel* f){ + double channelLength = f->GetLatency()* wire_length; + wire const this_wire = wireOptimize(channelLength); + double const & K = this_wire.K; + double const & N = this_wire.N; + double const & M = this_wire.M; + //area + channelArea += areaChannel(K,N,M); + + //activity factor; + const vector<int> temp = f->GetActivity(); + vector<double> a(classes); + for(int i = 0; i< classes; i++){ + + a[i] = ((double)temp[i])/totalTime; + } + + //power calculation + double const bitPower = powerRepeatedWire(channelLength, K,M,N); + + channelClkPower += powerWireClk(M,channel_width); + for(int i = 0; i< classes; i++){ + channelWirePower += bitPower * a[i]*channel_width; + channelDFFPower += powerWireDFF(M, channel_width, a[i]); + } + channelLeakPower+= powerRepeatedWireLeak(K,M,N)*channel_width; +} + +wire const & Power_Module::wireOptimize(double L){ + map<double, wire>::iterator iter = wire_map.find(L); + if(iter == wire_map.end()){ + + double W = 64; + double bestMetric = 100000000 ; + double bestK = -1; + double bestM = -1; + double bestN = -1; + for (double K = 1.0 ; K < 10 ; K+=0.1 ) { + for (double N = 1.0 ; N < 40 ; N += 1.0 ) { + for (double M = 1.0 ; M < 40.0 ; M +=1.0 ) { + double l = 1.0 * L/( N * M) ; + + double k0 = R * (Co_delay + Ci_delay) ; + double k1 = R/K * Cw + K * Rw * Ci_delay ; + double k2 = 0.5 * Rw * Cw ; + double Tw = k0 + (k1 * l) + k2 * (l * l) ; + double alpha = 0.2 ; + double power = alpha * W * powerRepeatedWire( L, K, M, N) + powerWireDFF( M, W, alpha ) ; + double metric = M * M * M * M * power ; + if ( (N*Tw) < (0.8 * tCLK) ) { + if ( metric < bestMetric ) { + bestMetric = metric ; + bestK = K ; + bestM = M ; + bestN = N ; + } + } + } + } + } + cout<<"L = "<<L<<" K = "<<bestK<<" M = "<<bestM<<" N = "<<bestN<<endl; + + wire const temp = {L, bestK, bestM, bestN}; + iter = wire_map.insert(make_pair(L, temp)).first; + } + return iter->second; +} + +double Power_Module::powerRepeatedWire(double L, double K, double M, double N){ + + double segments = 1.0 * M * N ; + double Ca = K * (Ci + Co) + Cw * (L/segments) ; + double Pa = 0.5 * Ca * Vdd * Vdd * fCLK; + return Pa * M * N ; + +} + +double Power_Module::powerRepeatedWireLeak (double K, double M, double N){ + double Pl = K * 0.5 * ( IoffN + 2.0 * IoffP ) * Vdd ; + return Pl * M * N ; + +} + +double Power_Module:: powerWireClk (double M, double W){ + // number of clock wires running down one repeater bank + double columns = H_DFQD1 * MetalPitch / ChannelPitch ; + + // length of clock wire + double clockLength = W * ChannelPitch ; + double Cclk = (1 + 5.0/16.0 * (1+Co_delay/Ci_delay)) * (clockLength * Cw * columns +W * Ci_delay); + + return M * Cclk * (Vdd * Vdd) * fCLK ; + +} + +double Power_Module::powerWireDFF(double M, double W, double alpha){ + double Cdin = 2 * 0.8 * (Ci + Co) + 2 * ( 2.0/3.0 * 0.8 * Co ) ; + double Cclk = 2 * 0.8 * (Ci + Co) + 2 * ( 2.0/3.0 * 0.8 * Cg_pwr) ; + double Cint = (alpha * 0.5) * Cdin + alpha * Cclk ; + + return Cint * M * W * (Vdd*Vdd) * fCLK ; +} + + +/////////////////////////////////////////////////////////////// +//Memory +////////////////////////////////////////////////////////////// +void Power_Module::calcBuffer(const BufferMonitor *bm){ + double depth = numVC * depthVC ; + double Pleak = powerMemoryBitLeak( depth ) * channel_width ; + //area + + const vector<int> reads = bm->GetReads(); + const vector<int> writes = bm->GetWrites(); + for(int i = 0; i<bm->NumInputs(); i++){ + inputArea += areaInputModule( depth ); + inputLeakagePower += Pleak ; + for(int j = 0; j< classes; j++){ + double ar = ((double)reads[i* classes+j])/totalTime; + double aw = ((double)writes[i* classes+j])/totalTime; + if(ar>1 ||aw >1){ + cout<<"activity factor is greater than one, soemthing is stomping memory\n"; exit(-1); + } + double Pwl = powerWordLine( channel_width, depth) ; + double Prd = powerMemoryBitRead( depth ) * channel_width ; + double Pwr = powerMemoryBitWrite( depth ) * channel_width ; + inputReadPower += ar * ( Pwl + Prd ) ; + inputWritePower += aw * ( Pwl + Pwr ) ; + } + } +} + + +double Power_Module::powerWordLine(double memoryWidth, double memoryDepth){ + // wordline capacitance + double Ccell = 2 * ( 4.0 * LAMBDA ) * Cg_pwr + 6 * MetalPitch * Cw ; + double Cwl = memoryWidth * Ccell ; + + // wordline circuits + double Warray = 8 * MetalPitch + memoryDepth ; + double x = 1.0 + (5.0/16.0) * (1 + Co/Ci) ; + double Cpredecode = x * (Cw * Warray * Ci) ; + double Cdecode = x * Cwl ; + + // bitline circuits + double Harray = 6 * memoryWidth * MetalPitch ; + double y = (1 + 0.25) * (1 + Co/Ci) ; + double Cprecharge = y * ( Cw * Harray + 3 * channel_width * Ci ) ; + double Cwren = y * ( Cw * Harray + 2 * channel_width * Ci ) ; + + double Cbd = Cprecharge + Cwren ; + double Cwd = 2 * Cpredecode + Cdecode ; + + return ( Cbd + Cwd ) * Vdd * Vdd * fCLK ; + +} + +double Power_Module::powerMemoryBitRead(double memoryDepth){ + // bitline capacitance + double Ccell = 4.0 * LAMBDA * Cd_pwr + 8 * MetalPitch * Cw ; + double Cbl = memoryDepth * Ccell ; + double Vswing = Vdd ; + return ( Cbl ) * ( Vdd * Vswing ) * fCLK ; +} + +double Power_Module:: powerMemoryBitWrite(double memoryDepth){ + // bitline capacitance + double Ccell = 4.0 * LAMBDA * Cd_pwr + 8 * MetalPitch * Cw ; + double Cbl = memoryDepth * Ccell ; + + // internal capacitance + double Ccc = 2 * (Co + Ci) ; + + return (0.5 * Ccc * (Vdd*Vdd)) + ( Cbl ) * ( Vdd * Vdd ) * fCLK ; +} + +double Power_Module::powerMemoryBitLeak(double memoryDepth ){ + + return memoryDepth * IoffSRAM * Vdd ; +} + +/////////////////////////////////////////////////////////////// +//switch +////////////////////////////////////////////////////////////// + +void Power_Module::calcSwitch(const SwitchMonitor* sm){ + + switchArea += areaCrossbar(sm->NumInputs(), sm->NumOutputs()); + outputArea += areaOutputModule(sm->NumOutputs()); + switchPowerLeak += powerCrossbarLeak(channel_width, sm->NumInputs(), sm->NumOutputs()); + + const vector<int> activity = sm->GetActivity(); + vector<double> type_activity(classes); + + for(int i = 0; i<sm->NumOutputs(); i++){ + for(int k = 0; k<classes; k++){ + type_activity[k] = 0; + } + for(int j = 0; j<sm->NumInputs(); j++){ + for(int k = 0; k<classes; k++){ + double a = activity[k+classes*(i+sm->NumOutputs()*j)]; + a = a/totalTime; + if(a>1){ + cout<<"Switcht activity factor is greater than 1!!!\n";exit(-1); + } + double Px = powerCrossbar(channel_width, sm->NumInputs(),sm->NumOutputs(),j,i); + switchPower += a*channel_width*Px; + switchPowerCtrl += a *powerCrossbarCtrl(channel_width, sm->NumInputs(),sm->NumOutputs()); + type_activity[k]+=a; + } + } + outputPowerClk += powerWireClk( 1, channel_width ) ; + for(int k = 0; k<classes; k++){ + outputPower += type_activity[k] * powerWireDFF( 1, channel_width, 1.0 ) ; + outputCtrlPower += type_activity[k] * powerOutputCtrl(channel_width ) ; + } + } + +} + +double Power_Module::powerCrossbar(double width, double inputs, double outputs, double from, double to){ + // datapath traversal power + double Wxbar = width * outputs * CrossbarPitch ; + double Hxbar = width * inputs * CrossbarPitch ; + + // wires + double CwIn = Wxbar * Cw ; + double CwOut = Hxbar * Cw ; + + // cross-points + double Cxi = (1.0/16.0) * CwOut ; + double Cxo = 4.0 * Cxi * (Co_delay/Ci_delay) ; + + // drivers + double Cti = (1.0/16.0) * CwIn ; + double Cto = 4.0 * Cti * (Co_delay/Ci_delay) ; + + double CinputDriver = 5.0/16.0 * (1 + Co_delay/Ci_delay) * (0.5 * Cw * Wxbar + Cti) ; + + // total switched capacitance + + //this maybe missing +Cto + double Cin = CinputDriver + CwIn + Cti + (outputs * Cxi) ; + if ( to < outputs/2 ) { + Cin -= ( 0.5 * CwIn + outputs/2 * Cxi) ; + } + //this maybe missing +cti + double Cout = CwOut + Cto + (inputs * Cxo) ; + if ( from < inputs/2) { + Cout -= ( 0.5 * CwOut + (inputs/2 * Cxo)) ; + } + return 0.5 * (Cin + Cout) * (Vdd * Vdd * fCLK) ; +} + + +double Power_Module::powerCrossbarCtrl(double width, double inputs, double outputs){ + + // datapath traversal power + double Wxbar = width * outputs * CrossbarPitch ; + double Hxbar = width * inputs * CrossbarPitch ; + + // wires + double CwIn = Wxbar * Cw ; + + // drivers + double Cti = (5.0/16.0) * CwIn ; + + // need some estimate of how many control wires are required + double Cctrl = width * Cti + (Wxbar + Hxbar) * Cw ; + double Cdrive = (5.0/16.0) * (1 + Co_delay/Ci_delay) * Cctrl ; + + return (Cdrive + Cctrl) * (Vdd*Vdd) * fCLK ; + +} + +double Power_Module::powerCrossbarLeak (double width, double inputs, double outputs){ + // datapath traversal power + double Wxbar = width * outputs * CrossbarPitch ; + double Hxbar = width * inputs * CrossbarPitch ; + + // wires + double CwIn = Wxbar * Cw ; + double CwOut = Hxbar * Cw ; + // cross-points + double Cxi = (1.0/16.0) * CwOut ; + // drivers + double Cti = (1.0/16.0) * CwIn ; + + return 0.5 * (IoffN + 2 * IoffP)*width*(inputs*outputs*Cxi+inputs*Cti+outputs*Cti)/Ci; +} + +////////////////////////////////////////////////////////////////// +//output module +////////////////////////////////////////////////////////////////// +double Power_Module:: powerOutputCtrl(double width) { + + double Woutmod = channel_width * ChannelPitch ; + double Cen = Ci ; + + double Cenable = (1 + 5.0/16.0)*(1.0+Co/Ci)*(Woutmod* Cw + width* Cen) ; + + return Cenable * (Vdd*Vdd) * fCLK ; + +} + +////////////////////////////////////////////////////////////////// +//area +////////////////////////////////////////////////////////////////// + +double Power_Module:: areaChannel (double K, double N, double M){ + + double Adff = M * W_DFQD1 * H_DFQD1 ; + double Ainv = M * N * ( W_INVD2 + 3 * K) * H_INVD2 ; + + return channel_width * (Adff + Ainv) * MetalPitch * MetalPitch ; +} + +double Power_Module:: areaCrossbar(double Inputs, double Outputs) { + return (Inputs * channel_width * CrossbarPitch) * (Outputs * channel_width * CrossbarPitch) ; +} + +double Power_Module:: areaInputModule(double Words) { + double Asram = ( channel_width * H_SRAM ) * (Words * W_SRAM) ; + return Asram * (MetalPitch * MetalPitch) ; +} + +double Power_Module:: areaOutputModule(double Outputs) { + double Adff = Outputs * W_DFQD1 * H_DFQD1 ; + return channel_width * Adff * MetalPitch * MetalPitch ; +} + +void Power_Module::run(){ + totalTime = GetSimTime(); + channelWirePower=0; + channelClkPower=0; + channelDFFPower=0; + channelLeakPower=0; + inputReadPower=0; + inputWritePower=0; + inputLeakagePower=0; + switchPower=0; + switchPowerCtrl=0; + switchPowerLeak=0; + outputPower=0; + outputPowerClk=0; + outputCtrlPower=0; + channelArea=0; + switchArea=0; + inputArea=0; + outputArea=0; + maxInputPort = 0; + maxOutputPort = 0; + + vector<FlitChannel *> inject = net->GetInject(); + vector<FlitChannel *> eject = net->GetEject(); + vector<FlitChannel *> chan = net->GetChannels(); + + for(int i = 0; i<net->NumNodes(); i++){ + calcChannel(inject[i]); + } + + for(int i = 0; i<net->NumNodes(); i++){ + calcChannel(eject[i]); + } + + for(int i = 0; i<net->NumChannels();i++){ + calcChannel(chan[i]); + } + + vector<Router*> routers = net->GetRouters(); + for(size_t i = 0; i < routers.size(); i++){ + IQRouter* temp = dynamic_cast<IQRouter*>(routers[i]); + const BufferMonitor * bm = temp->GetBufferMonitor(); + calcBuffer(bm); + const SwitchMonitor * sm = temp->GetSwitchMonitor(); + calcSwitch(sm); + } + + double totalpower = channelWirePower+channelClkPower+channelDFFPower+channelLeakPower+ inputReadPower+inputWritePower+inputLeakagePower+ switchPower+switchPowerCtrl+switchPowerLeak+outputPower+outputPowerClk+outputCtrlPower; + double totalarea = channelArea+switchArea+inputArea+outputArea; + cout<< "-----------------------------------------\n" ; + cout<< "- OCN Power Summary\n" ; + cout<< "- Completion Time: "<<totalTime <<"\n" ; + cout<< "- Flit Widths: "<<channel_width<<"\n" ; + cout<< "- Channel Wire Power: "<<channelWirePower <<"\n" ; + cout<< "- Channel Clock Power: "<<channelClkPower <<"\n" ; + cout<< "- Channel Retiming Power: "<<channelDFFPower <<"\n" ; + cout<< "- Channel Leakage Power: "<<channelLeakPower <<"\n" ; + + cout<< "- Input Read Power: "<<inputReadPower <<"\n" ; + cout<< "- Input Write Power: "<<inputWritePower <<"\n" ; + cout<< "- Input Leakage Power: "<<inputLeakagePower <<"\n" ; + + cout<< "- Switch Power: "<<switchPower <<"\n" ; + cout<< "- Switch Control Power: "<<switchPowerCtrl <<"\n" ; + cout<< "- Switch Leakage Power: "<<switchPowerLeak <<"\n" ; + + cout<< "- Output DFF Power: "<<outputPower <<"\n" ; + cout<< "- Output Clk Power: "<<outputPowerClk <<"\n" ; + cout<< "- Output Control Power: "<<outputCtrlPower <<"\n" ; + cout<< "- Total Power: "<<totalpower <<"\n"; + cout<< "-----------------------------------------\n" ; + cout<< "\n" ; + cout<< "-----------------------------------------\n" ; + cout<< "- OCN Area Summary\n" ; + cout<< "- Channel Area: "<<channelArea<<"\n" ; + cout<< "- Switch Area: "<<switchArea<<"\n" ; + cout<< "- Input Area: "<<inputArea<<"\n" ; + cout<< "- Output Area: "<<outputArea<<"\n" ; + cout<< "- Total Area: "<<totalarea<<endl; + cout<< "-----------------------------------------\n" ; + + + + +} |
