Lots of PEP8 cleanup. Refactor path graph to simulation class.

This commit is contained in:
mrg 2020-09-29 10:26:31 -07:00
parent 1eb8798bb6
commit d7e2340e62
13 changed files with 305 additions and 275 deletions

View File

@ -12,6 +12,7 @@ import os
from globals import OPTS from globals import OPTS
import tech import tech
class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
""" """
Design Class for all modules to inherit the base features. Design Class for all modules to inherit the base features.
@ -137,12 +138,16 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
os.remove(tempgds) os.remove(tempgds)
def init_graph_params(self): def init_graph_params(self):
"""Initializes parameters relevant to the graph creation""" """
Initializes parameters relevant to the graph creation
"""
# Only initializes a set for checking instances which should not be added # Only initializes a set for checking instances which should not be added
self.graph_inst_exclude = set() self.graph_inst_exclude = set()
def build_graph(self, graph, inst_name, port_nets): def build_graph(self, graph, inst_name, port_nets):
"""Recursively create graph from instances in module.""" """
Recursively create graph from instances in module.
"""
# Translate port names to external nets # Translate port names to external nets
if len(port_nets) != len(self.pins): if len(port_nets) != len(self.pins):
@ -159,7 +164,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
subinst.mod.build_graph(graph, subinst_name, subinst_ports) subinst.mod.build_graph(graph, subinst_name, subinst_ports)
def build_names(self, name_dict, inst_name, port_nets): def build_names(self, name_dict, inst_name, port_nets):
"""Collects all the nets and the parent inst of that net.""" """
Collects all the nets and the parent inst of that net.
"""
# Translate port names to external nets # Translate port names to external nets
if len(port_nets) != len(self.pins): if len(port_nets) != len(self.pins):
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets, debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,
@ -178,7 +185,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
subinst.mod.build_names(name_dict, subinst_name, subinst_ports) subinst.mod.build_names(name_dict, subinst_name, subinst_ports)
def translate_nets(self, subinst_ports, port_dict, inst_name): def translate_nets(self, subinst_ports, port_dict, inst_name):
"""Converts connection names to their spice hierarchy equivalent""" """
Converts connection names to their spice hierarchy equivalent
"""
converted_conns = [] converted_conns = []
for conn in subinst_ports: for conn in subinst_ports:
if conn in port_dict: if conn in port_dict:
@ -188,8 +197,10 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
return converted_conns return converted_conns
def add_graph_edges(self, graph, port_nets): def add_graph_edges(self, graph, port_nets):
"""For every input, adds an edge to every output. """
Only intended to be used for gates and other simple modules.""" For every input, adds an edge to every output.
Only intended to be used for gates and other simple modules.
"""
# The final pin names will depend on the spice hierarchy, so # The final pin names will depend on the spice hierarchy, so
# they are passed as an input. # they are passed as an input.
pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}

View File

@ -500,7 +500,8 @@ class spice():
return power_data(dynamic, leakage) return power_data(dynamic, leakage)
def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None): def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None):
"""Given a list of nets, will compare the internal alias of a mod to determine """
Given a list of nets, will compare the internal alias of a mod to determine
if the nets have a connection to this mod's net (but not inst). if the nets have a connection to this mod's net (but not inst).
""" """
if not exclusion_set: if not exclusion_set:
@ -520,7 +521,9 @@ class spice():
return aliases return aliases
def is_net_alias(self, known_net, net_alias, mod, exclusion_set): def is_net_alias(self, known_net, net_alias, mod, exclusion_set):
"""Checks if the alias_net in input mod is the same as the input net for this mod (self).""" """
Checks if the alias_net in input mod is the same as the input net for this mod (self).
"""
if self in exclusion_set: if self in exclusion_set:
return False return False
# Check ports of this mod # Check ports of this mod
@ -540,7 +543,9 @@ class spice():
return False return False
def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod): def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod):
"""Utility function for checking single net alias.""" """
Utility function for checking single net alias.
"""
return self == mod and \ return self == mod and \
child_net.lower() == alias_net.lower() and \ child_net.lower() == alias_net.lower() and \
parent_net.lower() == alias_net.lower() parent_net.lower() == alias_net.lower()

View File

@ -5,7 +5,7 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
import sys,re,shutil,copy import shutil
import debug import debug
import tech import tech
import math import math
@ -14,13 +14,10 @@ from .trim_spice import *
from .charutils import * from .charutils import *
from .sram_op import * from .sram_op import *
from .bit_polarity import * from .bit_polarity import *
import utils
from globals import OPTS from globals import OPTS
from .simulation import simulation from .simulation import simulation
from .measurements import * from .measurements import *
import logical_effort
import graph_util
from sram_factory import factory
class delay(simulation): class delay(simulation):
""" """
@ -253,45 +250,6 @@ class delay(simulation):
self.load = load self.load = load
self.slew = slew self.slew = slew
def create_graph(self):
"""Creates timing graph to generate the timing paths for the SRAM output."""
self.sram.bank.bitcell_array.bitcell_array.init_graph_params() # Removes previous bit exclusions
self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column)
# Generate new graph every analysis as edges might change depending on test bit
self.graph = graph_util.timing_graph()
self.sram_spc_name = "X{}".format(self.sram.name)
self.sram.build_graph(self.graph,self.sram_spc_name,self.pins)
def get_bl_name_search_exclusions(self):
"""Gets the mods as a set which should be excluded while searching for name."""
# Exclude the RBL as it contains bitcells which are not in the main bitcell array
# so it makes the search awkward
return set(factory.get_mods(OPTS.replica_bitline))
def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None):
"""
Finds a single alias for the int_net in given paths.
More or less hits cause an error
"""
net_found = False
for path in paths:
aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, int_net, mod, exclusion_set)
if net_found and len(aliases) >= 1:
debug.error('Found multiple paths with {} net.'.format(int_net),1)
elif len(aliases) > 1:
debug.error('Found multiple {} nets in single path.'.format(int_net),1)
elif not net_found and len(aliases) == 1:
path_net_name = aliases[0]
net_found = True
if not net_found:
debug.error("Could not find {} net in timing paths.".format(int_net),1)
return path_net_name
def check_arguments(self): def check_arguments(self):
"""Checks if arguments given for write_stimulus() meets requirements""" """Checks if arguments given for write_stimulus() meets requirements"""
@ -333,7 +291,6 @@ class delay(simulation):
for i in range(self.word_size): for i in range(self.word_size):
self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port, i, self.dout_name, self.load)) self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port, i, self.dout_name, self.load))
def write_delay_stimulus(self): def write_delay_stimulus(self):
""" """
Creates a stimulus file for simulations to probe a bitcell at a given clock period. Creates a stimulus file for simulations to probe a bitcell at a given clock period.
@ -385,7 +342,6 @@ class delay(simulation):
self.sf.close() self.sf.close()
def write_power_stimulus(self, trim): def write_power_stimulus(self, trim):
""" Creates a stimulus file to measure leakage power only. """ Creates a stimulus file to measure leakage power only.
This works on the *untrimmed netlist*. This works on the *untrimmed netlist*.
@ -1282,7 +1238,11 @@ class delay(simulation):
total_delay = self.sum_delays(path_delays) total_delay = self.sum_delays(path_delays)
max_delay = max(max_delay, total_delay.delay) max_delay = max(max_delay, total_delay.delay)
debug.info(1,'{}, {}, {}, {}'.format(slew,load,total_delay.delay/1e3, total_delay.slew/1e3)) debug.info(1,
'{}, {}, {}, {}'.format(slew,
load,
total_delay.delay / 1e3,
total_delay.slew / 1e3))
# Delay is only calculated on a single port and replicated for now. # Delay is only calculated on a single port and replicated for now.
for port in self.all_ports: for port in self.all_ports:
@ -1346,7 +1306,6 @@ class delay(simulation):
if port in self.readwrite_ports: if port in self.readwrite_ports:
self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05) self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05)
def get_empty_measure_data_dict(self): def get_empty_measure_data_dict(self):
"""Make a dict of lists for each type of delay and power measurement to append results to""" """Make a dict of lists for each type of delay and power measurement to append results to"""

View File

