Added linear corner factors in analytical delay model.

This commit is contained in:
Hunter Nichols 2019-03-04 00:42:18 -08:00
parent 816669b9ca
commit 0e96648211
36 changed files with 138 additions and 89 deletions

View File

@ -2,6 +2,7 @@ import debug
import re import re
import os import os
import math import math
import tech
class spice(): class spice():
""" """
@ -218,7 +219,7 @@ class spice():
del usedMODS del usedMODS
spfile.close() 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""" """Inform users undefined delay module while building new modules"""
debug.warning("Design Class {0} delay function needs to be defined" debug.warning("Design Class {0} delay function needs to be defined"
.format(self.__class__.__name__)) .format(self.__class__.__name__))
@ -228,13 +229,19 @@ class spice():
# return 0 to keep code running while building # return 0 to keep code running while building
return delay_data(0.0, 0.0) 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 Calculate the delay of a mosfet by
modeling it as a resistance driving a capacitance modeling it as a resistance driving a capacitance
""" """
swing_factor = abs(math.log(1-swing)) # time constant based on swing 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 = 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 delay = delay * 0.001 #make the unit to ps
# Output slew should be linear to input slew which is described # Output slew should be linear to input slew which is described
@ -247,6 +254,36 @@ class spice():
slew = delay * 0.6 * 2 + 0.005 * slew slew = delay * 0.6 * 2 + 0.005 * slew
return delay_data(delay = delay, slew = 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): def return_delay(self, delay, slew):
return delay_data(delay, slew) return delay_data(delay, slew)

View File

@ -24,7 +24,7 @@ class bitcell(design.design):
self.height = bitcell.height self.height = bitcell.height
self.pin_map = bitcell.pin_map 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) # delay of bit cell is not like a driver(from WL)
# so the slew used should be 0 # so the slew used should be 0
# it should not be slew dependent? # it should not be slew dependent?
@ -33,7 +33,7 @@ class bitcell(design.design):
from tech import spice from tech import spice
r = spice["min_tx_r"]*3 r = spice["min_tx_r"]*3
c_para = spice["min_tx_drain_c"] 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 return result

View File

@ -24,7 +24,7 @@ class bitcell_1rw_1r(design.design):
self.height = bitcell_1rw_1r.height self.height = bitcell_1rw_1r.height
self.pin_map = bitcell_1rw_1r.pin_map 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) # delay of bit cell is not like a driver(from WL)
# so the slew used should be 0 # so the slew used should be 0
# it should not be slew dependent? # it should not be slew dependent?
@ -33,7 +33,7 @@ class bitcell_1rw_1r(design.design):
from tech import spice from tech import spice
r = spice["min_tx_r"]*3 r = spice["min_tx_r"]*3
c_para = spice["min_tx_drain_c"] 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 return result

View File

@ -24,7 +24,7 @@ class bitcell_1w_1r(design.design):
self.height = bitcell_1w_1r.height self.height = bitcell_1w_1r.height
self.pin_map = bitcell_1w_1r.pin_map 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) # delay of bit cell is not like a driver(from WL)
# so the slew used should be 0 # so the slew used should be 0
# it should not be slew dependent? # it should not be slew dependent?
@ -33,7 +33,7 @@ class bitcell_1w_1r(design.design):
from tech import spice from tech import spice
r = spice["min_tx_r"]*3 r = spice["min_tx_r"]*3
c_para = spice["min_tx_drain_c"] 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 return result

View File

@ -866,12 +866,12 @@ class pbitcell(design.design):
vdd_pos = self.inverter_pmos_right.get_pin("D").center() vdd_pos = self.inverter_pmos_right.get_pin("D").center()
self.add_path("metal1", [Q_bar_pos, vdd_pos]) 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 #FIXME: Delay copied exactly over from bitcell
from tech import spice from tech import spice
r = spice["min_tx_r"]*3 r = spice["min_tx_r"]*3
c_para = spice["min_tx_drain_c"] 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 return result
def analytical_power(self, proc, vdd, temp, load): def analytical_power(self, proc, vdd, temp, load):

View File

@ -907,7 +907,7 @@ class delay(simulation):
for slew in slews: for slew in slews:
for load in loads: for load in loads:
self.set_load_slew(load,slew) 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 port in self.all_ports:
for mname in self.delay_meas_names+self.power_meas_names: for mname in self.delay_meas_names+self.power_meas_names:
if "power" in mname: if "power" in mname:
@ -922,7 +922,8 @@ class delay(simulation):
risefall_delay = bank_delay[self.read_ports[0]].delay/1e3 risefall_delay = bank_delay[self.read_ports[0]].delay/1e3
sram_data = { "min_period":risefall_delay*2*period_margin, 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) return (sram_data,port_data)

View File

@ -1216,26 +1216,30 @@ class bank(design.design):
rotate=90) rotate=90)
def analytical_delay(self, vdd, slew, load): def analytical_delay(self, corner, slew, load):
""" return analytical delay of the bank""" """ return analytical delay of the bank"""
results = [] 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. #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 #This also essentially creates the same delay for each port. Good structure, no substance
for port in self.all_ports: for port in self.all_ports:
if self.words_per_row > 1: if self.words_per_row > 1:
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew, column_mux_delay = self.column_mux_array[port].analytical_delay(corner,
self.sense_amp_array.input_load()) bitcell_array_delay.slew,
self.sense_amp_array.input_load())
else: else:
column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew) 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()) self.bitcell_array.output_load())
# output load of bitcell_array is set to be only small part of bl for sense amp. # 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) results.append(decoder_delay + word_driver_delay + bitcell_array_delay + column_mux_delay + bl_t_data_out_delay)

View File

@ -130,7 +130,7 @@ class bitcell_array(design.design):
self.add_power_pin(pin_name, pin.center(), 0, pin.layer) 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 from tech import drc
wl_wire = self.gen_wl_wire() wl_wire = self.gen_wl_wire()
wl_wire.return_delay_over_wire(slew) 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 cell_load = 2 * bl_wire.return_input_cap() # we ingore the wire r
# hence just use the whole c # hence just use the whole c
bl_swing = 0.1 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 #we do not consider the delay over the wire for now
return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay, return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay,

View File

@ -39,7 +39,7 @@ class dff(design.design):
transition_prob = spice["flop_transition_prob"] transition_prob = spice["flop_transition_prob"]
return transition_prob*(c_load + c_para) 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 # dont know how to calculate this now, use constant in tech file
result = self.return_delay(spice["dff_delay"], spice["dff_slew"]) result = self.return_delay(spice["dff_delay"], spice["dff_slew"])
return result return result

View File

@ -154,8 +154,8 @@ class dff_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) return self.dff.analytical_delay(corner, slew=slew, load=load)
def get_clk_cin(self): def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" """Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""

