diff --git a/compiler/base/contact.py b/compiler/base/contact.py index f5cfcb0b..39cb7b52 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -162,7 +162,7 @@ class contact(hierarchy_design.hierarchy_design): width=well_width, height=well_height) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """ Get total power of a module """ return self.return_power() diff --git a/compiler/base/design.py b/compiler/base/design.py index d07e392a..4e76b40a 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -88,11 +88,11 @@ class design(hierarchy_design): self.readonly_ports.append(port_number) port_number += 1 - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """ Get total power of a module """ total_module_power = self.return_power() for inst in self.insts: - total_module_power += inst.mod.analytical_power(proc, vdd, temp, load) + total_module_power += inst.mod.analytical_power(corner, load) return total_module_power def __str__(self): diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index b5ccd19b..5f3245a8 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -235,10 +235,10 @@ class spice(): modeling it as a resistance driving a capacitance """ swing_factor = abs(math.log(1-swing)) # time constant based on swing - proc,volt,temp = corner + proc,vdd,temp = corner #FIXME: type of delay is needed to know which process to use. proc_mult = max(self.get_process_delay_factor(proc)) - volt_mult = self.get_voltage_delay_factor(volt) + volt_mult = self.get_voltage_delay_factor(vdd) temp_mult = self.get_temp_delay_factor(temp) delay = swing_factor * r * c #c is in ff and delay is in fs delay = delay * proc_mult * volt_mult * temp_mult @@ -291,6 +291,22 @@ class spice(): def generate_rc_net(self,lump_num, wire_length, wire_width): return wire_spice_model(lump_num, wire_length, wire_width) + def calc_dynamic_power(self, corner, c, freq, swing=1.0): + """ + Calculate dynamic power using effective capacitance, frequency, and corner (PVT) + """ + proc,vdd,temp = corner + net_vswing = vdd*swing + power_dyn = c*vdd*net_vswing*freq + + #Apply process and temperature factors. Roughly, process and Vdd affect the delay which affects the power. + #No other estimations are currently used. Increased delay->slower freq.->less power + proc_div = max(self.get_process_delay_factor(proc)) + temp_div = self.get_temp_delay_factor(temp) + power_dyn = power_dyn/(proc_div*temp_div) + + return power_dyn + def return_power(self, dynamic=0.0, leakage=0.0): return power_data(dynamic, leakage) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index afa8ae1a..ed1647a8 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -66,7 +66,7 @@ class bitcell(design.design): column_pins = ["br"] return column_pins - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice leakage = spice["bitcell_leakage"] diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 30cf9144..a96dcff0 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -89,7 +89,7 @@ class bitcell_1rw_1r(design.design): column_pins = ["br0"] return column_pins - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice leakage = spice["bitcell_leakage"] diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 1283db76..e2cc662b 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -89,7 +89,7 @@ class bitcell_1w_1r(design.design): column_pins = ["br0"] return column_pins - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice leakage = spice["bitcell_leakage"] diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 104a2b41..55712e44 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -874,7 +874,7 @@ class pbitcell(design.design): result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew, swing = swing) return result - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice leakage = spice["bitcell_leakage"] diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 17ce8c4e..29b12ae9 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -931,7 +931,7 @@ class delay(simulation): """Get the dynamic and leakage power from the SRAM""" #slews unused, only last load is used load = loads[-1] - power = self.sram.analytical_power(self.process, self.vdd_voltage, self.temperature, load) + power = self.sram.analytical_power(self.corner, load) #convert from nW to mW power.dynamic /= 1e6 power.leakage /= 1e6 diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 9df5d696..ea8fc3f2 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -147,19 +147,19 @@ class bitcell_array(design.design): return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay, wl_to_cell_delay.slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" - from tech import drc + from tech import drc, parameter # Dynamic Power from Bitline bl_wire = self.gen_bl_wire() cell_load = 2 * bl_wire.return_input_cap() - bl_swing = 0.1 #This should probably be defined in the tech file or input + bl_swing = parameter["rbl_height_percentage"] freq = spice["default_event_rate"] - bitline_dynamic = bl_swing*cell_load*vdd*vdd*freq #not sure if calculation is correct + bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) #Calculate the bitcell power which currently only includes leakage - cell_power = self.cell.analytical_power(proc, vdd, temp, load) + cell_power = self.cell.analytical_power(corner, load) #Leakage power grows with entire array and bitlines. total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size, diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 8cf02d40..753ae41a 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -21,11 +21,11 @@ class dff(design.design): self.height = dff.height self.pin_map = dff.pin_map - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) - f = spice["default_event_rate"] - power_dyn = c_eff*vdd*vdd*f + freq = spice["default_event_rate"] + power_dyn = self.calc_dynamic_power(corner, c_eff, freq) power_leak = spice["msflop_leakage"] total_power = self.return_power(power_dyn, power_leak) diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 5b9808a8..0c959685 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -38,7 +38,7 @@ class sense_amp(design.design): result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) return self.return_delay(result.delay, result.slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). total_power = self.return_power() diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 7f20cfb5..57d2cd54 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -218,11 +218,11 @@ class single_level_column_mux_array(design.design): def analytical_delay(self, corner, vdd, slew, load=0.0): from tech import spice, parameter - proc,volt,temp = corner + proc,vdd,temp = corner r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"]) #Drains of mux transistors make up capacitance. c_para = spice["min_tx_drain_c"]*(self.mux.ptx_width/parameter["min_tx_size"])*self.words_per_row#ff - volt_swing = spice["v_threshold_typical"]/volt + volt_swing = spice["v_threshold_typical"]/vdd result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew, swing = volt_swing) return self.return_delay(result.delay, result.slew) diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 61d9da39..688b3644 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -33,7 +33,7 @@ class tri_gate(design.design): c_para = spice["min_tx_drain_c"] return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). total_power = self.return_power() diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 867deee2..f00e9af7 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -266,11 +266,11 @@ 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(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) freq = spice["default_event_rate"] - power_dyn = c_eff*vdd*vdd*freq + power_dyn = self.calc_dynamic_power(corner, c_eff, freq) power_leak = spice["inv_leakage"] total_power = self.return_power(power_dyn, power_leak) diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 8e702f84..95a9bc28 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -232,11 +232,11 @@ class pnand2(pgate.pgate): c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) freq = spice["default_event_rate"] - power_dyn = c_eff*vdd*vdd*freq + power_dyn = self.calc_dynamic_power(corner, c_eff, freq) power_leak = spice["nand2_leakage"] total_power = self.return_power(power_dyn, power_leak) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 4efd1820..d0c37b55 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -245,11 +245,11 @@ class pnand3(pgate.pgate): c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) freq = spice["default_event_rate"] - power_dyn = c_eff*vdd*vdd*freq + power_dyn = self.calc_dynamic_power(corner, c_eff, freq) power_leak = spice["nand3_leakage"] total_power = self.return_power(power_dyn, power_leak) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 0c62cfe9..8a5c80d4 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -217,11 +217,11 @@ class pnor2(pgate.pgate): c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, proc, vdd, temp, load): + def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) freq = spice["default_event_rate"] - power_dyn = c_eff*vdd*vdd*freq + power_dyn = self.calc_dynamic_power(corner, c_eff, freq) power_leak = spice["nor2_leakage"] total_power = self.return_power(power_dyn, power_leak)