@ -13,9 +13,6 @@ from .stimuli import *
from .charutils import * from .charutils import *
from globals import OPTS from globals import OPTS
from .simulation import simulation from .simulation import simulation
# from .delay import delay
import graph_util
from sram_factory import factory
class functional(simulation): class functional(simulation):
@ -249,7 +246,8 @@ class functional(simulation):
def check_stim_results(self): def check_stim_results(self):
for i in range(len(self.read_check)): for i in range(len(self.read_check)):
if self.read_check[i][0] != self.read_results[i][0]: if self.read_check[i][0] != self.read_results[i][0]:
error = "FAILED: {0} value {1} does not match written value {2} read during cycle {3} at time {4}n".format(self.read_results[i][1], str = "FAILED: {0} value {1} does not match written value {2} read during cycle {3} at time {4}n"
error = str.format(self.read_results[i][1],
self.read_results[i][0], self.read_results[i][0],
self.read_check[i][0], self.read_check[i][0],
int((self.read_results[i][2] - self.period) / self.period), int((self.read_results[i][2] - self.period) / self.period),
@ -424,19 +422,6 @@ class functional(simulation):
self.stim.write_control(self.cycle_times[-1] + self.period) self.stim.write_control(self.cycle_times[-1] + self.period)
self.sf.close() self.sf.close()
# FIXME: refactor to share with delay.py
def create_graph(self):
"""Creates timing graph to generate the timing paths for the SRAM output."""
self.sram.bank.bitcell_array.init_graph_params() # Removes previous bit exclusions
# Does wordline=0 and column=0 just for debug names
self.sram.bank.bitcell_array.graph_exclude_bits(0, 0)
# Generate new graph every analysis as edges might change depending on test bit
self.graph = graph_util.timing_graph()
self.sram_spc_name = "X{}".format(self.sram.name)
self.sram.build_graph(self.graph, self.sram_spc_name, self.pins)
#FIXME: Similar function to delay.py, refactor this #FIXME: Similar function to delay.py, refactor this
def get_bit_name(self): def get_bit_name(self):
""" Get a bit cell name """ """ Get a bit cell name """
@ -449,31 +434,4 @@ class functional(simulation):
return (q_name, qbar_name) return (q_name, qbar_name)
def get_bl_name_search_exclusions(self):
"""Gets the mods as a set which should be excluded while searching for name."""
# Exclude the RBL as it contains bitcells which are not in the main bitcell array
# so it makes the search awkward
return set(factory.get_mods(OPTS.replica_bitline))
def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None):
"""
Finds a single alias for the int_net in given paths.
More or less hits cause an error
"""
net_found = False
for path in paths:
aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, int_net, mod, exclusion_set)
if net_found and len(aliases) >= 1:
debug.error('Found multiple paths with {} net.'.format(int_net), 1)
elif len(aliases) > 1:
debug.error('Found multiple {} nets in single path.'.format(int_net), 1)
elif not net_found and len(aliases) == 1:
path_net_name = aliases[0]
net_found = True
if not net_found:
debug.error("Could not find {} net in timing paths.".format(int_net), 1)
return path_net_name

View File

