mirror of https://github.com/VLSIDA/OpenRAM.git
Added initial code for determining the logical effort delay of the wordline.
This commit is contained in:
parent
455ef7ef99
commit
b8061d3a4e
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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"]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
###################################################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
###################################################
|
||||
|
|
|
|||
Loading…
Reference in New Issue