Merged with dev

This commit is contained in:
Hunter Nichols
2020-11-10 15:47:56 -08:00
375 changed files with 20170 additions and 15576 deletions
+27 -8
View File
@@ -6,7 +6,10 @@
# All rights reserved.
#
import datetime
import os
import debug
import verify
from characterizer import functional
from globals import OPTS, print_time
@@ -38,7 +41,7 @@ class sram():
start_time = datetime.datetime.now()
self.name = name
if self.num_banks == 1:
from sram_1bank import sram_1bank as sram
elif self.num_banks == 2:
@@ -50,16 +53,16 @@ class sram():
self.s.create_netlist()
if not OPTS.netlist_only:
self.s.create_layout()
if not OPTS.is_unit_test:
print_time("SRAM creation", datetime.datetime.now(), start_time)
def sp_write(self, name):
self.s.sp_write(name)
def lvs_write(self, name):
self.s.lvs_write(name)
def lef_write(self, name):
self.s.lef_write(name)
@@ -70,7 +73,7 @@ class sram():
self.s.verilog_write(name)
def extended_config_write(self, name):
"""Dump config file with all options.
"""Dump config file with all options.
Include defaults and anything changed by input config."""
f = open(name, "w")
var_dict = dict((name, getattr(OPTS, name)) for name in dir(OPTS) if not name.startswith('__') and not callable(getattr(OPTS, name)))
@@ -80,7 +83,7 @@ class sram():
else:
f.write(str(var_name) + " = " + str(var_value)+ "\n")
f.close()
def save(self):
""" Save all the output files while reporting time to do it as well. """
@@ -90,6 +93,11 @@ class sram():
gdsname = OPTS.output_path + self.s.name + ".gds"
debug.print_raw("GDS: Writing to {0}".format(gdsname))
self.gds_write(gdsname)
verify.write_drc_script(cell_name=self.s.name,
gds_name=os.path.basename(gdsname),
extract=True,
final_verification=True,
output_path=OPTS.output_path)
print_time("GDS", datetime.datetime.now(), start_time)
# Create a LEF physical model
@@ -104,6 +112,10 @@ class sram():
spname = OPTS.output_path + self.s.name + ".sp"
debug.print_raw("SP: Writing to {0}".format(spname))
self.sp_write(spname)
functional(self.s,
os.path.basename(spname),
cycles=200,
output_path=OPTS.output_path)
print_time("Spice writing", datetime.datetime.now(), start_time)
# Save the LVS file
@@ -111,11 +123,16 @@ class sram():
lvsname = OPTS.output_path + self.s.name + ".lvs.sp"
debug.print_raw("LVS: Writing to {0}".format(lvsname))
self.lvs_write(lvsname)
if not OPTS.netlist_only:
verify.write_lvs_script(cell_name=self.s.name,
gds_name=os.path.basename(gdsname),
sp_name=os.path.basename(lvsname),
final_verification=True,
output_path=OPTS.output_path)
print_time("LVS writing", datetime.datetime.now(), start_time)
# Save the extracted spice file
if OPTS.use_pex:
import verify
start_time = datetime.datetime.now()
# Output the extracted design if requested
pexname = OPTS.output_path + self.s.name + ".pex.sp"
@@ -127,6 +144,8 @@ class sram():
# Use generated spice file for characterization
sp_file = spname
# Save a functional simulation file
# Characterize the design
start_time = datetime.datetime.now()
from characterizer import lib
+35 -35
View File
@@ -19,13 +19,13 @@ class sram_1bank(sram_base):
"""
def __init__(self, name, sram_config):
sram_base.__init__(self, name, sram_config)
def create_modules(self):
"""
This adds the modules for a single bank SRAM with control
logic.
"""
self.bank_inst=self.create_bank(0)
self.control_logic_insts = self.create_control_logic()
@@ -51,7 +51,7 @@ class sram_1bank(sram_base):
This places the instances for a single bank SRAM with control
logic and up to 2 ports.
"""
# No orientation or offset
self.place_bank(self.bank_inst, [0, 0], 1, 1)
@@ -129,10 +129,10 @@ class sram_1bank(sram_base):
y_offset = self.bank.bank_array_ll.y
self.row_addr_pos[port] = vector(x_offset, y_offset)
self.row_addr_dff_insts[port].place(self.row_addr_pos[port], mirror="XY")
def place_control(self):
port = 0
# This includes 2 M2 pitches for the row addr clock line.
# The delay line is aligned with the bitcell array while the control logic is aligned with the port_data
# using the control_logic_center value.
@@ -171,7 +171,7 @@ class sram_1bank(sram_base):
x_offset = self.col_addr_dff_insts[port].rx()
else:
self.col_addr_pos[port] = vector(x_offset, 0)
if port in self.write_ports:
if self.write_size:
# Add the write mask flops below the write mask AND array.
@@ -201,7 +201,7 @@ class sram_1bank(sram_base):
if len(self.all_ports) > 1:
port = 1
# Add the col address flops below the bank to the right of the control logic
x_offset = self.control_logic_insts[port].lx() - 2 * self.dff.width
# Place it a data bus below the x-axis, but at least as high as the control logic to not block
@@ -215,7 +215,7 @@ class sram_1bank(sram_base):
x_offset = self.col_addr_dff_insts[port].lx()
else:
self.col_addr_pos[port] = vector(x_offset, y_offset)
if port in self.write_ports:
# Add spare write enable flops to the right of the data flops since the spare
# columns will be on the left
@@ -248,7 +248,7 @@ class sram_1bank(sram_base):
highest_coord = self.find_highest_coords()
lowest_coord = self.find_lowest_coords()
bbox = [lowest_coord, highest_coord]
for port in self.all_ports:
# Depending on the port, use the bottom/top or left/right sides
# Port 0 is left/bottom
@@ -296,7 +296,7 @@ class sram_1bank(sram_base):
self.copy_layout_pin(self.data_dff_insts[port],
"din_{}".format(bit),
"din{0}[{1}]".format(port, bit))
# Data output pins go to BOTTOM/TOP
if port in self.readwrite_ports and OPTS.perimeter_pins:
for bit in range(self.word_size + self.num_spare_cols):
@@ -319,8 +319,8 @@ class sram_1bank(sram_base):
self.copy_layout_pin(self.bank_inst,
"dout{0}_{1}".format(port, bit),
"dout{0}[{1}]".format(port, bit))
# Lower address bits go to BOTTOM/TOP
for bit in range(self.col_addr_size):
@@ -333,7 +333,7 @@ class sram_1bank(sram_base):
self.copy_layout_pin(self.col_addr_dff_insts[port],
"din_{}".format(bit),
"addr{0}[{1}]".format(port, bit))
# Upper address bits go to LEFT/RIGHT
for bit in range(self.row_addr_size):
if OPTS.perimeter_pins:
@@ -345,7 +345,7 @@ class sram_1bank(sram_base):
self.copy_layout_pin(self.row_addr_dff_insts[port],
"din_{}".format(bit),
"addr{0}[{1}]".format(port, bit + self.col_addr_size))
# Write mask pins go to BOTTOM/TOP
if port in self.write_ports:
if self.write_size:
@@ -379,20 +379,20 @@ class sram_1bank(sram_base):
self.add_layout_pins()
self.route_clk()
self.route_control_logic()
self.route_row_addr_dff()
def route_dffs(self, add_routes=True):
for port in self.all_ports:
self.route_dff(port, add_routes)
def route_dff(self, port, add_routes):
route_map = []
# column mux dff is routed on it's own since it is to the far end
# decoder inputs are min pitch M2, so need to use lower layer stack
if self.col_addr_size > 0:
@@ -408,7 +408,7 @@ class sram_1bank(sram_base):
else:
offset = vector(0,
self.bank.height + 2 * self.m1_space)
cr = channel_route.channel_route(netlist=route_map,
offset=offset,
layer_stack=self.m1_stack,
@@ -420,7 +420,7 @@ class sram_1bank(sram_base):
self.col_addr_bus_size[port] = cr.height
route_map = []
# wmask dff
if self.num_wmasks > 0 and port in self.write_ports:
dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)]
@@ -436,7 +436,7 @@ class sram_1bank(sram_base):
bank_names = ["din{0}_{1}".format(port, x) for x in range(self.word_size + self.num_spare_cols)]
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
route_map.extend(list(zip(bank_pins, dff_pins)))
if port in self.readwrite_ports and OPTS.perimeter_pins:
# outputs from sense amp
# These are the output pins which had their pin placed on the perimeter, so route from the
@@ -454,14 +454,14 @@ class sram_1bank(sram_base):
bank_names = ["bank_spare_wen{0}_{1}".format(port, x) for x in range(self.num_spare_cols)]
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
route_map.extend(list(zip(bank_pins, dff_pins)))
if len(route_map) > 0:
if self.num_wmasks > 0 and port in self.write_ports:
layer_stack = self.m3_stack
else:
layer_stack = self.m1_stack
if port == 0:
offset = vector(self.control_logic_insts[port].rx() + self.dff.width,
- self.data_bus_size[port] + 2 * self.m1_pitch)
@@ -486,7 +486,7 @@ class sram_1bank(sram_base):
self.connect_inst([])
else:
self.data_bus_size[port] = max(cr.height, self.col_addr_bus_size[port]) + self.data_bus_gap
def route_clk(self):
""" Route the clock network """
@@ -497,7 +497,7 @@ class sram_1bank(sram_base):
# are clk_buf and clk_buf_bar
control_clk_buf_pin = self.control_logic_insts[port].get_pin("clk_buf")
control_clk_buf_pos = control_clk_buf_pin.center()
# This uses a metal2 track to the right (for port0) of the control/row addr DFF
# to route vertically. For port1, it is to the left.
row_addr_clk_pin = self.row_addr_dff_insts[port].get_pin("clk")
@@ -518,11 +518,11 @@ class sram_1bank(sram_base):
self.add_via_stack_center(from_layer=control_clk_buf_pin.layer,
to_layer="m2",
offset=clk_steiner_pos)
# Note, the via to the control logic is taken care of above
self.add_wire(self.m2_stack[::-1],
[row_addr_clk_pos, mid1_pos, clk_steiner_pos])
if self.col_addr_dff:
dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk")
dff_clk_pos = dff_clk_pin.center()
@@ -567,9 +567,9 @@ class sram_1bank(sram_base):
self.add_via_stack_center(from_layer=dest_pin.layer,
to_layer="m2",
offset=dest_pin.center())
def route_row_addr_dff(self):
"""
"""
Connect the output of the row flops to the bank pins
"""
for port in self.all_ports:
@@ -602,7 +602,7 @@ class sram_1bank(sram_base):
self.add_label(text=n,
layer=pin.layer,
offset=pin.center())
def graph_exclude_data_dff(self):
"""
Removes data dff and wmask dff (if applicable) from search graph.
@@ -616,7 +616,7 @@ class sram_1bank(sram_base):
if self.num_spare_cols:
for inst in self.spare_wen_dff_insts:
self.graph_inst_exclude.add(inst)
def graph_exclude_addr_dff(self):
"""
Removes data dff from search graph.
@@ -624,7 +624,7 @@ class sram_1bank(sram_base):
# Address is considered not part of the critical path, subjectively removed
for inst in self.row_addr_dff_insts:
self.graph_inst_exclude.add(inst)
if self.col_addr_dff:
for inst in self.col_addr_dff_insts:
self.graph_inst_exclude.add(inst)
@@ -636,7 +636,7 @@ class sram_1bank(sram_base):
# Insts located in control logic, exclusion function called here
for inst in self.control_logic_insts:
inst.mod.graph_exclude_dffs()
def get_cell_name(self, inst_name, row, col):
"""
Gets the spice name of the target bitcell.
@@ -645,6 +645,6 @@ class sram_1bank(sram_base):
if inst_name.find("x") != 0:
inst_name = "x" + inst_name
return self.bank_inst.mod.get_cell_name(inst_name + ".x" + self.bank_inst.name, row, col)
def get_bank_num(self, inst_name, row, col):
return 0
+27 -27
View File
@@ -32,11 +32,11 @@ class sram_2bank(sram_base):
# In 2 bank SRAM, the height is determined by the control bus which is higher than the msb address
self.vertical_bus_height = self.bank.height + 2*self.bank_to_bus_distance + self.data_bus_height + self.control_bus_height
# The address bus extends down through the power rails, but control and bank_sel bus don't
self.addr_bus_height = self.vertical_bus_height
self.addr_bus_height = self.vertical_bus_height
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0)
self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance)
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height)
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height)
self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height)
self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0)
self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0)
@@ -49,14 +49,14 @@ class sram_2bank(sram_base):
self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch,
self.supply_bus_offset.y + self.supply_bus_height \
+ 2*self.m1_pitch + self.msb_address.width)
def add_modules(self):
""" Adds the modules and the buses to the top level """
self.compute_bus_sizes()
self.add_banks()
self.compute_bank_offsets()
self.add_busses()
@@ -90,7 +90,7 @@ class sram_2bank(sram_base):
rotate=270)
self.msb_bank_sel_addr = "addr[{}]".format(self.addr_size-1)
self.connect_inst([self.msb_bank_sel_addr,"bank_sel[1]","bank_sel[0]","clk_buf", "vdd", "gnd"])
def route_shared_banks(self):
""" Route the shared signals for two and four bank configurations. """
@@ -98,7 +98,7 @@ class sram_2bank(sram_base):
# create the input control pins
for n in self.control_logic_inputs + ["clk"]:
self.copy_layout_pin(self.control_logic_inst, n)
# connect the control logic to the control bus
for n in self.control_logic_outputs + ["vdd", "gnd"]:
pins = self.control_logic_inst.get_pins(n)
@@ -109,7 +109,7 @@ class sram_2bank(sram_base):
rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y)
self.add_path("m2",[pin_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
# connect the control logic cross bar
for n in self.control_logic_outputs:
cross_pos = vector(self.vert_control_bus_positions[n].x,self.horz_control_bus_positions[n].y)
@@ -125,7 +125,7 @@ class sram_2bank(sram_base):
def route_single_msb_address(self):
""" Route one MSB address bit for 2-bank SRAM """
# connect the bank MSB flop supplies
vdd_pins = self.msb_address_inst.get_pins("vdd")
for vdd_pin in vdd_pins:
@@ -133,11 +133,11 @@ class sram_2bank(sram_base):
vdd_pos = vdd_pin.bc()
down_pos = vdd_pos - vector(0,self.m1_pitch)
rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y)
self.add_path("m1",[vdd_pos,down_pos])
self.add_via_center(self.m1_stack,down_pos,rotate=90)
self.add_path("m1",[vdd_pos,down_pos])
self.add_via_center(self.m1_stack,down_pos,rotate=90)
self.add_path("m2",[down_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
gnd_pins = self.msb_address_inst.get_pins("gnd")
# Only add the ground connection to the lowest metal2 rail in the flop array
# FIXME: SCMOS doesn't have a vertical rail in the cell, or we could use those
@@ -149,9 +149,9 @@ class sram_2bank(sram_base):
gnd_pos = gnd_pin.ur()
rail_pos = vector(gnd_pos.x,self.horz_control_bus_positions["gnd"].y)
self.add_path("m2",[gnd_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
# connect the MSB flop to the address input bus
self.add_via_center(self.m1_stack,rail_pos)
# connect the MSB flop to the address input bus
msb_pins = self.msb_address_inst.get_pins("din[0]")
for msb_pin in msb_pins:
if msb_pin.layer == "m3":
@@ -170,7 +170,7 @@ class sram_2bank(sram_base):
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_up_pos])
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_up_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
# Connect the output to select 1
msb_out_pin = self.msb_address_inst.get_pin("dout[0]")
msb_out_pos = msb_out_pin.rc()
@@ -180,21 +180,21 @@ class sram_2bank(sram_base):
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_down_pos])
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_down_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
# Connect clk
clk_pin = self.msb_address_inst.get_pin("clk")
clk_pos = clk_pin.bc()
rail_pos = self.horz_control_bus_positions["clk_buf"]
bend_pos = vector(clk_pos.x,self.horz_control_bus_positions["clk_buf"].y)
self.add_path("m1",[clk_pos,bend_pos,rail_pos])
def route(self):
""" Route all of the signals for the two bank SRAM. """
self.route_shared_banks()
# connect the horizontal control bus to the vertical bus
# connect the data output to the data bus
for n in self.data_bus_names:
@@ -220,21 +220,21 @@ class sram_2bank(sram_base):
self.add_via_center(self.m2_stack,rail_pos)
def add_lvs_correspondence_points(self):
"""
This adds some points for easier debugging if LVS goes wrong.
"""
This adds some points for easier debugging if LVS goes wrong.
These should probably be turned off by default though, since extraction
will show these as ports in the extracted netlist.
"""
if self.num_banks==1: return
for n in self.control_bus_names:
self.add_label(text=n,
layer="m2",
layer="m2",
offset=self.vert_control_bus_positions[n])
for n in self.bank_sel_bus_names:
self.add_label(text=n,
layer="m2",
layer="m2",
offset=self.vert_control_bus_positions[n])
+41 -41
View File
@@ -26,7 +26,7 @@ class sram_base(design, verilog, lef):
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)
@@ -46,7 +46,7 @@ class sram_base(design, verilog, lef):
for port in self.write_ports:
for bit in range(self.word_size + self.num_spare_cols):
self.add_pin("din{0}[{1}]".format(port, bit), "INPUT")
for port in self.all_ports:
for bit in range(self.addr_size):
self.add_pin("addr{0}[{1}]".format(port, bit), "INPUT")
@@ -64,7 +64,7 @@ class sram_base(design, verilog, lef):
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:
self.add_pin("csb{}".format(port), "INPUT")
for port in self.readwrite_ports:
@@ -80,7 +80,7 @@ class sram_base(design, verilog, lef):
for port in self.read_ports:
for bit in range(self.word_size + self.num_spare_cols):
self.add_pin("dout{0}[{1}]".format(port, bit), "OUTPUT")
self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND")
@@ -89,7 +89,7 @@ class sram_base(design, verilog, lef):
Add pex labels at the sram level for spice analysis
"""
# add pex labels for bitcells
for bank_num in range(len(self.bank_insts)):
@@ -103,13 +103,13 @@ class sram_base(design, verilog, lef):
br_offsets = pex_data[4]
bl_meta = pex_data[5]
br_meta = pex_data[6]
bl = []
br = []
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]]
@@ -166,21 +166,21 @@ class sram_base(design, verilog, lef):
def create_netlist(self):
""" Netlist creation """
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:
print_time("Submodules", datetime.datetime.now(), start_time)
def create_layout(self):
""" Layout creation """
start_time = datetime.datetime.now()
@@ -195,7 +195,7 @@ class sram_base(design, verilog, lef):
print_time("Routing", datetime.datetime.now(), start_time)
self.add_lvs_correspondence_points()
self.offset_all_coordinates()
highest_coord = self.find_highest_coords()
@@ -214,7 +214,7 @@ class sram_base(design, verilog, lef):
def create_modules(self):
debug.error("Must override pure virtual function.", -1)
def route_supplies(self):
""" Route the supply grid and connect the pins to them. """
@@ -244,10 +244,10 @@ class sram_base(design, verilog, lef):
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
self.num_vertical_line = self.addr_size + self.control_size + log(self.num_banks, 2) + 1
# data bus size
@@ -255,20 +255,20 @@ class sram_base(design, verilog, lef):
self.vertical_bus_width = self.m2_pitch * self.num_vertical_line
# vertical bus height depends on 2 or 4 banks
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
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
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)
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
@@ -304,7 +304,7 @@ class sram_base(design, verilog, lef):
offset=self.bank_sel_bus_offset,
names=self.bank_sel_bus_names,
length=self.vertical_bus_height))
# Horizontal data bus
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",
@@ -333,7 +333,7 @@ class sram_base(design, verilog, lef):
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
@@ -345,7 +345,7 @@ class sram_base(design, verilog, lef):
if self.num_banks>2:
self.msb_decoder = self.bank.decoder.pre2_4
self.add_mod(self.msb_decoder)
def add_modules(self):
self.bitcell = factory.create(module_type=OPTS.bitcell)
self.dff = factory.create(module_type="dff")
@@ -370,7 +370,7 @@ class sram_base(design, verilog, lef):
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)
@@ -383,7 +383,7 @@ class sram_base(design, verilog, lef):
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,
@@ -470,7 +470,7 @@ class sram_base(design, verilog, lef):
bank_mirror = "MY"
else:
bank_mirror = "R0"
bank_inst.place(offset=position,
mirror=bank_mirror,
rotate=bank_rotation)
@@ -483,7 +483,7 @@ class sram_base(design, verilog, lef):
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 = []
@@ -492,16 +492,16 @@ class sram_base(design, verilog, lef):
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 = []
@@ -510,7 +510,7 @@ class sram_base(design, verilog, lef):
outputs.append("a{}[{}]".format(port, bit))
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_data_dff(self):
@@ -523,7 +523,7 @@ class sram_base(design, verilog, lef):
else:
insts.append(None)
continue
# inputs, outputs/output/bar
inputs = []
outputs = []
@@ -532,7 +532,7 @@ class sram_base(design, verilog, lef):
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):
@@ -556,7 +556,7 @@ class sram_base(design, verilog, lef):
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 = []
@@ -578,7 +578,7 @@ class sram_base(design, verilog, lef):
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
return insts
def create_control_logic(self):
""" Add control logic instances """
@@ -590,7 +590,7 @@ class sram_base(design, verilog, lef):
mod = self.control_logic_w
else:
mod = self.control_logic_r
insts.append(self.add_inst(name="control{}".format(port), mod=mod))
# Inputs
@@ -608,9 +608,9 @@ class sram_base(design, verilog, lef):
temp.append("p_en_bar{}".format(port))
temp.extend(["wl_en{}".format(port), "clk_buf{}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
return insts
def sp_write(self, sp_name, lvs_netlist=False):
# Write the entire spice of the object to the file
############################################################
@@ -626,7 +626,7 @@ class sram_base(design, verilog, lef):
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"],
@@ -644,9 +644,9 @@ class sram_base(design, verilog, lef):
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()
+12 -12
View File
@@ -13,7 +13,7 @@ from sram_factory import factory
class sram_config:
""" This is a structure that is used to hold the SRAM configuration options. """
def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0):
self.word_size = word_size
self.num_words = num_words
@@ -29,7 +29,7 @@ class sram_config:
def set_local_config(self, module):
""" Copy all of the member variables to the given module for convenience """
members = [attr for attr in dir(self) if not callable(getattr(self, attr)) and not attr.startswith("__")]
# Copy all the variables to the local module
@@ -39,14 +39,14 @@ class sram_config:
def compute_sizes(self):
""" Computes the organization of the memory using bitcell size by trying to make it square."""
bitcell = factory.create(module_type="bitcell")
bitcell = factory.create(module_type=OPTS.bitcell)
debug.check(self.num_banks in [1, 2, 4],
"Valid number of banks are 1 , 2 and 4.")
self.num_words_per_bank = self.num_words / self.num_banks
self.num_bits_per_bank = self.word_size * self.num_words_per_bank
# If this was hard coded, don't dynamically compute it!
if not self.words_per_row:
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
@@ -64,18 +64,18 @@ class sram_config:
self.recompute_sizes()
def recompute_sizes(self):
"""
Calculate the auxiliary values assuming fixed number of words per row.
This can be called multiple times from the unit test when we reconfigure an
"""
Calculate the auxiliary values assuming fixed number of words per row.
This can be called multiple times from the unit test when we reconfigure an
SRAM for testing.
"""
debug.info(1, "Recomputing with words per row: {}".format(self.words_per_row))
# If the banks changed
self.num_words_per_bank = self.num_words / self.num_banks
self.num_bits_per_bank = self.word_size * self.num_words_per_bank
# Fix the number of columns and rows
self.num_cols = int(self.words_per_row * self.word_size)
self.num_rows_temp = int(self.num_words_per_bank / self.words_per_row)
@@ -116,11 +116,11 @@ class sram_config:
debug.check(tentative_num_rows * words_per_row <= 4096,
"Number of words exceeds 2048")
return int(words_per_row * tentative_num_rows / 512)
# Recompute the words per row given a hard min
if (not OPTS.is_unit_test and tentative_num_rows < 16):
debug.check(tentative_num_rows * words_per_row >= 16,
"Minimum number of rows is 16, but given {0}".format(tentative_num_rows))
return int(words_per_row * tentative_num_rows / 16)
return words_per_row