@ -5,17 +5,13 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
import sys,re,shutil
from design import design
import debug import debug
import math import math
import tech import tech
from .stimuli import *
from .trim_spice import *
from .charutils import *
import utils
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
import graph_util
class simulation(): class simulation():
@ -147,7 +143,6 @@ class simulation():
debug.error("Non-binary address string", 1) debug.error("Non-binary address string", 1)
bit -= 1 bit -= 1
def add_wmask(self, wmask, port): def add_wmask(self, wmask, port):
""" Add the array of address values """ """ Add the array of address values """
debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.") debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.")
@ -321,7 +316,6 @@ class simulation():
if unselected_port != port: if unselected_port != port:
self.add_noop_one_port(unselected_port) self.add_noop_one_port(unselected_port)
def append_cycle_comment(self, port, comment): def append_cycle_comment(self, port, comment):
"""Add comment to list to be printed in stimulus file""" """Add comment to list to be printed in stimulus file"""
#Clean up time before appending. Make spacing dynamic as well. #Clean up time before appending. Make spacing dynamic as well.
@ -335,7 +329,8 @@ class simulation():
def gen_cycle_comment(self, op, word, addr, wmask, port, t_current): def gen_cycle_comment(self, op, word, addr, wmask, port, t_current):
if op == "noop": if op == "noop":
comment = "\tIdle during cycle {0} ({1}ns - {2}ns)".format(int(t_current/self.period), str = "\tIdle during cycle {0} ({1}ns - {2}ns)"
comment = str.format(int(t_current / self.period),
t_current, t_current,
t_current + self.period) t_current + self.period)
elif op == "write": elif op == "write":
@ -346,7 +341,8 @@ class simulation():
t_current, t_current,
t_current+self.period) t_current+self.period)
elif op == "partial_write": elif op == "partial_write":
comment = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, str = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)"
comment = str.format(word,
addr, addr,
wmask, wmask,
port, port,
@ -354,14 +350,14 @@ class simulation():
t_current, t_current,
t_current + self.period) t_current + self.period)
else: else:
comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, str = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)"
comment = str.format(word,
addr, addr,
port, port,
int(t_current / self.period), int(t_current / self.period),
t_current, t_current,
t_current + self.period) t_current + self.period)
return comment return comment
def gen_pin_names(self, port_signal_names, port_info, abits, dbits): def gen_pin_names(self, port_signal_names, port_info, abits, dbits):
@ -484,6 +480,43 @@ class simulation():
sen_name = sen_name.split('.')[-1] sen_name = sen_name.split('.')[-1]
return sen_name return sen_name
def create_graph(self):
"""Creates timing graph to generate the timing paths for the SRAM output."""
self.sram.clear_exclude_bits() # Removes previous bit exclusions
self.sram.graph_exclude_bits(self.wordline_row, self.bitline_column)
# Generate new graph every analysis as edges might change depending on test bit
self.graph = graph_util.timing_graph()
self.sram_instance_name = "X{}".format(self.sram.name)
self.sram.build_graph(self.graph, self.sram_instance_name, self.pins)
def get_bl_name_search_exclusions(self):
"""Gets the mods as a set which should be excluded while searching for name."""
# Exclude the RBL as it contains bitcells which are not in the main bitcell array
# so it makes the search awkward
return set(factory.get_mods(OPTS.replica_bitline))
def get_alias_in_path(self, paths, internal_net, mod, exclusion_set=None):
"""
Finds a single alias for the internal_net in given paths.
More or less hits cause an error
"""
net_found = False
for path in paths:
aliases = self.sram.find_aliases(self.sram_instance_name, self.pins, path, internal_net, mod, exclusion_set)
if net_found and len(aliases) >= 1:
debug.error('Found multiple paths with {} net.'.format(internal_net), 1)
elif len(aliases) > 1:
debug.error('Found multiple {} nets in single path.'.format(internal_net), 1)
elif not net_found and len(aliases) == 1:
path_net_name = aliases[0]
net_found = True
if not net_found:
debug.error("Could not find {} net in timing paths.".format(internal_net), 1)
return path_net_name
def get_bl_name(self, paths, port): def get_bl_name(self, paths, port):
"""Gets the signal name associated with the bitlines in the bank.""" """Gets the signal name associated with the bitlines in the bank."""
@ -492,7 +525,6 @@ class simulation():
cell_bl = cell_mod.get_bl_name(port) cell_bl = cell_mod.get_bl_name(port)
cell_br = cell_mod.get_br_name(port) cell_br = cell_mod.get_br_name(port)
bl_found = False
# Only a single path should contain a single s_en name. Anything else is an error. # Only a single path should contain a single s_en name. Anything else is an error.
bl_names = [] bl_names = []
exclude_set = self.get_bl_name_search_exclusions() exclude_set = self.get_bl_name_search_exclusions()
@ -502,3 +534,6 @@ class simulation():
for i in range(len(bl_names)): for i in range(len(bl_names)):
bl_names[i] = bl_names[i].split('.')[-1] bl_names[i] = bl_names[i].split('.')[-1]
return bl_names[0], bl_names[1] return bl_names[0], bl_names[1]

View File

@ -1076,14 +1076,30 @@ class bank(design.design):
offset=control_pos) offset=control_pos)
def graph_exclude_precharge(self): def graph_exclude_precharge(self):
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity""" """
Precharge adds a loop between bitlines, can be excluded to reduce complexity
"""
for port in self.read_ports: for port in self.read_ports:
if self.port_data[port]: if self.port_data[port]:
self.port_data[port].graph_exclude_precharge() self.port_data[port].graph_exclude_precharge()
def get_cell_name(self, inst_name, row, col): def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell.""" """
Gets the spice name of the target bitcell.
"""
return self.bitcell_array_inst.mod.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name, return self.bitcell_array_inst.mod.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name,
row, row,
col) col)
def graph_exclude_bits(self, targ_row, targ_col):
"""
Excludes bits in column from being added to graph except target
"""
self.bitcell_array.graph_exclude_bits(targ_row, targ_col)
def clear_exclude_bits(self):
"""
Clears the bit exclusions
"""
self.bitcell_array.clear_exclude_bits()

View File

