diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index 8a6588af..5d1ee692 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -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 diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index c8ffb151..5166ac6b 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -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 diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 360e08de..cad069a5 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -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 diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 42bd3855..0d536b38 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -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 diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index b8f0e49b..7e8c9e75 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -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 diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index b09e81c2..919a0316 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -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 diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index f8ded969..2f804bf0 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -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) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 9737669d..0f56319e 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -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"]) \ No newline at end of file + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index fad5032d..b903e0ad 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -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 diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index 8453411f..4fcfb4c5 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -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() + \ No newline at end of file diff --git a/compiler/characterizer/logical_effort.py b/compiler/characterizer/logical_effort.py index 024cd4f1..42ac8861 100644 --- a/compiler/characterizer/logical_effort.py +++ b/compiler/characterizer/logical_effort.py @@ -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'] - \ No newline at end of file + +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'] \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index a053aff8..8c92440c 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -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: diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index fe59e7b9..998562b1 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -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): diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index d841b318..0844c762 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -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) diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 2275a336..21ca4184 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -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.""" diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index eee6ca9a..89628267 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -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.""" diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 3176915a..0564bf86 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -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"]