diff --git a/compiler/base/design.py b/compiler/base/design.py index 39ad1792..1d38f5a9 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -120,3 +120,10 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): for i in self.insts: text+=str(i)+",\n" return text + + def analytical_power(self, proc, vdd, temp, 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) + return total_module_power diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 1b722bd0..71921412 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=0.0, leakage=0.0): + 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 power_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 power_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 c4efa25c..ca51f358 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -721,17 +721,24 @@ class delay(): delay_hl.append(bank_delay.delay/1e3) slew_lh.append(bank_delay.slew/1e3) slew_hl.append(bank_delay.slew/1e3) - + + power = sram.analytical_power(self.process, self.vdd_voltage, self.temperature, load) + #convert from nW to mW + power.dynamic /= 1e6 + power.leakage /= 1e6 + debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic)) + debug.info(1,"Leakage Power: {0} mW".format(power.leakage)) + data = {"min_period": 0, "delay_lh": delay_lh, "delay_hl": delay_hl, "slew_lh": slew_lh, "slew_hl": slew_hl, - "read0_power": 0, - "read1_power": 0, - "write0_power": 0, - "write1_power": 0, - "leakage_power": 0 + "read0_power": power.dynamic, + "read1_power": power.dynamic, + "write0_power": power.dynamic, + "write1_power": power.dynamic, + "leakage_power": power.leakage } return data diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 142d2678..25b8199c 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1228,3 +1228,4 @@ class bank(design.design): result = msf_addr_delay + decoder_delay + word_driver_delay \ + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay return result + diff --git a/compiler/modules/bitcell.py b/compiler/modules/bitcell.py index 90269692..0cb80635 100644 --- a/compiler/modules/bitcell.py +++ b/compiler/modules/bitcell.py @@ -34,3 +34,11 @@ class bitcell(design.design): c_para = spice["min_tx_drain_c"] result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) return result + + def analytical_power(self, proc, vdd, temp, load): + """Bitcell power in nW. Only characterizes leakage.""" + from tech import spice + leakage = spice["bitcell_leakage"] + dynamic = 0 #temporary + total_power = self.return_power(dynamic, leakage) + return total_power diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 44318206..f923f1f8 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -177,6 +177,25 @@ class bitcell_array(design.design): #we do not consider the delay over the wire for now 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): + """Power of Bitcell array and bitline in nW.""" + from tech import drc + + # 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 + freq = spice["default_event_rate"] + bitline_dynamic = bl_swing*cell_load*vdd*vdd*freq #not sure if calculation is correct + + #Calculate the bitcell power which currently only includes leakage + cell_power = self.cell.analytical_power(proc, vdd, temp, load) + + #Leakage power grows with entire array and bitlines. + total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size, + cell_power.leakage * self.column_size * self.row_size) + return total_power def gen_wl_wire(self): wl_wire = self.generate_rc_net(int(self.column_size), self.width, drc["minwidth_metal1"]) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index a006068c..c9dbd436 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -98,7 +98,7 @@ class control_logic(design.design): # GAP between main control and replica bitline self.replica_bitline_gap = 2*self.m2_pitch - + def add_modules(self): @@ -688,4 +688,4 @@ class control_logic(design.design): height=pin.height(), width=pin.width()) - + \ No newline at end of file diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index ac513c0e..12c12007 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -494,6 +494,7 @@ class hierarchical_decoder(design.design): result = result + z_t_decodeout_delay return result + def input_load(self): if self.determine_predecodes(self.num_inputs)[1]==0: pre = self.pre2_4 diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index c621b81e..5dbacf0e 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -55,5 +55,6 @@ class hierarchical_predecode2x4(hierarchical_predecode): return a_t_b_delay + b_t_z_delay + a_t_out_delay + def input_load(self): return self.nand.input_load() diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index eff12549..ded0c612 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -64,6 +64,5 @@ class hierarchical_predecode3x8(hierarchical_predecode): return a_t_b_delay + b_t_z_delay + a_t_out_delay - def input_load(self): return self.nand.input_load() diff --git a/compiler/modules/ms_flop.py b/compiler/modules/ms_flop.py index 01928790..e04b4246 100644 --- a/compiler/modules/ms_flop.py +++ b/compiler/modules/ms_flop.py @@ -26,4 +26,25 @@ class ms_flop(design.design): from tech import spice result = self.return_delay(spice["msflop_delay"], spice["msflop_slew"]) return result + + def analytical_power(self, proc, vdd, temp, load): + """Returns dynamic and leakage power. Results in nW""" + from tech import spice + c_eff = self.calculate_effective_capacitance(load) + f = spice["default_event_rate"] + power_dyn = c_eff*vdd*vdd*f + power_leak = spice["msflop_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + """Computes effective capacitance. Results in fF""" + from tech import spice, parameter + c_load = load + c_para = spice["flop_para_cap"]#ff + transistion_prob = spice["flop_transisition_prob"] + return transistion_prob*(c_load + c_para) + + \ No newline at end of file diff --git a/compiler/modules/ms_flop_array.py b/compiler/modules/ms_flop_array.py index ca51cda3..da3efc6d 100644 --- a/compiler/modules/ms_flop_array.py +++ b/compiler/modules/ms_flop_array.py @@ -134,3 +134,4 @@ class ms_flop_array(design.design): def analytical_delay(self, slew, load=0.0): return self.ms.analytical_delay(slew=slew, load=load) + diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index fb6ddb6f..45a195fc 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -30,3 +30,8 @@ class sense_amp(design.design): result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) return self.return_delay(result.delay, result.slew) + def analytical_power(self, proc, vdd, temp, 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() + return total_power diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 235a82c5..df40a38d 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -117,3 +117,4 @@ class sense_amp_array(design.design): def analytical_delay(self, slew, load=0.0): return self.amp.analytical_delay(slew=slew, load=load) + diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 7351c575..cce7683c 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -32,7 +32,12 @@ class tri_gate(design.design): r = spice["min_tx_r"] c_para = spice["min_tx_drain_c"] return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) - + + def analytical_power(self, proc, vdd, temp, 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() + return total_power def input_load(self): return 9*spice["min_tx_gate_c"] diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index fca72cf3..4bef69c2 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -111,3 +111,4 @@ class tri_gate_array(design.design): def analytical_delay(self, slew, load=0.0): return self.tri.analytical_delay(slew = slew, load = load) + diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index aaab96eb..67d414af 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -205,6 +205,7 @@ class wordline_driver(design.design): net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load) return decode_t_net + net_t_wl - + + def input_load(self): return self.nand2.input_load() diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 8bcd7841..7bf71e5d 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -241,3 +241,20 @@ class pinv(pgate.pgate): r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) 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, proc, vdd, temp, 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_leak = spice["inv_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + """Computes effective capacitance. Results in fF""" + 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/pgates/pnand2.py b/compiler/pgates/pnand2.py index dfd89680..fa576850 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -213,3 +213,20 @@ class pnand2(pgate.pgate): r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) 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, proc, vdd, temp, 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_leak = spice["nand2_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + """Computes effective capacitance. Results in fF""" + c_load = load + c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff + transistion_prob = spice["nand2_transisition_prob"] + return transistion_prob*(c_load + c_para) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 6d0b1e79..02262b39 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -233,3 +233,20 @@ class pnand3(pgate.pgate): r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) 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, proc, vdd, temp, 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_leak = spice["nand3_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + """Computes effective capacitance. Results in fF""" + c_load = load + c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff + transistion_prob = spice["nand3_transisition_prob"] + return transistion_prob*(c_load + c_para) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 684a2b51..4ee1583e 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -223,3 +223,21 @@ class pnor2(pgate.pgate): r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) 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, proc, vdd, temp, 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_leak = spice["nor2_leakage"] + + total_power = self.return_power(power_dyn, power_leak) + return total_power + + def calculate_effective_capacitance(self, load): + """Computes effective capacitance. Results in fF""" + c_load = load + c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff + transistion_prob = spice["nor2_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 951a5ea3..74185aa2 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -1015,7 +1015,6 @@ class sram(design.design): """ LH and HL are the same in analytical model. """ return self.bank.analytical_delay(slew,load) - def save_output(self): """ Save all the output files while reporting time to do it as well. """ diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index e98d78f3..528c6978 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -283,6 +283,21 @@ spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load spice["dff_in_cap"] = 0.2091 # Input capacitance of ms_flop (Din) [Femto-farad] +# analytical power parameters, many values are temporary +spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW +spice["inv_leakage"] = 1 # Leakage power of inverter in nW +spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW +spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW +spice["msflop_leakage"] = 1 # Leakage power of flop in nW +spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF + +spice["default_event_rate"] = 100 # Default event activity of every gate. MHz +spice["flop_transisition_prob"] = .5 # Transition probability of inverter. +spice["inv_transisition_prob"] = .5 # Transition probability of inverter. +spice["nand2_transisition_prob"] = .1875 # Transition probability of 2-input nand. +spice["nand3_transisition_prob"] = .1094 # Transition probability of 3-input nand. +spice["nor2_transisition_prob"] = .1875 # Transition probability of 2-input nor. ################################################### ##END Spice Simulation Parameters diff --git a/technology/scn3me_subm/models/ff/nmos.sp b/technology/scn3me_subm/models/ff/nmos.sp index 278dfc57..9711c533 100644 --- a/technology/scn3me_subm/models/ff/nmos.sp +++ b/technology/scn3me_subm/models/ff/nmos.sp @@ -5,6 +5,6 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL n NMOS (LEVEL=49 VTHO=0.669845 KP=113.7771E-6 +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 + NSUB=6E16 U0=461 K1=0.5705 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/ff/pmos.sp b/technology/scn3me_subm/models/ff/pmos.sp index 86ad3cf1..e08967e4 100644 --- a/technology/scn3me_subm/models/ff/pmos.sp +++ b/technology/scn3me_subm/models/ff/pmos.sp @@ -5,5 +5,5 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 KP=366.0244-6 +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 + NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/nmos.sp b/technology/scn3me_subm/models/nom/nmos.sp index 150788b4..59f88cfd 100644 --- a/technology/scn3me_subm/models/nom/nmos.sp +++ b/technology/scn3me_subm/models/nom/nmos.sp @@ -5,5 +5,5 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL n NMOS (LEVEL=49 VTHO=0.669845 KP=113.7771E-6 +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 + NSUB=6E16 U0=458 K1=0.5705 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/pmos.sp b/technology/scn3me_subm/models/nom/pmos.sp index 4cf58290..69f3aacd 100644 --- a/technology/scn3me_subm/models/nom/pmos.sp +++ b/technology/scn3me_subm/models/nom/pmos.sp @@ -5,5 +5,5 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 KP=366.0244-6 +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 + NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/ss/nmos.sp b/technology/scn3me_subm/models/ss/nmos.sp index 1728b331..4e8a531f 100644 --- a/technology/scn3me_subm/models/ss/nmos.sp +++ b/technology/scn3me_subm/models/ss/nmos.sp @@ -5,6 +5,6 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL n NMOS (LEVEL=49 VTHO=0.669845 KP=113.7771E-6 +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 + NSUB=6E16 U0=460 K1=0.5705 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/ss/pmos.sp b/technology/scn3me_subm/models/ss/pmos.sp index 86ad3cf1..e08967e4 100644 --- a/technology/scn3me_subm/models/ss/pmos.sp +++ b/technology/scn3me_subm/models/ss/pmos.sp @@ -5,5 +5,5 @@ * models from MOSIS or SCN3ME ********************************************* -.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 KP=366.0244-6 +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 + NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index fbb4cb7b..faafb7db 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -246,7 +246,21 @@ spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load spice["dff_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] +# analytical power parameters, many values are temporary +spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW +spice["inv_leakage"] = 1 # Leakage power of inverter in nW +spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW +spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW +spice["msflop_leakage"] = 1 # Leakage power of flop in nW +spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF +spice["default_event_rate"] = 100 # Default event activity of every gate. MHz +spice["flop_transisition_prob"] = .5 # Transition probability of inverter. +spice["inv_transisition_prob"] = .5 # Transition probability of inverter. +spice["nand2_transisition_prob"] = .1875 # Transition probability of 2-input nand. +spice["nand3_transisition_prob"] = .1094 # Transition probability of 3-input nand. +spice["nor2_transisition_prob"] = .1875 # Transition probability of 2-input nor. ################################################### ##END Spice Simulation Parameters ###################################################