diff --git a/compiler/bank.py b/compiler/bank.py index c792ee23..ba59a8e9 100644 --- a/compiler/bank.py +++ b/compiler/bank.py @@ -1225,3 +1225,22 @@ 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 + + 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()) + + decoder_power = self.decoder.analytical_power(slew, load) + + word_driver_power = self.wordline_driver.analytical_power(slew, self.bitcell_array.input_load()) + + 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()) + + data_t_DATA_power = self.tri_gate_array.analytical_power(slew, load) + + total_power = msf_addr_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/bitcell.py b/compiler/bitcell.py index 90269692..13486bfd 100644 --- a/compiler/bitcell.py +++ b/compiler/bitcell.py @@ -34,3 +34,8 @@ 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, slew, load=0, swing = 0.5): + #Power of the bitcell. Mostly known for leakage, but dynamic can also be factored in. + #Just skeleton code for now which returns a magic number. + return 5 diff --git a/compiler/bitcell_array.py b/compiler/bitcell_array.py index 44318206..c7fa1bd8 100644 --- a/compiler/bitcell_array.py +++ b/compiler/bitcell_array.py @@ -177,6 +177,27 @@ 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, slew, load=0): + #This will be pretty bare bones as the power needs to be determined from the dynamic power + #of the word line, leakage power from the cell, and dynamic power of the bitlines as a few + #sources for power. These features are tbd. + from tech import drc + + #calculate wl dynamic power, functions not implemented. + #wl_wire = self.gen_wl_wire() + #wl_to_cell_power = wl_wire.return_power_over_wire(slew) + + # hypothetical delay from cell to bl end without sense amp + bl_wire = self.gen_bl_wire() + cell_load = 2 * bl_wire.return_input_cap() # we ingore the wire r + # hence just use the whole c + bl_swing = 0.1 + #Calculate the bitcell power which can include leakage as well as bitline dynamic + cell_power = self.cell.analytical_power(slew, cell_load, swing = bl_swing) + + #we do not consider the delay over the wire for now + return cell_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/hierarchical_decoder.py b/compiler/hierarchical_decoder.py index ac513c0e..0f87ae0e 100644 --- a/compiler/hierarchical_decoder.py +++ b/compiler/hierarchical_decoder.py @@ -494,6 +494,22 @@ class hierarchical_decoder(design.design): result = result + z_t_decodeout_delay return result + def analytical_power(self, slew, load = 0.0): + # A -> out + if self.determine_predecodes(self.num_inputs)[1]==0: + pre = self.pre2_4 + nand = self.nand2 + else: + pre = self.pre3_8 + nand = self.nand3 + a_t_out_power = pre.analytical_power(slew=slew,load = nand.input_load()) + + out_t_z_power = nand.analytical_power(slew, + load = self.inv.input_load()) + + z_t_decodeout_power = self.inv.analytical_power(slew, load = load) + return a_t_out_power + out_t_z_power + z_t_decodeout_power + def input_load(self): if self.determine_predecodes(self.num_inputs)[1]==0: pre = self.pre2_4 diff --git a/compiler/hierarchical_predecode2x4.py b/compiler/hierarchical_predecode2x4.py index 90f86f45..905342c8 100644 --- a/compiler/hierarchical_predecode2x4.py +++ b/compiler/hierarchical_predecode2x4.py @@ -55,5 +55,17 @@ class hierarchical_predecode2x4(hierarchical_predecode): return a_t_b_delay + b_t_z_delay + a_t_out_delay + def analytical_power(self, slew, load = 0.0 ): + # in -> inbar + a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load()) + + # inbar -> z + b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load()) + + # Z -> out + a_t_out_power = self.inv.analytical_power(slew, load=load) + + return a_t_b_power + b_t_z_power + a_t_out_power + def input_load(self): return self.nand.input_load() diff --git a/compiler/hierarchical_predecode3x8.py b/compiler/hierarchical_predecode3x8.py index eff12549..df173548 100644 --- a/compiler/hierarchical_predecode3x8.py +++ b/compiler/hierarchical_predecode3x8.py @@ -63,7 +63,17 @@ class hierarchical_predecode3x8(hierarchical_predecode): return a_t_b_delay + b_t_z_delay + a_t_out_delay + def analytical_power(self, slew, load = 0.0 ): + # in -> inbar + a_t_b_power = self.inv.analytical_power(slew=slew, load=self.nand.input_load()) + # inbar -> z + b_t_z_power = self.nand.analytical_power(slew, load=self.inv.input_load()) + + # Z -> out + a_t_out_power = self.inv.analytical_power(slew, load=load) + + return a_t_b_power + b_t_z_power + a_t_out_power def input_load(self): return self.nand.input_load() diff --git a/compiler/ms_flop.py b/compiler/ms_flop.py index 01928790..c90511f9 100644 --- a/compiler/ms_flop.py +++ b/compiler/ms_flop.py @@ -26,4 +26,7 @@ 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, slew, load = 0.0): + return 4 diff --git a/compiler/ms_flop_array.py b/compiler/ms_flop_array.py index ca51cda3..f80ca54b 100644 --- a/compiler/ms_flop_array.py +++ b/compiler/ms_flop_array.py @@ -134,3 +134,6 @@ class ms_flop_array(design.design): def analytical_delay(self, slew, load=0.0): return self.ms.analytical_delay(slew=slew, load=load) + + def analytical_power(self, slew, load): + return self.ms.analytical_power(slew=slew, load=load) diff --git a/compiler/pinv.py b/compiler/pinv.py index 8bcd7841..b628b4d9 100644 --- a/compiler/pinv.py +++ b/compiler/pinv.py @@ -241,3 +241,7 @@ 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, slew, load=0.0): + #Adding a magic number until I can properly define this. + return 3 diff --git a/compiler/pnand2.py b/compiler/pnand2.py index dfd89680..87f8f006 100644 --- a/compiler/pnand2.py +++ b/compiler/pnand2.py @@ -213,3 +213,7 @@ 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, slew, load=0.0): + #Adding a magic number until I can properly define this. + return 1 diff --git a/compiler/pnand3.py b/compiler/pnand3.py index 6d0b1e79..a8216a45 100644 --- a/compiler/pnand3.py +++ b/compiler/pnand3.py @@ -233,3 +233,7 @@ 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, slew, load=0.0): + #Adding a magic number until I can properly define this. + return 2 diff --git a/compiler/sense_amp.py b/compiler/sense_amp.py index fb6ddb6f..319ed7e3 100644 --- a/compiler/sense_amp.py +++ b/compiler/sense_amp.py @@ -30,3 +30,7 @@ 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, slew, load=0.0): + #This is just skeleton code which returns a magic number. The sense amp consumes static + #power during its operation and some dynamic power due to the switching. + return 2 diff --git a/compiler/sense_amp_array.py b/compiler/sense_amp_array.py index 235a82c5..4ec0a365 100644 --- a/compiler/sense_amp_array.py +++ b/compiler/sense_amp_array.py @@ -117,3 +117,6 @@ class sense_amp_array(design.design): def analytical_delay(self, slew, load=0.0): return self.amp.analytical_delay(slew=slew, load=load) + + def analytical_power(self, slew, load=0.0): + return self.amp.analytical_power(slew=slew, load=load) diff --git a/compiler/sram.py b/compiler/sram.py index d9eb9db8..25499cb3 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -1006,4 +1006,4 @@ class sram(design.design): def analytical_power(self,slew,load): """ Just a test function for the power.""" - return 1 + return self.bank.analytical_power(slew,load) diff --git a/compiler/tri_gate.py b/compiler/tri_gate.py index 7351c575..2cac63a2 100644 --- a/compiler/tri_gate.py +++ b/compiler/tri_gate.py @@ -32,6 +32,10 @@ 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, slew, load=0.0): + #Skeleton code for the power of a trigate. Returns magic number for now. + return 2 def input_load(self): diff --git a/compiler/tri_gate_array.py b/compiler/tri_gate_array.py index fca72cf3..4b9132dc 100644 --- a/compiler/tri_gate_array.py +++ b/compiler/tri_gate_array.py @@ -111,3 +111,6 @@ class tri_gate_array(design.design): def analytical_delay(self, slew, load=0.0): return self.tri.analytical_delay(slew = slew, load = load) + + def analytical_power(self, slew, load=0.0): + return self.tri.analytical_power(slew = slew, load = load) diff --git a/compiler/wordline_driver.py b/compiler/wordline_driver.py index aaab96eb..c1e07bf5 100644 --- a/compiler/wordline_driver.py +++ b/compiler/wordline_driver.py @@ -206,5 +206,14 @@ class wordline_driver(design.design): return decode_t_net + net_t_wl + def analytical_power(self, slew, load=0): + # decode -> net + decode_p_net = self.nand2.analytical_power(slew, self.inv.input_load()) + + # net -> wl + net_p_wl = self.inv.analytical_power(slew, load) + + return decode_p_net + net_p_wl + def input_load(self): return self.nand2.input_load()