@ -105,7 +105,9 @@ class bitcell_array(bitcell_base_array):
return bl_wire return bl_wire
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
"""Excludes bits in column from being added to graph except target""" """
Excludes bits in column from being added to graph except target
"""
# Function is not robust with column mux configurations # Function is not robust with column mux configurations
for row in range(self.row_size): for row in range(self.row_size):
for col in range(self.column_size): for col in range(self.column_size):

View File

@ -297,6 +297,15 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array):
for i, local_col in enumerate(self.col_offsets): for i, local_col in enumerate(self.col_offsets):
if local_col > col: if local_col > col:
break break
else:
# In this case, we it should be in the last bitcell array
i = len(self.col_offsets)
return self.local_mods[i - 1].get_cell_name(inst_name + '.x' + self.local_insts[i - 1].name, row, col) return self.local_mods[i - 1].get_cell_name(inst_name + '.x' + self.local_insts[i - 1].name, row, col)
def clear_exclude_bits(self):
"""
Clears the bit exclusions
"""
for mod in self.local_mods:
mod.clear_exclude_bits()

View File

@ -280,3 +280,9 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
"""Gets the spice name of the target bitcell.""" """Gets the spice name of the target bitcell."""
return self.bitcell_array.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name, row, col) return self.bitcell_array.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name, row, col)
def clear_exclude_bits(self):
"""
Clears the bit exclusions
"""
self.bitcell_array.clear_exclude_bits()

View File

@ -529,15 +529,27 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
return bl_wire return bl_wire
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
"""Excludes bits in column from being added to graph except target""" """
Excludes bits in column from being added to graph except target
"""
self.bitcell_array.graph_exclude_bits(targ_row, targ_col) self.bitcell_array.graph_exclude_bits(targ_row, targ_col)
def graph_exclude_replica_col_bits(self): def graph_exclude_replica_col_bits(self):
"""Exclude all replica/dummy cells in the replica columns except the replica bit.""" """
Exclude all replica/dummy cells in the replica columns except the replica bit.
"""
for port in self.left_rbl + self.right_rbl: for port in self.left_rbl + self.right_rbl:
self.replica_columns[port].exclude_all_but_replica() self.replica_columns[port].exclude_all_but_replica()
def get_cell_name(self, inst_name, row, col): def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell.""" """
Gets the spice name of the target bitcell.
"""
return self.bitcell_array.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name, row, col) return self.bitcell_array.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name, row, col)
def clear_exclude_bits(self):
"""
Clears the bit exclusions
"""
self.bitcell_array.init_graph_params()

View File

@ -200,8 +200,10 @@ class replica_column(bitcell_base_array):
return self.bitline_names[port] return self.bitline_names[port]
def get_bitcell_pins(self, row, col): def get_bitcell_pins(self, row, col):
""" Creates a list of connections in the bitcell, """
indexed by column and row, for instance use in bitcell_array """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array
"""
bitcell_pins = [] bitcell_pins = []
for port in self.all_ports: for port in self.all_ports:
bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))]) bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))])
@ -212,8 +214,10 @@ class replica_column(bitcell_base_array):
return bitcell_pins return bitcell_pins
def get_bitcell_pins_col_cap(self, row, col): def get_bitcell_pins_col_cap(self, row, col):
""" Creates a list of connections in the bitcell, """
indexed by column and row, for instance use in bitcell_array """ Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array
"""
bitcell_pins = [] bitcell_pins = []
for port in self.all_ports: for port in self.all_ports:
bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))]) bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))])
@ -223,7 +227,9 @@ class replica_column(bitcell_base_array):
return bitcell_pins return bitcell_pins
def exclude_all_but_replica(self): def exclude_all_but_replica(self):
"""Excludes all bits except the replica cell (self.replica_bit).""" """
Excludes all bits except the replica cell (self.replica_bit).
"""
for row, cell in self.cell_inst.items(): for row, cell in self.cell_inst.items():
if row != self.replica_bit: if row != self.replica_bit:

View File

@ -631,3 +631,14 @@ class sram_base(design, verilog, lef):
def lvs_write(self, sp_name): def lvs_write(self, sp_name):
self.sp_write(sp_name, lvs_netlist=True) self.sp_write(sp_name, lvs_netlist=True)
def graph_exclude_bits(self, targ_row, targ_col):
"""
Excludes bits in column from being added to graph except target
"""
self.bank.graph_exclude_bits(targ_row, targ_col)
def clear_exclude_bits(self):
"""
Clears the bit exclusions
"""
self.bank.clear_exclude_bits()