View File

@ -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 """ """ Calculate the analytical delay of DFF-> INV -> INV """
dff_delay=self.dff.analytical_delay(slew=slew, load=self.inv1.input_load()) dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load())
inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=self.inv2.input_load()) inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=self.inv2.input_load())
inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load)
return dff_delay + inv1_delay + inv2_delay return dff_delay + inv1_delay + inv2_delay
def get_clk_cin(self): def get_clk_cin(self):

View File

@ -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) return self.dff.analytical_delay(slew=slew, load=load)
def get_clk_cin(self): def get_clk_cin(self):

View File

@ -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 """ """ Calculate the analytical delay of DFF-> INV -> INV """
dff_delay=self.dff.analytical_delay(slew=slew, load=self.inv1.input_load()) dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load())
inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=load) inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=load)
return dff_delay + inv1_delay return dff_delay + inv1_delay
def get_clk_cin(self): def get_clk_cin(self):

View File

@ -185,8 +185,8 @@ class dff_inv_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) return self.dff.analytical_delay(corner, slew=slew, load=load)
def get_clk_cin(self): def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" """Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""

View File

@ -594,7 +594,7 @@ class hierarchical_decoder(design.design):
rotate=90) rotate=90)
def analytical_delay(self, slew, load = 0.0): def analytical_delay(self, corner, slew, load = 0.0):
# A -> out # A -> out
if self.determine_predecodes(self.num_inputs)[1]==0: if self.determine_predecodes(self.num_inputs)[1]==0:
pre = self.pre2_4 pre = self.pre2_4
@ -602,15 +602,15 @@ class hierarchical_decoder(design.design):
else: else:
pre = self.pre3_8 pre = self.pre3_8
nand = self.nand3 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 -> 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()) load = self.inv.input_load())
result = a_t_out_delay + out_t_z_delay result = a_t_out_delay + out_t_z_delay
# Z -> decode_out # 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 result = result + z_t_decodeout_delay
return result return result

View File

@ -51,15 +51,15 @@ class hierarchical_predecode2x4(hierarchical_predecode):
return combination return combination
def analytical_delay(self, slew, load = 0.0 ): def analytical_delay(self, corner, slew, load = 0.0 ):
# in -> inbar # 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 # 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 # 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 return a_t_b_delay + b_t_z_delay + a_t_out_delay

View File

@ -60,15 +60,15 @@ class hierarchical_predecode3x8(hierarchical_predecode):
return combination return combination
def analytical_delay(self, slew, load = 0.0 ): def analytical_delay(self, corner, slew, load = 0.0 ):
# A -> Abar # 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 # 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 # 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 return a_t_b_delay + b_t_z_delay + a_t_out_delay

View File

