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 debug
import utils
from tech import GDS,layer
from tech import GDS,layer, parameter
class bitcell(design.design):
"""
@ -93,3 +93,8 @@ class bitcell(design.design):
total_power = self.return_power(dynamic, leakage)
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)
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):
wl_wire = self.gen_wl_wire()
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(),
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
from math import log
import design
from tech import GDS,layer
from tech import GDS,layer,spice,parameter
import utils
class dff(design.design):
@ -23,7 +23,6 @@ class dff(design.design):
def analytical_power(self, proc, vdd, temp, load):
"""Returns dynamic and leakage power. Results in nW"""
from tech import spice
c_eff = self.calculate_effective_capacitance(load)
f = spice["default_event_rate"]
power_dyn = c_eff*vdd*vdd*f
@ -34,7 +33,7 @@ class dff(design.design):
def calculate_effective_capacitance(self, load):
"""Computes effective capacitance. Results in fF"""
from tech import spice, parameter
from tech import parameter
c_load = load
c_para = spice["flop_para_cap"]#ff
transition_prob = spice["flop_transition_prob"]
@ -42,7 +41,12 @@ class dff(design.design):
def analytical_delay(self, slew, load = 0.0):
# 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"])
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):
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)
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):
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):
"""Gets the capacitance of the wordline driver in absolute units (fF)"""
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 globals import OPTS
from utils import round_to_grid
import logical_effort
class pinv(pgate.pgate):
"""
@ -29,7 +30,8 @@ class pinv(pgate.pgate):
pinv.unique_id += 1
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pinv structure {0} with size of {1}".format(name, size))
self.size = size
self.nmos_size = size
self.pmos_size = beta*size
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
transition_prob = spice["inv_transition_prob"]
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)
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 vector import vector
from globals import OPTS
import logical_effort
class pnand2(pgate.pgate):
"""
@ -21,6 +22,7 @@ class pnand2(pgate.pgate):
pgate.pgate.__init__(self, name, height)
debug.info(2, "create pnand2 structure {0} with size of {1}".format(name, size))
self.size = size
self.nmos_size = 2*size
self.pmos_size = parameter["beta"]*size
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
transition_prob = spice["nand2_transition_prob"]
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. """
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["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
###################################################

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["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand.
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
###################################################