diff --git a/compiler/base/design.py b/compiler/base/design.py index 5dd0db14..ad37dfe6 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -122,6 +122,9 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): return text def analytical_power(self, slew, load): - #This function is here return 0 power for every module that does not have a power function defined - #This is a hack and should be made better (also may be a little dangerous) - return 0 + """ Get total power of a module """ + #print "Getting power for ",self.name," module" + total_module_power = 0 + for inst in self.insts: + total_module_power += inst.mod.analytical_power(slew, load) + return total_module_power diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index d218227e..dadebdab 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -214,6 +214,9 @@ class spice(verilog.verilog): def generate_rc_net(self,lump_num, wire_length, wire_width): return wire_spice_model(lump_num, wire_length, wire_width) + + def return_power(self, dynamic, leakage): + return power_data(dynamic, leakage) class delay_data: """ @@ -246,6 +249,37 @@ class delay_data: assert isinstance(other,delay_data) return delay_data(other.delay + self.delay, self.slew) + +class power_data: + """ + This is the power class to represent the power information + Dynamic and leakage power are stored as a single object with this class. + """ + def __init__(self, dynamic=0.0, leakage=0.0): + """ init function support two init method""" + # will take single input as a coordinate + self.dynamic = dynamic + self.leakage = leakage + + def __str__(self): + """ override print function output """ + return "Power Data: Dynamic "+str(self.dynamic)+", Leakage "+str(self.leakage)+" in nW" + + def __add__(self, other): + """ + Override - function (left), for power_data: a+b != b+a + """ + assert isinstance(other,power_data) + return delay_data(other.dynamic + self.dynamic, + other.leakage + self.leakage) + + def __radd__(self, other): + """ + Override - function (left), for power_data: a+b != b+a + """ + assert isinstance(other,power_data) + return delay_data(other.dynamic + self.dynamic, + other.leakage + self.leakage) class wire_spice_model: diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 82515933..8865b71b 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -550,7 +550,9 @@ class delay(): LH_slew.append(bank_delay.slew/1e3) HL_slew.append(bank_delay.slew/1e3) - power = sram.analytical_power(slew, load) + voltage = 1 + temperature = 20 + power = sram.analytical_power(voltage, temperature, load) data = {"min_period": 0, "delay1": LH_delay, diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 3d5bcddf..b936670e 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1229,22 +1229,22 @@ class bank(design.design): + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay return result - def analytical_power(self, slew, load): - """ return analytical power of the bank. Basic skeleton code""" - msf_addr_power = self.msf_address.analytical_power(slew, self.decoder.input_load()) - msf_data_in_power = self.msf_data_in.analytical_power(slew, self.decoder.input_load()) + # def analytical_power(self, slew, load): + # """ return analytical power of the bank. Basic skeleton code""" + # msf_addr_power = self.msf_address.analytical_power(slew, self.decoder.input_load()) + # msf_data_in_power = self.msf_data_in.analytical_power(slew, self.decoder.input_load()) - decoder_power = self.decoder.analytical_power(slew, load) + # decoder_power = self.decoder.analytical_power(slew, load) - word_driver_power = self.wordline_driver.analytical_power(slew, self.bitcell_array.input_load()) + # word_driver_power = self.wordline_driver.analytical_power(slew, self.bitcell_array.input_load()) - bitcell_array_power = self.bitcell_array.analytical_power(slew) + # bitcell_array_power = self.bitcell_array.analytical_power(slew) - bl_t_data_out_power = self.sense_amp_array.analytical_power(slew, - self.bitcell_array.output_load()) + # bl_t_data_out_power = self.sense_amp_array.analytical_power(slew, + # self.bitcell_array.output_load()) - data_t_DATA_power = self.tri_gate_array.analytical_power(slew, load) + # data_t_DATA_power = self.tri_gate_array.analytical_power(slew, load) - total_power = msf_addr_power + msf_data_in_power + decoder_power + word_driver_power \ - + bitcell_array_power + bl_t_data_out_power + data_t_DATA_power - return total_power + # total_power = msf_addr_power + msf_data_in_power + decoder_power + word_driver_power \ + # + bitcell_array_power + bl_t_data_out_power + data_t_DATA_power + # return total_power diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index ce99040f..16091b60 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -688,8 +688,10 @@ class control_logic(design.design): width=pin.width()) - def analytical_power(self, slew, load): + def analytical_power(self, vdd, temp, load): #This has yet to be fully determined. - msf_power = self.msf_control.analytical_power(slew, load) + print "Instances:" + for inst in self.insts: + print inst.name," Instance" #currently, only return flop array power - return msf_power \ No newline at end of file + return 0 \ No newline at end of file diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index b628b4d9..337728ca 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -242,6 +242,18 @@ class pinv(pgate.pgate): c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) - def analytical_power(self, slew, load=0.0): + def analytical_power(self, vdd, temp, load): #Adding a magic number until I can properly define this. - return 3 + c_eff = self.calculate_effective_capacitance(load) + f = spice["default_event_rate"] + power_dyn = c_eff*vdd*vdd*f + power_leak = spice["inv_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + c_load = load + c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff + transistion_prob = spice["inv_transisition_prob"] + return transistion_prob*(c_load + c_para) \ No newline at end of file diff --git a/compiler/sram.py b/compiler/sram.py index 3e80d059..91df3704 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -1015,34 +1015,29 @@ class sram(design.design): """ LH and HL are the same in analytical model. """ return self.bank.analytical_delay(slew,load) - def analytical_power(self,slew,load): + def analytical_power(self, vdd, temp, load): """ Just a test function for the power.""" power_sum = 0; print "Module Powers" - for mod in self.mods: - #print mod.name," Power: ", mod.analytical_power(slew, load) - power_sum += mod.analytical_power(slew, load) + # for mod in self.mods: + # print mod.name," Power: ", mod.analytical_power(slew, load) + # power_sum += mod.analytical_power(slew, load) - print "Instances:" - for inst in self.insts: - print inst.name," Instance" - - print "Modules from Instances:" - for inst in self.insts: - print inst.mod.name," Module" + # print "Instances:" + # for inst in self.insts: + # print inst.name," Instance" - print "Instances from Modules of Instances:" - for inst in self.insts: - print inst.mod.name," Module" - for mod_inst in inst.mod.insts: - print mod_inst.name," Instance" - - #There is only one instance of the bank module in the mod list so this is too account for the other banks - bank_power = self.bank.analytical_power(slew,load) + # print "Instances from Modules of Instances:" + # for inst in self.insts: + # print inst.mod.name," Module" + # for mod_inst in inst.mod.insts: + # print mod_inst.name," Instance" - return bank_power + + power_sum = self.control_logic.analytical_power(vdd, temp, load) + return power_sum def save_output(self): """ Save all the output files while reporting time to do it as well. """ diff --git a/compiler/temp/sram_2_16_1_freepdk45.gds b/compiler/temp/sram_2_16_1_freepdk45.gds index f9ecf3d8..3d0a6910 100644 Binary files a/compiler/temp/sram_2_16_1_freepdk45.gds and b/compiler/temp/sram_2_16_1_freepdk45.gds differ diff --git a/compiler/temp/sram_2_16_1_freepdk45_TT_10V_25C.lib b/compiler/temp/sram_2_16_1_freepdk45_TT_10V_25C.lib index ed43129e..75a20561 100644 --- a/compiler/temp/sram_2_16_1_freepdk45_TT_10V_25C.lib +++ b/compiler/temp/sram_2_16_1_freepdk45_TT_10V_25C.lib @@ -92,10 +92,10 @@ cell (sram_2_16_1_freepdk45){ internal_power(){ when : "OEb & !clk"; rise_power(scalar){ - values("292"); + values("0"); } fall_power(scalar){ - values("292"); + values("0"); } } timing(){ @@ -129,10 +129,10 @@ cell (sram_2_16_1_freepdk45){ internal_power(){ when : "!OEb & !clk"; rise_power(scalar){ - values("292"); + values("0"); } fall_power(scalar){ - values("292"); + values("0"); } } timing(){ diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index dacc3644..21cd87a0 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -275,6 +275,13 @@ spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load spice["msflop_in_cap"] = 0.2091 # Input capacitance of ms_flop (Din) [Femto-farad] +# analytical power parameters +spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nano-Watts +spice["inv_leakage"] = 1 # Leakage power of inverter, temporary until a way to calculate is determined, in nW +spice["msflop_power"] = 1 # Total power of a single flop in nano-Watts + +spice["default_event_rate"] = 200 # Default event activity of every gate. Temporary value. In Mega-Hz +spice["inv_transisition_prob"] = .5 # Transition probability of inverter. Will be dynamically calculated later. ################################################### ##END Spice Simulation Parameters