OpenRAM/compiler/sram/sram_base.py

653 lines
29 KiB
Python
Raw Normal View History

# See LICENSE for licensing information.
#
2019-06-14 17:43:41 +02:00
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import datetime
import debug
from math import log, ceil
from importlib import reload
from vector import vector
from globals import OPTS, print_time
from design import design
from verilog import verilog
from lef import lef
2019-01-17 01:15:38 +01:00
from sram_factory import factory
class sram_base(design, verilog, lef):
"""
Dynamically generated SRAM by connecting banks to control logic. The
number of banks should be 1 , 2 or 4
"""
def __init__(self, name, sram_config):
design.__init__(self, name)
lef.__init__(self, ["m1", "m2", "m3", "m4"])
verilog.__init__(self)
self.sram_config = sram_config
sram_config.set_local_config(self)
self.bank_insts = []
if self.write_size:
self.num_wmasks = int(ceil(self.word_size / self.write_size))
else:
self.num_wmasks = 0
2020-05-14 12:30:29 +02:00
if not self.num_spare_cols:
self.num_spare_cols = 0
def add_pins(self):
""" Add pins for entire SRAM. """
for port in self.write_ports:
2020-05-14 12:30:29 +02:00
for bit in range(self.word_size + self.num_spare_cols):
2020-03-06 01:27:35 +01:00
self.add_pin("din{0}[{1}]".format(port, bit), "INPUT")
for port in self.all_ports:
for bit in range(self.addr_size):
2020-03-06 01:27:35 +01:00
self.add_pin("addr{0}[{1}]".format(port, bit), "INPUT")
# These are used to create the physical pins
self.control_logic_inputs = []
self.control_logic_outputs = []
for port in self.all_ports:
if port in self.readwrite_ports:
self.control_logic_inputs.append(self.control_logic_rw.get_inputs())
self.control_logic_outputs.append(self.control_logic_rw.get_outputs())
elif port in self.write_ports:
self.control_logic_inputs.append(self.control_logic_w.get_inputs())
self.control_logic_outputs.append(self.control_logic_w.get_outputs())
else:
self.control_logic_inputs.append(self.control_logic_r.get_inputs())
self.control_logic_outputs.append(self.control_logic_r.get_outputs())
for port in self.all_ports:
2020-03-06 01:27:35 +01:00
self.add_pin("csb{}".format(port), "INPUT")
for port in self.readwrite_ports:
2020-03-06 01:27:35 +01:00
self.add_pin("web{}".format(port), "INPUT")
for port in self.all_ports:
2020-03-06 01:27:35 +01:00
self.add_pin("clk{}".format(port), "INPUT")
# add the optional write mask pins
for port in self.write_ports:
for bit in range(self.num_wmasks):
2020-03-06 01:27:35 +01:00
self.add_pin("wmask{0}[{1}]".format(port, bit), "INPUT")
2020-05-14 12:30:29 +02:00
for bit in range(self.num_spare_cols):
self.add_pin("spare_wen{0}[{1}]".format(port, bit), "INPUT")
for port in self.read_ports:
2020-05-14 12:30:29 +02:00
for bit in range(self.word_size + self.num_spare_cols):
2020-03-06 01:27:35 +01:00
self.add_pin("dout{0}[{1}]".format(port, bit), "OUTPUT")
self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND")
def add_global_pex_labels(self):
"""
Add pex labels at the sram level for spice analysis
"""
2020-01-20 13:16:30 +01:00
# add pex labels for bitcells
for bank_num in range(len(self.bank_insts)):
bank = self.bank_insts[bank_num]
2020-10-02 22:32:52 +02:00
pex_data = bank.reverse_transformation_bitcell(self.bitcell.name)
2020-01-28 01:28:55 +01:00
bank_offset = pex_data[0] # offset bank relative to sram
Q_offset = pex_data[1] # offset of storage relative to bank
Q_bar_offset = pex_data[2] # offset of storage relative to bank
bl_offsets = pex_data[3]
br_offsets = pex_data[4]
bl_meta = pex_data[5]
br_meta = pex_data[6]
bl = []
br = []
2020-10-02 22:32:52 +02:00
storage_layer_name = "m1"
bitline_layer_name = self.bitcell.get_pin("bl").layer
for cell in range(len(bank_offset)):
Q = [bank_offset[cell][0] + Q_offset[cell][0],
bank_offset[cell][1] + Q_offset[cell][1]]
Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0],
bank_offset[cell][1] + Q_bar_offset[cell][1]]
2020-05-04 12:05:33 +02:00
OPTS.words_per_row = self.words_per_row
row = int(cell % (OPTS.num_words / self.words_per_row))
col = int(cell / (OPTS.num_words))
self.add_layout_pin_rect_center("bitcell_Q_b{}_r{}_c{}".format(bank_num,
row,
col),
storage_layer_name,
Q)
self.add_layout_pin_rect_center("bitcell_Q_bar_b{}_r{}_c{}".format(bank_num,
row,
col),
storage_layer_name,
Q_bar)
2020-08-04 02:14:34 +02:00
2020-01-28 01:28:55 +01:00
for cell in range(len(bl_offsets)):
col = bl_meta[cell][0][2]
for bitline in range(len(bl_offsets[cell])):
bitline_location = [float(bank_offset[cell][0]) + bl_offsets[cell][bitline][0],
float(bank_offset[cell][1]) + bl_offsets[cell][bitline][1]]
2020-01-28 01:28:55 +01:00
bl.append([bitline_location, bl_meta[cell][bitline][3], col])
2020-01-28 01:28:55 +01:00
for cell in range(len(br_offsets)):
col = br_meta[cell][0][2]
for bitline in range(len(br_offsets[cell])):
bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0],
float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]]
br.append([bitline_location, br_meta[cell][bitline][3], col])
2020-01-28 01:28:55 +01:00
for i in range(len(bl)):
self.add_layout_pin_rect_center("bl{0}_{1}".format(bl[i][1], bl[i][2]),
bitline_layer_name, bl[i][0])
2020-01-28 01:28:55 +01:00
for i in range(len(br)):
self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]),
bitline_layer_name, br[i][0])
# add pex labels for control logic
for i in range(len(self.control_logic_insts)):
instance = self.control_logic_insts[i]
control_logic_offset = instance.offset
for output in instance.mod.output_list:
pin = instance.mod.get_pin(output)
pin.transform([0, 0], instance.mirror, instance.rotate)
offset = [control_logic_offset[0] + pin.center()[0],
control_logic_offset[1] + pin.center()[1]]
self.add_layout_pin_rect_center("{0}{1}".format(pin.name, i),
storage_layer_name,
offset)
def create_netlist(self):
""" Netlist creation """
2020-03-06 18:03:52 +01:00
start_time = datetime.datetime.now()
# Must create the control logic before pins to get the pins
self.add_modules()
self.add_pins()
self.create_modules()
# This is for the lib file if we don't create layout
self.width=0
self.height=0
if not OPTS.is_unit_test:
2020-03-06 18:03:52 +01:00
print_time("Submodules", datetime.datetime.now(), start_time)
def create_layout(self):
2020-03-06 01:27:35 +01:00
""" Layout creation """
2020-03-06 18:03:52 +01:00
start_time = datetime.datetime.now()
self.place_instances()
if not OPTS.is_unit_test:
2020-03-06 18:03:52 +01:00
print_time("Placement", datetime.datetime.now(), start_time)
2020-03-06 18:03:52 +01:00
start_time = datetime.datetime.now()
self.route_layout()
self.route_supplies()
if not OPTS.is_unit_test:
2020-03-06 18:03:52 +01:00
print_time("Routing", datetime.datetime.now(), start_time)
2018-10-06 23:03:00 +02:00
self.add_lvs_correspondence_points()
2019-09-05 01:41:27 +02:00
self.offset_all_coordinates()
2018-10-06 23:03:00 +02:00
highest_coord = self.find_highest_coords()
2019-09-05 01:41:27 +02:00
self.width = highest_coord[0]
self.height = highest_coord[1]
if OPTS.use_pex:
self.add_global_pex_labels()
2020-06-14 23:17:35 +02:00
self.add_boundary(ll=vector(0, 0),
ur=vector(self.width, self.height))
2020-03-06 18:03:52 +01:00
start_time = datetime.datetime.now()
# We only enable final verification if we have routed the design
self.DRC_LVS(final_verification=OPTS.route_supplies, force_check=OPTS.check_lvsdrc)
if not OPTS.is_unit_test:
2020-03-06 18:03:52 +01:00
print_time("Verification", datetime.datetime.now(), start_time)
def create_modules(self):
2020-03-06 01:27:35 +01:00
debug.error("Must override pure virtual function.", -1)
def route_supplies(self):
""" Route the supply grid and connect the pins to them. """
2018-10-08 18:56:39 +02:00
2019-05-28 01:38:47 +02:00
# Copy the pins to the top level
# This will either be used to route or left unconnected.
for inst in self.insts:
2020-03-06 01:27:35 +01:00
self.copy_power_pins(inst, "vdd")
self.copy_power_pins(inst, "gnd")
2020-06-14 23:17:35 +02:00
if not OPTS.route_supplies:
2019-05-28 02:38:59 +02:00
# Do not route the power supply (leave as must-connect pins)
return
grid_stack = set()
try:
from tech import power_grid
grid_stack = power_grid
except ImportError:
# if no power_grid is specified by tech we use sensible defaults
import tech
if "m4" in tech.layer:
# Route a M3/M4 grid
grid_stack = self.m3_stack
elif "m3" in tech.layer:
grid_stack =("m3",)
from supply_grid_router import supply_grid_router as router
rtr=router(grid_stack, self)
rtr.route()
def compute_bus_sizes(self):
""" Compute the independent bus widths shared between two and four bank SRAMs """
# address size + control signals + one-hot bank select signals
2020-03-06 01:27:35 +01:00
self.num_vertical_line = self.addr_size + self.control_size + log(self.num_banks, 2) + 1
# data bus size
self.num_horizontal_line = self.word_size
2020-03-06 01:27:35 +01:00
self.vertical_bus_width = self.m2_pitch * self.num_vertical_line
# vertical bus height depends on 2 or 4 banks
2020-03-06 01:27:35 +01:00
self.data_bus_height = self.m3_pitch * self.num_horizontal_line
self.data_bus_width = 2 * (self.bank.width + self.bank_to_bus_distance) + self.vertical_bus_width
2020-03-06 01:27:35 +01:00
self.control_bus_height = self.m1_pitch * (self.control_size + 2)
self.control_bus_width = self.bank.width + self.bank_to_bus_distance + self.vertical_bus_width
2020-03-06 01:27:35 +01:00
self.supply_bus_height = self.m1_pitch * 2 # 2 for vdd/gnd placed with control bus
self.supply_bus_width = self.data_bus_width
# Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really)
2020-03-06 01:27:35 +01:00
debug.check(self.bank.width + self.vertical_bus_width > 0.9 * self.control_logic.width,
"Bank is too small compared to control logic.")
def add_busses(self):
""" Add the horizontal and vertical busses """
# Vertical bus
# The order of the control signals on the control bus:
self.control_bus_names = []
for port in self.all_ports:
2018-11-27 03:00:59 +01:00
self.control_bus_names[port] = ["clk_buf{}".format(port)]
wen = "w_en{}".format(port)
sen = "s_en{}".format(port)
pen = "p_en_bar{}".format(port)
2018-11-27 03:00:59 +01:00
if self.port_id[port] == "r":
self.control_bus_names[port].extend([sen, pen])
elif self.port_id[port] == "w":
2019-08-01 21:21:43 +02:00
self.control_bus_names[port].extend([wen, pen])
2018-11-27 03:00:59 +01:00
else:
self.control_bus_names[port].extend([sen, wen, pen])
self.vert_control_bus_positions = self.create_vertical_bus(layer="m2",
pitch=self.m2_pitch,
offset=self.vertical_bus_offset,
names=self.control_bus_names[port],
length=self.vertical_bus_height)
2020-03-06 01:27:35 +01:00
self.addr_bus_names=["A{0}[{1}]".format(port, i) for i in range(self.addr_size)]
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="m2",
pitch=self.m2_pitch,
offset=self.addr_bus_offset,
names=self.addr_bus_names,
length=self.addr_bus_height))
2020-03-06 01:27:35 +01:00
self.bank_sel_bus_names = ["bank_sel{0}_{1}".format(port, i) for i in range(self.num_banks)]
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="m2",
pitch=self.m2_pitch,
offset=self.bank_sel_bus_offset,
names=self.bank_sel_bus_names,
length=self.vertical_bus_height))
# Horizontal data bus
2020-03-06 01:27:35 +01:00
self.data_bus_names = ["DATA{0}[{1}]".format(port, i) for i in range(self.word_size)]
self.data_bus_positions = self.create_horizontal_pin_bus(layer="m3",
pitch=self.m3_pitch,
offset=self.data_bus_offset,
names=self.data_bus_names,
length=self.data_bus_width)
# Horizontal control logic bus
# vdd/gnd in bus go along whole SRAM
# FIXME: Fatten these wires?
self.horz_control_bus_positions = self.create_horizontal_bus(layer="m1",
pitch=self.m1_pitch,
offset=self.supply_bus_offset,
names=["vdd"],
length=self.supply_bus_width)
# The gnd rail must not be the entire width since we protrude the right-most vdd rail up for
# the decoder in 4-bank SRAMs
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="m1",
pitch=self.m1_pitch,
2020-03-06 01:27:35 +01:00
offset=self.supply_bus_offset + vector(0, self.m1_pitch),
names=["gnd"],
length=self.supply_bus_width))
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="m1",
pitch=self.m1_pitch,
offset=self.control_bus_offset,
names=self.control_bus_names[port],
length=self.control_bus_width))
def add_multi_bank_modules(self):
""" Create the multibank address flops and bank decoder """
from dff_buf_array import dff_buf_array
self.msb_address = dff_buf_array(name="msb_address",
rows=1,
2020-03-06 01:27:35 +01:00
columns=self.num_banks / 2)
self.add_mod(self.msb_address)
if self.num_banks>2:
self.msb_decoder = self.bank.decoder.pre2_4
self.add_mod(self.msb_decoder)
def add_modules(self):
2019-01-17 01:15:38 +01:00
self.bitcell = factory.create(module_type=OPTS.bitcell)
2019-07-03 22:17:12 +02:00
self.dff = factory.create(module_type="dff")
# Create the address and control flops (but not the clk)
self.row_addr_dff = factory.create("dff_array", module_name="row_addr_dff", rows=self.row_addr_size, columns=1)
self.add_mod(self.row_addr_dff)
if self.col_addr_size > 0:
self.col_addr_dff = factory.create("dff_array", module_name="col_addr_dff", rows=1, columns=self.col_addr_size)
self.add_mod(self.col_addr_dff)
else:
self.col_addr_dff = None
2020-05-14 12:30:29 +02:00
self.data_dff = factory.create("dff_array", module_name="data_dff", rows=1, columns=self.word_size + self.num_spare_cols)
self.add_mod(self.data_dff)
2019-07-03 22:17:12 +02:00
if self.write_size:
self.wmask_dff = factory.create("dff_array", module_name="wmask_dff", rows=1, columns=self.num_wmasks)
self.add_mod(self.wmask_dff)
2019-07-04 20:14:32 +02:00
if self.num_spare_cols:
self.spare_wen_dff = factory.create("dff_array", module_name="spare_wen_dff", rows=1, columns=self.num_spare_cols)
self.add_mod(self.spare_wen_dff)
# Create the bank module (up to four are instantiated)
self.bank = factory.create("bank", sram_config=self.sram_config, module_name="bank")
self.add_mod(self.bank)
# Create bank decoder
if(self.num_banks > 1):
self.add_multi_bank_modules()
self.bank_count = 0
c = reload(__import__(OPTS.control_logic))
self.mod_control_logic = getattr(c, OPTS.control_logic)
# Create the control logic module for each port type
if len(self.readwrite_ports)>0:
self.control_logic_rw = self.mod_control_logic(num_rows=self.num_rows,
words_per_row=self.words_per_row,
word_size=self.word_size,
2020-05-14 12:30:29 +02:00
spare_columns=self.num_spare_cols,
sram=self,
port_type="rw")
self.add_mod(self.control_logic_rw)
if len(self.writeonly_ports)>0:
2020-03-06 01:27:35 +01:00
self.control_logic_w = self.mod_control_logic(num_rows=self.num_rows,
words_per_row=self.words_per_row,
word_size=self.word_size,
2020-05-14 12:30:29 +02:00
spare_columns=self.num_spare_cols,
sram=self,
port_type="w")
self.add_mod(self.control_logic_w)
if len(self.readonly_ports)>0:
2020-03-06 01:27:35 +01:00
self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows,
words_per_row=self.words_per_row,
word_size=self.word_size,
2020-05-14 12:30:29 +02:00
spare_columns=self.num_spare_cols,
sram=self,
port_type="r")
self.add_mod(self.control_logic_r)
2020-03-06 01:27:35 +01:00
def create_bank(self, bank_num):
""" Create a bank """
self.bank_insts.append(self.add_inst(name="bank{0}".format(bank_num),
mod=self.bank))
temp = []
for port in self.read_ports:
2020-05-14 12:30:29 +02:00
for bit in range(self.word_size + self.num_spare_cols):
2020-03-06 01:27:35 +01:00
temp.append("dout{0}[{1}]".format(port, bit))
for port in self.all_ports:
2019-07-12 17:42:36 +02:00
temp.append("rbl_bl{0}".format(port))
for port in self.write_ports:
2020-05-14 12:30:29 +02:00
for bit in range(self.word_size + self.num_spare_cols):
2020-03-06 01:27:35 +01:00
temp.append("bank_din{0}[{1}]".format(port, bit))
for port in self.all_ports:
for bit in range(self.bank_addr_size):
2020-03-06 01:27:35 +01:00
temp.append("a{0}[{1}]".format(port, bit))
if(self.num_banks > 1):
for port in self.all_ports:
2020-03-06 01:27:35 +01:00
temp.append("bank_sel{0}[{1}]".format(port, bank_num))
for port in self.read_ports:
temp.append("s_en{0}".format(port))
2019-08-01 21:21:43 +02:00
for port in self.all_ports:
temp.append("p_en_bar{0}".format(port))
for port in self.write_ports:
temp.append("w_en{0}".format(port))
for bit in range(self.num_wmasks):
temp.append("bank_wmask{}[{}]".format(port, bit))
2020-05-14 12:30:29 +02:00
for bit in range(self.num_spare_cols):
temp.append("bank_spare_wen{0}[{1}]".format(port, bit))
for port in self.all_ports:
2018-11-27 03:00:59 +01:00
temp.append("wl_en{0}".format(port))
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
return self.bank_insts[-1]
def place_bank(self, bank_inst, position, x_flip, y_flip):
""" Place a bank at the given position with orientations """
# x_flip == 1 --> no flip in x_axis
# x_flip == -1 --> flip in x_axis
# y_flip == 1 --> no flip in y_axis
# y_flip == -1 --> flip in y_axis
# x_flip and y_flip are used for position translation
if x_flip == -1 and y_flip == -1:
bank_rotation = 180
else:
bank_rotation = 0
if x_flip == y_flip:
bank_mirror = "R0"
elif x_flip == -1:
bank_mirror = "MX"
elif y_flip == -1:
bank_mirror = "MY"
else:
bank_mirror = "R0"
bank_inst.place(offset=position,
mirror=bank_mirror,
rotate=bank_rotation)
return bank_inst
def create_row_addr_dff(self):
""" Add all address flops for the main decoder """
insts = []
for port in self.all_ports:
insts.append(self.add_inst(name="row_address{}".format(port),
mod=self.row_addr_dff))
# inputs, outputs/output/bar
inputs = []
outputs = []
for bit in range(self.row_addr_size):
2020-03-06 01:27:35 +01:00
inputs.append("addr{}[{}]".format(port, bit + self.col_addr_size))
outputs.append("a{}[{}]".format(port, bit + self.col_addr_size))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_col_addr_dff(self):
""" Add and place all address flops for the column decoder """
insts = []
for port in self.all_ports:
insts.append(self.add_inst(name="col_address{}".format(port),
mod=self.col_addr_dff))
# inputs, outputs/output/bar
inputs = []
outputs = []
for bit in range(self.col_addr_size):
2020-03-06 01:27:35 +01:00
inputs.append("addr{}[{}]".format(port, bit))
outputs.append("a{}[{}]".format(port, bit))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_data_dff(self):
""" Add and place all data flops """
insts = []
for port in self.all_ports:
if port in self.write_ports:
insts.append(self.add_inst(name="data_dff{}".format(port),
mod=self.data_dff))
else:
insts.append(None)
continue
# inputs, outputs/output/bar
inputs = []
outputs = []
2020-05-14 12:30:29 +02:00
for bit in range(self.word_size + self.num_spare_cols):
2020-03-06 01:27:35 +01:00
inputs.append("din{}[{}]".format(port, bit))
outputs.append("bank_din{}[{}]".format(port, bit))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_wmask_dff(self):
""" Add and place all wmask flops """
insts = []
for port in self.all_ports:
if port in self.write_ports:
insts.append(self.add_inst(name="wmask_dff{}".format(port),
mod=self.wmask_dff))
else:
insts.append(None)
continue
# inputs, outputs/output/bar
inputs = []
outputs = []
for bit in range(self.num_wmasks):
inputs.append("wmask{}[{}]".format(port, bit))
outputs.append("bank_wmask{}[{}]".format(port, bit))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_spare_wen_dff(self):
""" Add all spare write enable flops """
insts = []
for port in self.all_ports:
if port in self.write_ports:
insts.append(self.add_inst(name="spare_wen_dff{}".format(port),
mod=self.spare_wen_dff))
else:
insts.append(None)
continue
# inputs, outputs/output/bar
inputs = []
outputs = []
for bit in range(self.num_spare_cols):
inputs.append("spare_wen{}[{}]".format(port, bit))
outputs.append("bank_spare_wen{}[{}]".format(port, bit))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_control_logic(self):
2018-11-14 01:05:22 +01:00
""" Add control logic instances """
insts = []
for port in self.all_ports:
if port in self.readwrite_ports:
mod = self.control_logic_rw
elif port in self.write_ports:
mod = self.control_logic_w
else:
mod = self.control_logic_r
2018-11-14 01:05:22 +01:00
insts.append(self.add_inst(name="control{}".format(port), mod=mod))
2018-11-29 00:30:52 +01:00
# Inputs
temp = ["csb{}".format(port)]
if port in self.readwrite_ports:
temp.append("web{}".format(port))
temp.append("clk{}".format(port))
temp.append("rbl_bl{}".format(port))
2018-11-29 00:30:52 +01:00
# Outputs
if port in self.read_ports:
temp.append("s_en{}".format(port))
if port in self.write_ports:
temp.append("w_en{}".format(port))
2019-08-01 21:21:43 +02:00
temp.append("p_en_bar{}".format(port))
2018-11-27 03:00:59 +01:00
temp.extend(["wl_en{}".format(port), "clk_buf{}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
return insts
2019-07-16 18:04:58 +02:00
2020-04-07 00:20:59 +02:00
def sp_write(self, sp_name, lvs_netlist=False):
# Write the entire spice of the object to the file
############################################################
# Spice circuit
############################################################
sp = open(sp_name, 'w')
sp.write("**************************************************\n")
sp.write("* OpenRAM generated memory.\n")
sp.write("* Words: {}\n".format(self.num_words))
sp.write("* Data bits: {}\n".format(self.word_size))
sp.write("* Banks: {}\n".format(self.num_banks))
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
sp.write("**************************************************\n")
# This causes unit test mismatch
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
# sp.write("* User: {0}\n".format(getpass.getuser()))
# sp.write(".global {0} {1}\n".format(spice["vdd_name"],
# spice["gnd_name"]))
usedMODS = list()
2020-04-07 00:20:59 +02:00
self.sp_write_file(sp, usedMODS, lvs_netlist=lvs_netlist)
del usedMODS
sp.close()
2020-04-07 00:20:59 +02:00
def lvs_write(self, sp_name):
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()