Made all cin function relate to farads and all input_load relate to relative units.

This commit is contained in:
Hunter Nichols 2019-08-08 01:57:04 -07:00
parent 6860d3258e
commit fc1cba099c
17 changed files with 102 additions and 85 deletions

View File

@ -104,7 +104,8 @@ class timing_graph():
if len(path) == 0:
return []
delays = []
delays = []
cur_slew = slew
for i in range(len(path)-1):
path_edge_mod = self.edge_mods[(path[i], path[i+1])]
@ -112,14 +113,14 @@ class timing_graph():
# On the output of the current stage, get COUT from all other mods connected
cout = 0
for node in self.graph[path[i+1]]:
output_edge_mode = self.edge_mods[(path[i+1], node)]
cout+=output_edge_mode.input_load()
output_edge_mod = self.edge_mods[(path[i+1], node)]
cout+=output_edge_mod.get_cin()
# If at the last output, include the final output load
if i == len(path)-2:
cout+=load
delays.append(path_edge_mod.analytical_delay(corner, slew, cout))
slew = delays[-1].slew
cur_slew = delays[-1].slew
return delays

View File

@ -304,6 +304,8 @@ class spice():
def analytical_delay(self, corner, slew, load=0.0):
"""Inform users undefined delay module while building new modules"""
# FIXME: Slew is not used in the model right now. Can be added heuristically as linear factor
relative_cap = logical_effort.convert_farad_to_relative_c(load)
stage_effort = self.get_stage_effort(relative_cap)
@ -326,6 +328,24 @@ class spice():
self.name))
return None
def get_cin(self):
"""Returns input load in Femto-Farads. All values generated using
relative capacitance function then converted based on tech file parameter."""
# Override this function within a module if a more accurate input capacitance is needed.
# Input/outputs with differing capacitances is not implemented.
relative_cap = self.input_load()
return logical_effort.convert_relative_c_to_farad(relative_cap)
def input_load(self):
"""Inform users undefined relative capacitance functions used for analytical delays."""
debug.warning("Design Class {0} input capacitance function needs to be defined"
.format(self.__class__.__name__))
debug.warning("Class {0} name {1}"
.format(self.__class__.__name__,
self.name))
return 0
def cal_delay_with_rc(self, corner, r, c ,slew, swing = 0.5):
"""
Calculate the delay of a mosfet by

View File

@ -42,16 +42,6 @@ class bitcell(design.design):
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False)
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
#FIXME: The graph algorithm will apply this capacitance to the bitline load as they cannot be
# distinguished currently
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin
def get_all_wl_names(self):
""" Creates a list of all wordline pin names """
row_pins = ["wl"]
@ -104,10 +94,10 @@ class bitcell(design.design):
debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets))
return None
def get_wl_cin(self):
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
# FIXME: This applies to bitline capacitances as well.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin

View File

@ -36,7 +36,7 @@ class bitcell_1rw_1r(design.design):
self.add_pin_types(self.type_list)
self.nets_match = self.do_nets_exist(self.storage_nets)
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
@ -118,11 +118,11 @@ class bitcell_1rw_1r(design.design):
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
# FIXME: This applies to bitline capacitances as well.
# FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin

View File

@ -36,7 +36,7 @@ class bitcell_1w_1r(design.design):
self.add_pin_types(self.type_list)
self.nets_match = self.do_nets_exist(self.storage_nets)
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
@ -116,11 +116,11 @@ class bitcell_1w_1r(design.design):
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
# FIXME: This applies to bitline capacitances as well.
# FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin

View File

@ -934,7 +934,7 @@ class pbitcell(design.design):
return "wl{}".format(port)
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
@ -954,9 +954,11 @@ class pbitcell(design.design):
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#pbitcell uses the different sizing for the port access tx's. Not accounted for in this model.
# FIXME: This applies to bitline capacitances as well.
# pbitcell uses the different sizing for the port access tx's. Not accounted for in this model.
access_tx_cin = self.readwrite_nmos.get_cin()
return 2*access_tx_cin

View File

@ -31,6 +31,20 @@ class replica_bitcell(design.design):
self.height = replica_bitcell.height
self.pin_map = replica_bitcell.pin_map
self.add_pin_types(self.type_list)
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
read_port_load = 0.5 #min size NMOS gate load
return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False)
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
# FIXME: This applies to bitline capacitances as well.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin
def analytical_power(self, corner, load):
"""Bitcell power in nW. Only characterizes leakage."""
@ -40,13 +54,6 @@ class replica_bitcell(design.design):
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin
def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function."""
self.add_graph_edges(graph, port_nets)

View File

@ -32,11 +32,18 @@ class replica_bitcell_1rw_1r(design.design):
self.pin_map = replica_bitcell_1rw_1r.pin_map
self.add_pin_types(self.type_list)
def get_wl_cin(self):
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
read_port_load = 0.5 #min size NMOS gate load
return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False)
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
# FIXME: This applies to bitline capacitances as well.
# FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin
@ -49,5 +56,5 @@ class replica_bitcell_1rw_1r(design.design):
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self)
graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self)
# Port 1 edges
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"])
graph.add_edge(pin_dict["wl1"], pin_dict["br1"])
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self)
graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self)

View File

@ -32,11 +32,18 @@ class replica_bitcell_1w_1r(design.design):
self.pin_map = replica_bitcell_1w_1r.pin_map
self.add_pin_types(self.type_list)
def get_wl_cin(self):
def get_stage_effort(self, load):
parasitic_delay = 1
size = 0.5 #This accounts for bitline being drained thought the access TX and internal node
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
read_port_load = 0.5 #min size NMOS gate load
return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False)
def input_load(self):
"""Return the relative capacitance of the access transistor gates"""
#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 related gates and dividing by the minimum width.
#FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
# FIXME: This applies to bitline capacitances as well.
# FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin

View File

@ -84,8 +84,4 @@ class replica_pbitcell(design.design):
self.copy_layout_pin(self.prbc_inst, "wl{}".format(port))
self.copy_layout_pin(self.prbc_inst, "vdd")
self.copy_layout_pin(self.prbc_inst, "gnd")
def get_wl_cin(self):
"""Return the relative capacitance of the access transistor gates"""
#This module is made using a pbitcell. Get the cin from that module
return self.prbc.get_wl_cin()

View File

@ -23,23 +23,23 @@ class logical_effort():
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.electrical_effort = self.cout/self.cin
self.parasitic_scale = parasitic
self.is_rise = out_is_rise
def __str__(self):
return "Name={}, g={}, h={}, p={}*pinv, rise_delay={}".format(self.name,
self.logical_effort,
self.eletrical_effort,
self.electrical_effort,
self.parasitic_scale,
self.is_rise
)
def get_stage_effort(self):
return self.logical_effort*self.eletrical_effort
return self.logical_effort*self.electrical_effort
def get_parasitic_delay(self):
return logical_effort.pinv * self.parasitic_scale
return logical_effort.pinv*self.parasitic_scale
def get_stage_delay(self):
return self.get_stage_effort()+self.get_parasitic_delay()
@ -78,4 +78,7 @@ def calculate_relative_rise_fall_delays(stage_effort_list):
def convert_farad_to_relative_c(c_farad):
"""Converts capacitance in Femto-Farads to relative capacitance."""
return c_farad*parameter['cap_relative_per_ff']
def convert_relative_c_to_farad(c_relative):
"""Converts capacitance in logical effort relative units to Femto-Farads."""
return c_relative/parameter['cap_relative_per_ff']

View File

@ -33,7 +33,10 @@ class sense_amp(design.design):
self.pin_map = sense_amp.pin_map
self.add_pin_types(self.type_list)
def input_load(self):
def get_cin(self):
# FIXME: This input load will be applied to both the s_en timing and bitline timing.
#Input load for the bitlines which are connected to the source/drain of a TX. Not the selects.
from tech import spice, parameter
# Default is 8x. Per Samira and Hodges-Jackson book:

View File

@ -12,7 +12,7 @@ from tech import GDS,layer
class tri_gate(design.design):
"""
This module implements the tri gate cell used in the design for
This module implements the tri gate cell used in the design forS
bit-line isolation. It is a hand-made cell, so the layout and
netlist should be available in the technology library.
"""
@ -42,7 +42,7 @@ class tri_gate(design.design):
total_power = self.return_power()
return total_power
def input_load(self):
def get_cin(self):
return 9*spice["min_tx_gate_c"]
def build_graph(self, graph, inst_name, port_nets):

View File

@ -272,11 +272,6 @@ class pinv(pgate.pgate):
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 input_load(self):
"""Return the capacitance of the gate connection in generic capacitive
units relative to the minimum width of a transistor"""
@ -289,7 +284,7 @@ class pinv(pgate.pgate):
parasitic_delay = 1
return logical_effort.logical_effort(self.name,
self.size,
self.get_cin(),
self.input_load(),
cout,
parasitic_delay,
not inp_is_rise)

View File

@ -37,10 +37,7 @@ class pnand2(pgate.pgate):
# Creates the netlist and layout
pgate.pgate.__init__(self, name, height)
#For characterization purposes only
#self.exclude_nmos_from_graph()
def create_netlist(self):
self.add_pins()
self.add_ptx()
@ -250,10 +247,6 @@ class pnand2(pgate.pgate):
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 input_load(self):
"""Return the relative input capacitance of a single input"""
return self.nmos_size+self.pmos_size
@ -263,14 +256,7 @@ class pnand2(pgate.pgate):
Optional is_rise refers to the input direction rise/fall. Input inverted by this stage.
"""
parasitic_delay = 2
return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
def exclude_nmos_from_graph(self):
"""Exclude the nmos TXs from the graph to reduce complexity"""
#The pull-down network has an internal net which causes 2 different in->out paths
#Removing them simplifies generic path searching.
self.graph_inst_exclude.add(self.nmos1_inst)
self.graph_inst_exclude.add(self.nmos2_inst)
return logical_effort.logical_effort(self.name, self.size, self.input_load(), cout, parasitic_delay, not inp_is_rise)
def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function."""

View File

@ -260,7 +260,7 @@ class pnand3(pgate.pgate):
transition_prob = spice["nand3_transition_prob"]
return transition_prob*(c_load + c_para)
def get_cin(self):
def input_load(self):
"""Return the relative input capacitance of a single input"""
return self.nmos_size+self.pmos_size
@ -269,7 +269,7 @@ class pnand3(pgate.pgate):
Optional is_rise refers to the input direction rise/fall. Input inverted by this stage.
"""
parasitic_delay = 3
return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise)
return logical_effort.logical_effort(self.name, self.size, self.input_load(), cout, parasitic_delay, not inp_is_rise)
def build_graph(self, graph, inst_name, port_nets):
"""Adds edges based on inputs/outputs. Overrides base class function."""

View File

@ -216,5 +216,5 @@ class ptristate_inv(pgate.pgate):
total_power = self.return_power()
return total_power
def input_load(self):
def get_cin(self):
return 9*spice["min_tx_gate_c"]