Added initial code for determining the logical effort delay of the wordline.

This commit is contained in:
Hunter Nichols 2018-11-08 00:10:51 -08:00
parent 455ef7ef99
commit b8061d3a4e
16 changed files with 174 additions and 6 deletions

View File

@ -1,7 +1,7 @@
import design import design
import debug import debug
import utils import utils
from tech import GDS,layer from tech import GDS,layer, parameter
class bitcell(design.design): class bitcell(design.design):
""" """
@ -93,3 +93,8 @@ class bitcell(design.design):
total_power = self.return_power(dynamic, leakage) total_power = self.return_power(dynamic, leakage)
return total_power return total_power
def get_wl_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
#Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width.
return parameter["6tcell_wl_cin"]

View File

@ -0,0 +1,16 @@
import debug
from tech import drc, parameter, spice
class logical_effort():
"""
Class to support the values behind logical effort. Useful for storing the different components
such as logical effort, electrical effort, and parasitic delay.
"""
beta = parameter["beta"]
min_inv_cin = 1+beta
def __init__(self, size, cin, cout, parasitic):
self.cin = cin
self.cout = cout
self.logical_effort = (self.cin/size)/logical_effort.min_inv_cin
self.eletrical_effort = self.cout/self.cin
self.parasitic = parasitic

View File

@ -950,4 +950,18 @@ class bank(design.design):
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)
return results return results
def determine_wordline_stage_efforts(self, external_cout):
"""Get the all the stage efforts for each stage in the path within the bank clk_buf to a wordline"""
#Decoder is assumed to have settled before the negative edge of the clock. Delay model relies on this assumption
stage_effort_list = []
wordline_cout = self.bitcell_array.get_wordline_cin() + external_cout
stage_effort_list += self.wordline_driver.determine_wordline_stage_efforts(wordline_cout)
return stage_effort_list
def get_clk_cin(self):
"""Get the relative capacitance of all the clk connections in the bank"""
#Current bank only uses clock (clk_buf) as an enable for the wordline driver.
total_clk_cin = self.wordline_driver.get_clk_cin()
return total_clk_cin

View File

@ -225,3 +225,10 @@ class bitcell_array(design.design):
def input_load(self): def input_load(self):
wl_wire = self.gen_wl_wire() wl_wire = self.gen_wl_wire()
return wl_wire.return_input_cap() return wl_wire.return_input_cap()
def get_wordline_cin(self):
"""Get the relative input capacitance from the wordline connections in all the bitcell"""
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
bitcell_wl_cin = self.cell.get_wl_cin()
total_cin = bitcell_wl_cin * self.column_size
return total_cin

View File

@ -596,4 +596,14 @@ class control_logic(design.design):
height=pin.height(), height=pin.height(),
width=pin.width()) width=pin.width())
def determine_wordline_stage_efforts(self, external_cout):
"""Follows the clock signal to the clk_buf signal adding each stages stage effort to a list"""
stage_effort_list = []
#Calculate the load on clk_buf within the module and add it to external load
internal_cout = self.ctrl_dff_array.get_clk_cin()
clk_buf_cap = internal_cout+external_cout
#First stage is the clock buffer
stage_effort_list += self.clkbuf.determine_wordline_stage_efforts(clk_buf_cap)
return stage_effort_list

View File

@ -2,7 +2,7 @@ import globals
import design import design
from math import log from math import log
import design import design
from tech import GDS,layer from tech import GDS,layer,spice,parameter
import utils import utils
class dff(design.design): class dff(design.design):
@ -23,7 +23,6 @@ class dff(design.design):
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"""
from tech import spice
c_eff = self.calculate_effective_capacitance(load) c_eff = self.calculate_effective_capacitance(load)
f = spice["default_event_rate"] f = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*f power_dyn = c_eff*vdd*vdd*f
@ -34,7 +33,7 @@ class dff(design.design):
def calculate_effective_capacitance(self, load): def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF""" """Computes effective capacitance. Results in fF"""
from tech import spice, parameter from tech import parameter
c_load = load c_load = load
c_para = spice["flop_para_cap"]#ff c_para = spice["flop_para_cap"]#ff
transition_prob = spice["flop_transition_prob"] transition_prob = spice["flop_transition_prob"]
@ -42,7 +41,12 @@ class dff(design.design):
def analytical_delay(self, slew, load = 0.0): def analytical_delay(self, 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
from tech import spice
result = self.return_delay(spice["dff_delay"], spice["dff_slew"]) result = self.return_delay(spice["dff_delay"], spice["dff_slew"])
return result return result
def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
#Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width.
return parameter["dff_clk_cin"]

View File

@ -157,3 +157,9 @@ class dff_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, 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):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
dff_clk_cin = self.dff.get_clk_cin()
total_cin = dff_clk_cin * self.rows * self.columns
return total_cin

View File

@ -148,3 +148,6 @@ class dff_inv(design.design):
inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=load) inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=load)
return dff_delay + inv1_delay return dff_delay + inv1_delay
def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
return self.dff.get_clk_cin()

View File

@ -182,3 +182,9 @@ class dff_inv_array(design.design):
def analytical_delay(self, slew, load=0.0): def analytical_delay(self, 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):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
dff_clk_cin = self.dff.get_clk_cin()
total_cin = dff_clk_cin * self.rows * self.columns
return total_cin

View File

@ -238,4 +238,27 @@ class wordline_driver(design.design):
def input_load(self): def input_load(self):
"""Gets the capacitance of the wordline driver in absolute units (fF)"""
return self.nand2.input_load() return self.nand2.input_load()
def determine_wordline_stage_efforts(self, external_cout):
"""Follows the clk_buf to a wordline signal adding each stages stage effort to a list"""
stage_effort_list = []
stage1_cout = self.nand2.get_cin()
stage1 = self.inv_no_output.get_effort_stage(stage1_cout)
stage_effort_list.append(stage1)
stage2_cout = self.inv.get_cin()
stage2 = self.nand2.get_effort_stage(stage2_cout)
stage_effort_list.append(stage2)
stage3 = self.inv.get_effort_stage(external_cout)
stage_effort_list.append(stage3)
return stage_effort_list
def get_clk_cin(self):
"""Get the relative capacitance of all the clk connections in the bank"""
#Clock is connected as an input to 1 inverter per row
total_cin = self.inv_no_output.get_cin() * self.rows
return total_cin

View File

@ -7,6 +7,7 @@ from vector import vector
from math import ceil from math import ceil
from globals import OPTS from globals import OPTS
from utils import round_to_grid from utils import round_to_grid
import logical_effort
class pinv(pgate.pgate): class pinv(pgate.pgate):
""" """
@ -29,7 +30,8 @@ class pinv(pgate.pgate):
pinv.unique_id += 1 pinv.unique_id += 1
pgate.pgate.__init__(self, name, height) pgate.pgate.__init__(self, name, height)
debug.info(2, "create pinv structure {0} with size of {1}".format(name, size)) debug.info(2, "create pinv structure {0} with size of {1}".format(name, size))
self.size = size
self.nmos_size = size self.nmos_size = size
self.pmos_size = beta*size self.pmos_size = beta*size
self.beta = beta self.beta = beta
@ -281,3 +283,12 @@ class pinv(pgate.pgate):
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
transition_prob = spice["inv_transition_prob"] transition_prob = spice["inv_transition_prob"]
return transition_prob*(c_load + c_para) return transition_prob*(c_load + c_para)
def get_cin(self):
"""Return the capacitance of the gate connection in generic capacitive units relative to the minimum width of a transistor"""
return self.nmos_size + self.pmos_size
def get_effort_stage(self, cout):
"""Returns an object representing the parameters for delay in tau units."""
parasitic_delay = 1
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay)

View File

@ -187,3 +187,14 @@ class pinvbuf(design.design):
inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load)
return inv1_delay + inv2_delay return inv1_delay + inv2_delay
def determine_wordline_stage_efforts(self, external_cout):
"""Get the stage efforts of the clk -> clk_buf path"""
stage_effort_list = []
stage1_cout = self.inv1.get_cin() + self.inv2.get_cin()
stage1 = self.inv.get_effort_stage(stage1_cout)
stage_effort_list.append(stage1)
stage2 = self.inv2.get_effort_stage(external_cout)
stage_effort_list.append(stage2)
return stage_effort_list

View File

@ -5,6 +5,7 @@ from tech import drc, parameter, spice
from ptx import ptx from ptx import ptx
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
import logical_effort
class pnand2(pgate.pgate): class pnand2(pgate.pgate):
""" """
@ -21,6 +22,7 @@ class pnand2(pgate.pgate):
pgate.pgate.__init__(self, name, height) pgate.pgate.__init__(self, name, height)
debug.info(2, "create pnand2 structure {0} with size of {1}".format(name, size)) debug.info(2, "create pnand2 structure {0} with size of {1}".format(name, size))
self.size = size
self.nmos_size = 2*size self.nmos_size = 2*size
self.pmos_size = parameter["beta"]*size self.pmos_size = parameter["beta"]*size
self.nmos_width = self.nmos_size*drc("minwidth_tx") self.nmos_width = self.nmos_size*drc("minwidth_tx")
@ -242,3 +244,12 @@ class pnand2(pgate.pgate):
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
transition_prob = spice["nand2_transition_prob"] transition_prob = spice["nand2_transition_prob"]
return transition_prob*(c_load + c_para) return transition_prob*(c_load + c_para)
def get_cin(self):
"""Return the relative input capacitance of a single input"""
return self.nmos_size+self.pmos_size
def get_effort_stage(self, cout):
"""Returns an object representing the parameters for delay in tau units."""
parasitic_delay = 2
return logical_effort.logical_effort(self.size, self.get_cin(), cout, parasitic_delay)

View File

@ -455,4 +455,36 @@ class sram_base(design):
""" 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(vdd,slew,load)
def calculate_delay_to_wl(self):
stage_efforts = self.determine_wordline_stage_efforts()
return 0
def determine_wordline_stage_efforts(self):
"""Get the all the stage efforts for each stage in the path from clk to a wordline"""
stage_effort_list = []
clk_buf_cout = self.get_clk_cin()
#Assume rw only. There are important differences with multiport that will need to be accounted for.
if self.control_logic_rw != None:
stage_effort_list += self.control_logic_rw.determine_wordline_stage_efforts(clk_buf_cout)
else:
stage_effort_list += self.control_logic_r.determine_wordline_stage_efforts(clk_buf_cout)
#Clk_buf then move to the bank/wordline driver. Get the delay stages there.
external_wordline_cout = 0 #No loading on the wordline other than in the bank.
stage_effort_list += self.bank.determine_wordline_stage_efforts(external_wordline_cout)
return stage_effort_list
def get_clk_cin(self):
"""Gets the capacitive load the of clock (clk_buf) for the sram"""
#As clk_buf is an output of the control logic. The cap for that module is not determined here.
row_addr_clk_cin = self.row_addr_dff.get_clk_cin()
data_clk_cin = self.data_dff.get_clk_cin()
col_addr_clk_cin = 0
if self.col_addr_size > 0:
col_addr_clk_cin = self.col_addr_dff.get_clk_cin()
#Bank cin...
bank_clk_cin = self.bank.get_clk_cin()
return row_addr_clk_cin + data_clk_cin + col_addr_clk_cin + bank_clk_cin

View File

@ -328,6 +328,10 @@ spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input na
spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand.
spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor.
#Logical Effort relative values for the Handmade cells
spice["dff_clk_cin"] = 30.6
parameter["6tcell_wl_cin"] = 3
################################################### ###################################################
##END Spice Simulation Parameters ##END Spice Simulation Parameters
################################################### ###################################################

View File

@ -293,6 +293,11 @@ spice["inv_transition_prob"] = .5 # Transition probability of inverter.
spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand. spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand.
spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand.
spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor.
#Logical Effort relative values for the Handmade cells
parameter["dff_clk_cin"] = 27.5
parameter["6tcell_wl_cin"] = 2
################################################### ###################################################
##END Spice Simulation Parameters ##END Spice Simulation Parameters
################################################### ###################################################