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 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"]
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
###################################################
|
###################################################
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
###################################################
|
###################################################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue