diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 424e4d94..b5ccd19b 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -2,6 +2,7 @@ import debug import re import os import math +import tech class spice(): """ @@ -218,7 +219,7 @@ class spice(): del usedMODS spfile.close() - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """Inform users undefined delay module while building new modules""" debug.warning("Design Class {0} delay function needs to be defined" .format(self.__class__.__name__)) @@ -228,15 +229,21 @@ class spice(): # return 0 to keep code running while building return delay_data(0.0, 0.0) - def cal_delay_with_rc(self, r, c ,slew, swing = 0.5): + def cal_delay_with_rc(self, corner, r, c ,slew, swing = 0.5): """ Calculate the delay of a mosfet by modeling it as a resistance driving a capacitance """ swing_factor = abs(math.log(1-swing)) # time constant based on swing + proc,volt,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) + 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 delay = delay * 0.001 #make the unit to ps - + # Output slew should be linear to input slew which is described # as 0.005* slew. @@ -247,6 +254,36 @@ class spice(): slew = delay * 0.6 * 2 + 0.005 * slew return delay_data(delay = delay, slew = slew) + def get_process_delay_factor(self, proc): + """Returns delay increase estimate based off process + Currently does +/-10 for fast/slow corners.""" + proc_factors = [] + for mos_proc in proc: + if mos_proc == 'T': + proc_factors.append(1.0) + elif mos_proc == 'F': + proc_factors.append(0.9) + elif mos_proc == 'S': + proc_factors.append(1.1) + return proc_factors + + def get_voltage_delay_factor(self, voltage): + """Returns delay increase due to voltage. + Implemented as linear factor based off nominal voltage. + """ + return tech.spice['vdd_nominal']/voltage + + def get_temp_delay_factor(self, temp): + """Returns delay increase due to temperature (in C). + Determines effect on threshold voltage and then linear factor is estimated. + """ + #Some portions of equation condensed (phi_t = k*T/q for T in Kelvin) in mV + #(k/q)/100 = .008625, The division 100 simplifies the conversion from C to K and mV to V + thermal_voltage_nom = .008625*tech.spice["temp_nominal"] + thermal_voltage = .008625*temp + vthresh = (tech.spice["v_threshold_typical"]+2*(thermal_voltage-thermal_voltage_nom)) + #Calculate effect on Vdd-Vth. The current vdd is not used here. A separate vdd factor is calculated. + return (tech.spice['vdd_nominal'] - tech.spice["v_threshold_typical"])/(tech.spice['vdd_nominal']-vthresh) def return_delay(self, delay, slew): return delay_data(delay, slew) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 3c49a959..afa8ae1a 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -24,7 +24,7 @@ class bitcell(design.design): self.height = bitcell.height self.pin_map = bitcell.pin_map - def analytical_delay(self, slew, load=0, swing = 0.5): + def analytical_delay(self, corner, slew, load=0, swing = 0.5): # delay of bit cell is not like a driver(from WL) # so the slew used should be 0 # it should not be slew dependent? @@ -33,7 +33,7 @@ class bitcell(design.design): from tech import spice r = spice["min_tx_r"]*3 c_para = spice["min_tx_drain_c"] - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) + result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew, swing = swing) return result diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 79dc734c..30cf9144 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -24,7 +24,7 @@ class bitcell_1rw_1r(design.design): self.height = bitcell_1rw_1r.height self.pin_map = bitcell_1rw_1r.pin_map - def analytical_delay(self, slew, load=0, swing = 0.5): + def analytical_delay(self, corner, slew, load=0, swing = 0.5): # delay of bit cell is not like a driver(from WL) # so the slew used should be 0 # it should not be slew dependent? @@ -33,7 +33,7 @@ class bitcell_1rw_1r(design.design): from tech import spice r = spice["min_tx_r"]*3 c_para = spice["min_tx_drain_c"] - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) + result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew, swing = swing) return result diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 4df9e813..1283db76 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -24,7 +24,7 @@ class bitcell_1w_1r(design.design): self.height = bitcell_1w_1r.height self.pin_map = bitcell_1w_1r.pin_map - def analytical_delay(self, slew, load=0, swing = 0.5): + def analytical_delay(self, corner, slew, load=0, swing = 0.5): # delay of bit cell is not like a driver(from WL) # so the slew used should be 0 # it should not be slew dependent? @@ -33,7 +33,7 @@ class bitcell_1w_1r(design.design): from tech import spice r = spice["min_tx_r"]*3 c_para = spice["min_tx_drain_c"] - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) + result = self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew, swing = swing) return result diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index b241471d..104a2b41 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -866,12 +866,12 @@ class pbitcell(design.design): vdd_pos = self.inverter_pmos_right.get_pin("D").center() self.add_path("metal1", [Q_bar_pos, vdd_pos]) - def analytical_delay(self, slew, load=0, swing = 0.5): + def analytical_delay(self, corner, slew, load=0, swing = 0.5): #FIXME: Delay copied exactly over from bitcell from tech import spice r = spice["min_tx_r"]*3 c_para = spice["min_tx_drain_c"] - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing) + 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): diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 7aa9641d..17ce8c4e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -907,7 +907,7 @@ class delay(simulation): for slew in slews: for load in loads: self.set_load_slew(load,slew) - bank_delay = self.sram.analytical_delay(self.vdd_voltage, self.slew,self.load) + bank_delay = self.sram.analytical_delay(self.corner, self.slew,self.load) for port in self.all_ports: for mname in self.delay_meas_names+self.power_meas_names: if "power" in mname: @@ -921,8 +921,9 @@ class delay(simulation): period_margin = 0.1 risefall_delay = bank_delay[self.read_ports[0]].delay/1e3 sram_data = { "min_period":risefall_delay*2*period_margin, - "leakage_power": power.leakage} - + "leakage_power": power.leakage} + debug.info(2,"SRAM Data:\n{}".format(sram_data)) + debug.info(2,"Port Data:\n{}".format(port_data)) return (sram_data,port_data) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 5d4e9739..7eddc3bb 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1216,26 +1216,30 @@ class bank(design.design): rotate=90) - def analytical_delay(self, vdd, slew, load): + def analytical_delay(self, corner, slew, load): """ return analytical delay of the bank""" results = [] - decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load()) + decoder_delay = self.row_decoder.analytical_delay(corner, slew, self.wordline_driver.input_load()) - word_driver_delay = self.wordline_driver.analytical_delay(decoder_delay.slew, self.bitcell_array.input_load()) + word_driver_delay = self.wordline_driver.analytical_delay(corner, + decoder_delay.slew, + self.bitcell_array.input_load()) #FIXME: Array delay is the same for every port. - bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew) + bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_delay.slew) #This also essentially creates the same delay for each port. Good structure, no substance for port in self.all_ports: if self.words_per_row > 1: - column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew, - self.sense_amp_array.input_load()) + column_mux_delay = self.column_mux_array[port].analytical_delay(corner, + bitcell_array_delay.slew, + self.sense_amp_array.input_load()) else: column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew) - bl_t_data_out_delay = self.sense_amp_array.analytical_delay(column_mux_delay.slew, + bl_t_data_out_delay = self.sense_amp_array.analytical_delay(corner, + column_mux_delay.slew, self.bitcell_array.output_load()) # output load of bitcell_array is set to be only small part of bl for sense amp. results.append(decoder_delay + word_driver_delay + bitcell_array_delay + column_mux_delay + bl_t_data_out_delay) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 67e5a9da..9df5d696 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -130,7 +130,7 @@ class bitcell_array(design.design): self.add_power_pin(pin_name, pin.center(), 0, pin.layer) - def analytical_delay(self, slew, load=0): + def analytical_delay(self, corner, slew, load=0): from tech import drc wl_wire = self.gen_wl_wire() wl_wire.return_delay_over_wire(slew) @@ -141,7 +141,7 @@ class bitcell_array(design.design): cell_load = 2 * bl_wire.return_input_cap() # we ingore the wire r # hence just use the whole c bl_swing = 0.1 - cell_delay = self.cell.analytical_delay(wl_to_cell_delay.slew, cell_load, swing = bl_swing) + cell_delay = self.cell.analytical_delay(corner, wl_to_cell_delay.slew, cell_load, swing = bl_swing) #we do not consider the delay over the wire for now return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay, diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 19077689..8cf02d40 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -39,7 +39,7 @@ class dff(design.design): transition_prob = spice["flop_transition_prob"] return transition_prob*(c_load + c_para) - def analytical_delay(self, slew, load = 0.0): + def analytical_delay(self, corner, slew, load = 0.0): # dont know how to calculate this now, use constant in tech file result = self.return_delay(spice["dff_delay"], spice["dff_slew"]) return result diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 5d728205..9d11b811 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -154,8 +154,8 @@ class dff_array(design.design): - def analytical_delay(self, slew, load=0.0): - return self.dff.analytical_delay(slew=slew, load=load) + def analytical_delay(self, corner, slew, load=0.0): + return self.dff.analytical_delay(corner, slew=slew, load=load) def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 42d37bd1..fa3285ba 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -172,11 +172,11 @@ class dff_buf(design.design): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """ Calculate the analytical delay of DFF-> INV -> INV """ - dff_delay=self.dff.analytical_delay(slew=slew, load=self.inv1.input_load()) - inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) + dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load()) + inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=self.inv2.input_load()) + inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) return dff_delay + inv1_delay + inv2_delay def get_clk_cin(self): diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index b179b1c3..56b20dfb 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -187,7 +187,7 @@ class dff_buf_array(design.design): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): return self.dff.analytical_delay(slew=slew, load=load) def get_clk_cin(self): diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 436026bb..9b901d3b 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -145,10 +145,10 @@ class dff_inv(design.design): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """ Calculate the analytical delay of DFF-> INV -> INV """ - dff_delay=self.dff.analytical_delay(slew=slew, load=self.inv1.input_load()) - inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=load) + dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load()) + inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=load) return dff_delay + inv1_delay def get_clk_cin(self): diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 91ccfa92..624e13d0 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -185,8 +185,8 @@ class dff_inv_array(design.design): - def analytical_delay(self, slew, load=0.0): - return self.dff.analytical_delay(slew=slew, load=load) + def analytical_delay(self, corner, slew, load=0.0): + return self.dff.analytical_delay(corner, slew=slew, load=load) def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 4bbb6aca..bd17b37e 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -594,7 +594,7 @@ class hierarchical_decoder(design.design): rotate=90) - def analytical_delay(self, slew, load = 0.0): + def analytical_delay(self, corner, slew, load = 0.0): # A -> out if self.determine_predecodes(self.num_inputs)[1]==0: pre = self.pre2_4 @@ -602,15 +602,15 @@ class hierarchical_decoder(design.design): else: pre = self.pre3_8 nand = self.nand3 - a_t_out_delay = pre.analytical_delay(slew=slew,load = nand.input_load()) + a_t_out_delay = pre.analytical_delay(corner, slew=slew,load = nand.input_load()) # out -> z - out_t_z_delay = nand.analytical_delay(slew= a_t_out_delay.slew, + out_t_z_delay = nand.analytical_delay(corner, slew= a_t_out_delay.slew, load = self.inv.input_load()) result = a_t_out_delay + out_t_z_delay # Z -> decode_out - z_t_decodeout_delay = self.inv.analytical_delay(slew = out_t_z_delay.slew , load = load) + z_t_decodeout_delay = self.inv.analytical_delay(corner, slew = out_t_z_delay.slew , load = load) result = result + z_t_decodeout_delay return result diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 83e93f85..f50a43c1 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -51,15 +51,15 @@ class hierarchical_predecode2x4(hierarchical_predecode): return combination - def analytical_delay(self, slew, load = 0.0 ): + def analytical_delay(self, corner, slew, load = 0.0 ): # in -> inbar - a_t_b_delay = self.inv.analytical_delay(slew=slew, load=self.nand.input_load()) + a_t_b_delay = self.inv.analytical_delay(corner, slew=slew, load=self.nand.input_load()) # inbar -> z - b_t_z_delay = self.nand.analytical_delay(slew=a_t_b_delay.slew, load=self.inv.input_load()) + b_t_z_delay = self.nand.analytical_delay(corner, slew=a_t_b_delay.slew, load=self.inv.input_load()) # Z -> out - a_t_out_delay = self.inv.analytical_delay(slew=b_t_z_delay.slew, load=load) + a_t_out_delay = self.inv.analytical_delay(corner, slew=b_t_z_delay.slew, load=load) return a_t_b_delay + b_t_z_delay + a_t_out_delay diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index 109e8160..820427c7 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -60,15 +60,15 @@ class hierarchical_predecode3x8(hierarchical_predecode): return combination - def analytical_delay(self, slew, load = 0.0 ): + def analytical_delay(self, corner, slew, load = 0.0 ): # A -> Abar - a_t_b_delay = self.inv.analytical_delay(slew=slew, load=self.nand.input_load()) + a_t_b_delay = self.inv.analytical_delay(corner, slew=slew, load=self.nand.input_load()) # Abar -> z - b_t_z_delay = self.nand.analytical_delay(slew=a_t_b_delay.slew, load=self.inv.input_load()) + b_t_z_delay = self.nand.analytical_delay(corner, slew=a_t_b_delay.slew, load=self.inv.input_load()) # Z -> out - a_t_out_delay = self.inv.analytical_delay(slew=b_t_z_delay.slew, load=load) + a_t_out_delay = self.inv.analytical_delay(corner, slew=b_t_z_delay.slew, load=load) return a_t_b_delay + b_t_z_delay + a_t_out_delay diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 1b9e6194..15882f8b 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -816,19 +816,19 @@ class multibank(design.design): offset=in_pin + self.m2m3_via_offset, rotate=90) - def analytical_delay(self, slew, load): + def analytical_delay(self, corner, slew, load): """ return analytical delay of the bank""" - decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load()) + decoder_delay = self.row_decoder.analytical_delay(corner, slew, self.wordline_driver.input_load()) - word_driver_delay = self.wordline_driver.analytical_delay(decoder_delay.slew, self.bitcell_array.input_load()) + word_driver_delay = self.wordline_driver.analytical_delay(corner, decoder_delay.slew, self.bitcell_array.input_load()) - bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew) + bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_delay.slew) - bl_t_data_out_delay = self.sense_amp_array.analytical_delay(bitcell_array_delay.slew, + bl_t_data_out_delay = self.sense_amp_array.analytical_delay(corner, bitcell_array_delay.slew, self.bitcell_array.output_load()) # output load of bitcell_array is set to be only small part of bl for sense amp. - data_t_DATA_delay = self.tri_gate_array.analytical_delay(bl_t_data_out_delay.slew, load) + data_t_DATA_delay = self.tri_gate_array.analytical_delay(corner, bl_t_data_out_delay.slew, load) result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay return result diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 9601259c..5b9808a8 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -31,11 +31,11 @@ class sense_amp(design.design): bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file. return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): from tech import spice r = spice["min_tx_r"]/(10) c_para = spice["min_tx_drain_c"] - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew) + 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): diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index dc80a13b..47969fd1 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -136,8 +136,8 @@ class sense_amp_array(design.design): def input_load(self): return self.amp.input_load() - def analytical_delay(self, slew, load=0.0): - return self.amp.analytical_delay(slew=slew, load=load) + def analytical_delay(self, corner, slew, load=0.0): + return self.amp.analytical_delay(corner, slew=slew, load=load) def get_en_cin(self): """Get the relative capacitance of all the sense amp enable connections in the array""" diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 49293568..7f20cfb5 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -216,13 +216,14 @@ class single_level_column_mux_array(design.design): offset= br_out_offset, rotate=90) - def analytical_delay(self, vdd, slew, load=0.0): + def analytical_delay(self, corner, vdd, slew, load=0.0): from tech import spice, parameter + proc,volt,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"]/vdd + volt_swing = spice["v_threshold_typical"]/volt - result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = volt_swing) + 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 da42c7a8..61d9da39 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -27,11 +27,11 @@ class tri_gate(design.design): self.height = tri_gate.height self.pin_map = tri_gate.pin_map - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): from tech import spice 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) + return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) def analytical_power(self, proc, vdd, temp, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index d56e9c96..c9dee703 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -116,6 +116,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_delay(self, corner, slew, load=0.0): + return self.tri.analytical_delay(corner, slew = slew, load = load) diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 830c28de..6ddba9de 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -210,12 +210,12 @@ class wordline_driver(design.design): end=wl_offset-vector(self.m1_width,0)) - def analytical_delay(self, slew, load=0): + def analytical_delay(self, corner, slew, load=0): # decode -> net - decode_t_net = self.nand2.analytical_delay(slew, self.inv.input_load()) + decode_t_net = self.nand2.analytical_delay(corner, slew, self.inv.input_load()) # net -> wl - net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load) + net_t_wl = self.inv.analytical_delay(corner, decode_t_net.slew, load) return decode_t_net + net_t_wl diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index a5805728..54787282 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -107,10 +107,10 @@ class pand2(pgate.pgate): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """ Calculate the analytical delay of DFF-> INV -> INV """ - nand_delay = selfnand.analytical_delay(slew=slew, load=self.inv.input_load()) - inv_delay = self.inv.analytical_delay(slew=nand_delay.slew, load=load) + nand_delay = self.nand.analytical_delay(corner, slew=slew, load=self.inv.input_load()) + inv_delay = self.inv.analytical_delay(corner, slew=nand_delay.slew, load=load) return nand_delay + inv_delay def get_stage_efforts(self, external_cout, inp_is_rise=False): diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index a0b36111..9d73c004 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -110,10 +110,10 @@ class pbuf(pgate.pgate): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """ Calculate the analytical delay of DFF-> INV -> INV """ - inv1_delay = self.inv1.analytical_delay(slew=slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) + inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load()) + inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) return inv1_delay + inv2_delay def get_stage_efforts(self, external_cout, inp_is_rise=False): diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 23f3f4f8..daf4d334 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -172,7 +172,7 @@ class pdriver(pgate.pgate): def input_load(self): return self.inv_list[0].input_load() - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """Calculate the analytical delay of INV1 -> ... -> INVn""" cout_list = [] @@ -184,7 +184,7 @@ class pdriver(pgate.pgate): delays = [] for inv,cout in zip(self.inv_list,cout_list): - delays.append(inv.analytical_delay(slew=input_slew, load=cout)) + delays.append(inv.analytical_delay(corner, slew=input_slew, load=cout)) input_slew = delays[-1].slew delay = delays[0] diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index f1ba89f4..867deee2 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -261,10 +261,10 @@ class pinv(pgate.pgate): def input_load(self): return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): 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) + return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) def analytical_power(self, proc, vdd, temp, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index e950bd3f..06936895 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -177,10 +177,10 @@ class pinvbuf(design.design): - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): """ Calculate the analytical delay of DFF-> INV -> INV """ - inv1_delay = self.inv1.analytical_delay(slew=slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) + inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load()) + inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) return inv1_delay + inv2_delay def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False): diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index fa24dc1f..8e702f84 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -227,10 +227,10 @@ class pnand2(pgate.pgate): def input_load(self): return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): 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) + return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) def analytical_power(self, proc, vdd, temp, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index d4554863..4efd1820 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -240,10 +240,10 @@ class pnand3(pgate.pgate): def input_load(self): return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): 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) + return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) def analytical_power(self, proc, vdd, temp, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index d1be51f3..0c62cfe9 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -212,10 +212,10 @@ class pnor2(pgate.pgate): def input_load(self): return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - def analytical_delay(self, slew, load=0.0): + def analytical_delay(self, corner, slew, load=0.0): 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) + return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) def analytical_power(self, proc, vdd, temp, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 61d3639d..611900e4 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -499,9 +499,9 @@ class sram_base(design, verilog, lef): sp.close() - def analytical_delay(self, vdd, slew,load): + def analytical_delay(self, corner, slew,load): """ LH and HL are the same in analytical model. """ - return self.bank.analytical_delay(vdd,slew,load) + return self.bank.analytical_delay(corner,slew,load) def determine_wordline_stage_efforts(self, inp_is_rise=True): """Get the all the stage efforts for each stage in the path from clk_buf to a wordline""" diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index eccfd1c8..760d2a5a 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -300,6 +300,8 @@ spice["channel"] = drc["minlength_channel"] spice["clk"] = "clk" # analytical delay parameters +spice["vdd_nominal"] = 1.0 # Typical Threshold voltage in Volts +spice["temp_nominal"] = 25.0 # Typical Threshold voltage in Volts spice["v_threshold_typical"] = 0.4 # Typical Threshold voltage in Volts spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index d448b5dc..e088eff9 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -240,6 +240,8 @@ spice["clk"] = "clk" # analytical delay parameters # FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. +spice["vdd_nominal"] = 5.0 # Typical Threshold voltage in Volts +spice["temp_nominal"] = 25.0 # Typical Threshold voltage in Volts spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 8b6ee827..78222fd6 100755 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -266,6 +266,8 @@ spice["clk"] = "clk" # analytical delay parameters # FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. +spice["vdd_nominal"] = 5.0 # Typical Threshold voltage in Volts +spice["temp_nominal"] = 25.0 # Typical Threshold voltage in Volts spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2