@ -816,19 +816,19 @@ class multibank(design.design):
offset=in_pin + self.m2m3_via_offset, offset=in_pin + self.m2m3_via_offset,
rotate=90) rotate=90)
def analytical_delay(self, slew, load): def analytical_delay(self, corner, slew, load):
""" return analytical delay of the bank""" """ 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()) self.bitcell_array.output_load())
# output load of bitcell_array is set to be only small part of bl for sense amp. # 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 result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay
return result return result

View File

@ -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. 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 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 from tech import spice
r = spice["min_tx_r"]/(10) r = spice["min_tx_r"]/(10)
c_para = spice["min_tx_drain_c"] 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) return self.return_delay(result.delay, result.slew)
def analytical_power(self, proc, vdd, temp, load): def analytical_power(self, proc, vdd, temp, load):

View File

@ -136,8 +136,8 @@ class sense_amp_array(design.design):
def input_load(self): def input_load(self):
return self.amp.input_load() return self.amp.input_load()
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, corner, slew, load=0.0):
return self.amp.analytical_delay(slew=slew, load=load) return self.amp.analytical_delay(corner, slew=slew, load=load)
def get_en_cin(self): def get_en_cin(self):
"""Get the relative capacitance of all the sense amp enable connections in the array""" """Get the relative capacitance of all the sense amp enable connections in the array"""

View File

@ -216,13 +216,14 @@ class single_level_column_mux_array(design.design):
offset= br_out_offset, offset= br_out_offset,
rotate=90) 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 from tech import spice, parameter
proc,volt,temp = corner
r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"]) r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"])
#Drains of mux transistors make up capacitance. #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 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) return self.return_delay(result.delay, result.slew)

View File

@ -27,11 +27,11 @@ class tri_gate(design.design):
self.height = tri_gate.height self.height = tri_gate.height
self.pin_map = tri_gate.pin_map 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 from tech import spice
r = spice["min_tx_r"] r = spice["min_tx_r"]
c_para = spice["min_tx_drain_c"] 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): def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""

View File

@ -116,6 +116,6 @@ class tri_gate_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, corner, slew, load=0.0):
return self.tri.analytical_delay(slew = slew, load = load) return self.tri.analytical_delay(corner, slew = slew, load = load)

View File

@ -210,12 +210,12 @@ class wordline_driver(design.design):
end=wl_offset-vector(self.m1_width,0)) 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 -> 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 -> 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 return decode_t_net + net_t_wl

View File

@ -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 """ """ Calculate the analytical delay of DFF-> INV -> INV """
nand_delay = selfnand.analytical_delay(slew=slew, load=self.inv.input_load()) nand_delay = self.nand.analytical_delay(corner, slew=slew, load=self.inv.input_load())
inv_delay = self.inv.analytical_delay(slew=nand_delay.slew, load=load) inv_delay = self.inv.analytical_delay(corner, slew=nand_delay.slew, load=load)
return nand_delay + inv_delay return nand_delay + inv_delay
def get_stage_efforts(self, external_cout, inp_is_rise=False): def get_stage_efforts(self, external_cout, inp_is_rise=False):

View File

@ -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 """ """ Calculate the analytical delay of DFF-> INV -> INV """
inv1_delay = self.inv1.analytical_delay(slew=slew, load=self.inv2.input_load()) inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load())
inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load)
return inv1_delay + inv2_delay return inv1_delay + inv2_delay
def get_stage_efforts(self, external_cout, inp_is_rise=False): def get_stage_efforts(self, external_cout, inp_is_rise=False):

View File

@ -172,7 +172,7 @@ class pdriver(pgate.pgate):
def input_load(self): def input_load(self):
return self.inv_list[0].input_load() 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""" """Calculate the analytical delay of INV1 -> ... -> INVn"""
cout_list = [] cout_list = []
@ -184,7 +184,7 @@ class pdriver(pgate.pgate):
delays = [] delays = []
for inv,cout in zip(self.inv_list,cout_list): 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 input_slew = delays[-1].slew
delay = delays[0] delay = delays[0]

View File

@ -261,10 +261,10 @@ class pinv(pgate.pgate):
def input_load(self): def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] 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"]) 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 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): def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""

View File

@ -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 """ """ Calculate the analytical delay of DFF-> INV -> INV """
inv1_delay = self.inv1.analytical_delay(slew=slew, load=self.inv2.input_load()) inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load())
inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load)
return inv1_delay + inv2_delay return inv1_delay + inv2_delay
def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False): def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False):

View File

@ -227,10 +227,10 @@ class pnand2(pgate.pgate):
def input_load(self): def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] 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"]) 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 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): def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""

View File

@ -240,10 +240,10 @@ class pnand3(pgate.pgate):
def input_load(self): def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] 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"]) 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 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): def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""

View File

@ -212,10 +212,10 @@ class pnor2(pgate.pgate):
def input_load(self): def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] 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"]) 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 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): def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW""" """Returns dynamic and leakage power. Results in nW"""

View File

@ -499,9 +499,9 @@ class sram_base(design, verilog, lef):
sp.close() 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. """ """ 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): 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""" """Get the all the stage efforts for each stage in the path from clk_buf to a wordline"""

View File

@ -300,6 +300,8 @@ spice["channel"] = drc["minlength_channel"]
spice["clk"] = "clk" spice["clk"] = "clk"
# analytical delay parameters # 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["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_r"] = 0.075 # Unit wire resistance in ohms/square
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2

View File

@ -240,6 +240,8 @@ spice["clk"] = "clk"
# analytical delay parameters # analytical delay parameters
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. # 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["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_r"] = 0.075 # Unit wire resistance in ohms/square
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2

View File

@ -266,6 +266,8 @@ spice["clk"] = "clk"
# analytical delay parameters # analytical delay parameters
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. # 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["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_r"] = 0.075 # Unit wire resistance in ohms/square
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2