Merge branch 'dev' into datasheet_gen

This commit is contained in:
Jesse Cirimelli-Low 2018-12-07 04:29:07 -08:00
commit 3d9203a7ea
43 changed files with 445 additions and 262 deletions

View File

@ -1,93 +1,45 @@
TECH = scn4m_subm
CUR_DIR = $(shell pwd)
TEST_DIR = ${CUR_DIR}/tests
MAKEFLAGS += -j 2
MAKEFLAGS += -j 1
# Library test
LIBRARY_TESTS = \
01_library_drc_test.py \
02_library_lvs_test.py
LIBRARY_TESTS = $(shell find ${TEST_DIR} -name 0[1-2]*_test.py)
# Technology and DRC tests (along with ptx)
TECH_TESTS = \
03_contact_test.py \
03_ptx_1finger_pmos_test.py \
03_ptx_4finger_nmos_test.py \
03_path_test.py \
03_ptx_3finger_nmos_test.py \
03_ptx_4finger_pmos_test.py \
03_ptx_1finger_nmos_test.py \
03_ptx_3finger_pmos_test.py \
03_wire_test.py
TECH_TESTS = $(shell find ${TEST_DIR} -name 03*_test.py)
# Parameterized cells
PCELLS_TESTS = \
04_pinv_1x_test.py \
04_pinv_1x_beta_test.py \
04_pinv_2x_test.py \
04_pinv_10x_test.py \
04_pnand2_test.py \
04_pnor2_test.py \
04_pnand3_test.py\
04_wordline_driver_test.py \
04_precharge_test.py
CELL_TESTS = $(shell find ${TEST_DIR} -name 04*_test.py)
# Dynamically generated modules and arrays
MODULE_TESTS = \
05_bitcell_array_test.py \
06_hierarchical_decoder_test.py \
06_hierarchical_predecode2x4_test.py \
06_hierarchical_predecode3x8_test.py \
07_single_level_column_mux_array_test.py \
08_precharge_array_test.py \
09_sense_amp_array_test.py \
10_write_driver_array_test.py \
11_ms_flop_array_test.py \
12_tri_gate_array_test.py \
13_delay_chain_test.py \
14_replica_bitline_test.py \
16_control_logic_test.py
MODULE_TESTS = $(shell find ${TEST_DIR} -name 0[5-9]*_test.py)\
$(shell find ${TEST_DIR} -name 1*_test.py)
# Top-level SRAM configurations
TOP_TESTS = \
19_multi_bank_test.py \
19_single_bank_test.py \
20_sram_1bank_test.py \
20_sram_2bank_test.py \
20_sram_4bank_test.py
TOP_TESTS = $(shell find ${TEST_DIR} -name 20*_test.py)
# All simulation tests.
CHAR_TESTS = \
21_hspice_delay_test.py \
21_ngspice_delay_test.py \
21_ngspice_setuphold_test.py \
21_hspice_setuphold_test.py \
22_sram_func_test.py \
22_pex_func_test_with_pinv.py \
23_lib_sram_prune_test.py \
23_lib_sram_test.py
CHAR_TESTS = $(shell find ${TEST_DIR} -name 2[1-2]*_test.py)
# Keep the model lib test here since it is fast
# and doesn't need simulation.
USAGE_TESTS = \
23_lib_sram_model_test.py \
24_lef_sram_test.py \
25_verilog_sram_test.py
USAGE_TESTS = $(shell find ${TEST_DIR} -name 2[3-9]*_test.py)\
$(shell find ${TEST_DIR} -name 30*_test.py)
ALL_FILES = \
ALL_TESTS = \
${LIBRARY_TESTS} \
${TECH_TESTS} \
${PCELLS_TESTS} \
${MODULES_TESTS} \
${CELL_TESTS} \
${MODULE_TESTS} \
${TOP_TESTS} \
${CHAR_TESTS} \
${USAGE_TESTS}
default all:
.PHONY: ${ALL_TESTS}
$(ALL_FILES):
python ${TEST_DIR}/$@ -t freepdk45
python ${TEST_DIR}/$@ -t scn3me_subm
all: ${ALL_TESTS}
# Library tests
lib: ${LIBRARY_TESTS}
@ -96,10 +48,10 @@ lib: ${LIBRARY_TESTS}
tech: ${TECH_TESTS}
# Dynamically generated cells
pcells: ${PCELLS_TESTS}
cell: ${CELL_TESTS}
# Dynamically generated modules
modules: ${MODULES_TESTS}
module: ${MODULE_TESTS}
# Top level SRAM tests
top: ${TOP_TESTS}
@ -110,6 +62,9 @@ char: ${CHAR_TESTS}
# Usage and file generation
usage: ${USAGE_TESTS}
$(ALL_TESTS):
python3 $@ -t ${TECH}
clean:
find . -name \*.pyc -exec rm {} \;
find . -name \*~ -exec rm {} \;

View File

@ -59,7 +59,7 @@ def parse_args():
# This may be overridden when we read a config file though...
if OPTS.tech_name == "":
OPTS.tech_name = "scmos"
# Alias SCMOS to AMI 0.5um
# Alias SCMOS to 180nm
if OPTS.tech_name == "scmos":
OPTS.tech_name = "scn4m_subm"
@ -89,6 +89,7 @@ def print_banner():
print("|=========" + dev_info.center(60) + "=========|")
temp_info = "Temp dir: {}".format(OPTS.openram_temp)
print("|=========" + temp_info.center(60) + "=========|")
print("|=========" + "See LICENSE for license info".center(60) + "=========|")
print("|==============================================================================|")
@ -418,6 +419,9 @@ def report_status():
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size,
OPTS.num_words,
OPTS.num_banks))
print("RW ports: {0}\nR-only ports: {1}\nW-only ports: {2}".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports))
if OPTS.netlist_only:
print("Netlist only mode (no physical design is being done).")

View File

@ -26,6 +26,10 @@ if len(args) != 1:
# These depend on arguments, so don't load them until now.
import debug
# Keep track of running stats
start_time = datetime.datetime.now()
print_time("Start",start_time)
init_openram(config_file=args[0], is_unit_test=False)
# Only print banner here so it's not in unit tests
@ -34,10 +38,14 @@ print_banner()
# Output info about this run
report_status()
# Start importing design modules after we have the config file
import verify
from sram import sram
from sram_config import sram_config
# Configure the SRAM organization
c = sram_config(word_size=OPTS.word_size,
num_words=OPTS.num_words)
print("Words per row: {}".format(c.words_per_row))
#from parser import *
output_extensions = ["sp","v","lib","py"]
if OPTS.datasheet_gen:
@ -48,15 +56,8 @@ output_files = ["{0}.{1}".format(OPTS.output_name,x) for x in output_extensions]
print("Output files are: ")
print(*output_files,sep="\n")
# Keep track of running stats
start_time = datetime.datetime.now()
print_time("Start",start_time)
# Configure the SRAM organization
c = sram_config(word_size=OPTS.word_size,
num_words=OPTS.num_words)
# import SRAM test generation
from sram import sram
s = sram(sram_config=c,
name=OPTS.output_name)

227
compiler/pgates/pdriver.py Normal file
View File

@ -0,0 +1,227 @@
import debug
import pgate
import math
from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
class pdriver(pgate.pgate):
"""
This instantiates an even or odd number of inverters sized for driving a load.
"""
unique_id = 1
inv_list = []
inv_inst_list = []
calc_size_list = []
def __init__(self, height=None, name="", neg_polarity=False, c_load=8, size_list = []):
self.stage_effort = 4
self.row_height = height
self.neg_polarity = neg_polarity
self.size_list = size_list
self.c_load = c_load
if len(self.size_list) > 0 and (self.c_load != 8 or self.neg_polarity):
raise Exception("Cannot specify both size_list and neg_polarity or c_load.")
self.compute_sizes()
if name=="":
name = "pdriver_{0}_{1}_".format(self.num_inv, pdriver.unique_id)
pdriver.unique_id += 1
pgate.pgate.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def compute_sizes(self):
# size_list specified
if len(self.size_list) > 0:
if not len(self.size_list) % 2:
neg_polarity = True
self.num_inv = len(self.size_list)
else:
# find the number of stages
c_prev = int(round(self.c_load/self.stage_effort))
num_stages = 1
while c_prev > 1: #stop when the first stage is 1
c_prev = int(round(c_prev/self.stage_effort))
num_stages+=1
# find inv_num and compute sizes
if self.neg_polarity:
if (num_stages % 2 == 0): # if num_stages is even
self.diff_polarity(num_stages=num_stages)
else: # if num_stages is odd
self.same_polarity(num_stages=num_stages)
else: # positive polarity
if (num_stages % 2 == 0):
self.same_polarity(num_stages=num_stages)
else:
self.diff_polarity(num_stages=num_stages)
def same_polarity(self, num_stages):
self.num_inv = num_stages
# compute sizes
c_prev = self.c_load
for x in range(self.num_inv-1,-1,-1):
c_prev = int(round(c_prev/self.stage_effort))
self.calc_size_list.append(c_prev)
def diff_polarity(self, num_stages):
# find which delay is smaller
delay_below = ((num_stages-1)*(self.c_load**(1/num_stages-1))) + num_stages-1
delay_above = ((num_stages+1)*(self.c_load**(1/num_stages+1))) + num_stages+1
if (delay_above < delay_below):
# recompute stage_effort for this delay
self.num_inv = num_stages+1
polarity_stage_effort = self.c_load**(1/self.num_inv)
else:
self.num_inv = num_stages-1
polarity_stage_effort = self.c_load**(1/self.num_inv)
# compute sizes
c_prev = self.c_load
for x in range(self.num_inv-1,-1,-1):
c_prev = int(round(c_prev/polarity_stage_effort))
self.calc_size_list.append(c_prev)
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_insts()
def create_layout(self):
self.width = self.num_inv * self.inv_list[0].width
self.height = self.inv_list[0].height
self.place_modules()
self.route_wires()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
self.add_pin("A")
self.add_pin("Z")
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
if len(self.size_list) > 0: # size list specified
for x in range(len(self.size_list)):
self.inv_list.append(pinv(size=self.size_list[x], height=self.row_height))
self.add_mod(self.inv_list[x])
else: # find inv sizes
for x in range(len(self.calc_size_list)):
self.inv_list.append(pinv(size=self.calc_size_list[x], height=self.row_height))
self.add_mod(self.inv_list[x])
def create_insts(self):
for x in range(1,self.num_inv+1):
# Create first inverter
if x == 1:
zbx_int = "Zb{}_int".format(x);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
if self.num_inv == 1:
self.connect_inst(["A", "Z", "vdd", "gnd"])
else:
self.connect_inst(["A", zbx_int, "vdd", "gnd"])
# Create last inverter
elif x == self.num_inv:
zbn_int = "Zb{}_int".format(x-1);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
self.connect_inst([zbn_int, "Z", "vdd", "gnd"])
# Create middle inverters
else:
zbx_int = "Zb{}_int".format(x-1);
zbn_int = "Zb{}_int".format(x);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
self.connect_inst([zbx_int, zbn_int, "vdd", "gnd"])
def place_modules(self):
# Add INV1 to the left
self.inv_inst_list[0].place(vector(0,0))
# Add inverters to the right of INV1
for x in range(1,len(self.inv_inst_list)):
self.inv_inst_list[x].place(vector(self.inv_inst_list[x-1].rx(),0))
def route_wires(self):
z_inst_list = []
a_inst_list = []
# inv_current Z to inv_next A
for x in range(0,len(self.inv_inst_list)-1):
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
a_inst_list.append(self.inv_inst_list[x+1].get_pin("A"))
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
self.add_path("metal1", [z_inst_list[x].center(), mid_point, a_inst_list[x].center()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin=self.inv_inst_list[0].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
offset=vdd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
# Continous gnd rail along with label.
gnd_pin=self.inv_inst_list[0].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
offset=gnd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
z_pin = self.inv_inst_list[len(self.inv_inst_list)-1].get_pin("Z")
self.add_layout_pin_rect_center(text="Z",
layer=z_pin.layer,
offset=z_pin.center(),
width = z_pin.width(),
height = z_pin.height())
a_pin = self.inv_inst_list[0].get_pin("A")
self.add_layout_pin_rect_center(text="A",
layer=a_pin.layer,
offset=a_pin.center(),
width = a_pin.width(),
height = a_pin.height())
def analytical_delay(self, slew, load=0.0):
"""Calculate the analytical delay of INV1 -> ... -> INVn"""
delay = 0;
if len(self.inv_inst_list) == 1:
delay = self.inv_inst_list[x].analytical_delay(slew=slew);
else:
for x in range(len(self.inv_inst_list-1)):
load_next = 0.0
for n in range(x,len(self.inv_inst_list+1)):
load_next += self.inv_inst_list[x+1]
if x == 1:
delay += self.inv_inst_list[x].analytical_delay(slew=slew,
load=load_next)
else:
delay += self.inv_inst_list[x+1].analytical_delay(slew=delay.slew,
load=load_next)
return delay

View File

@ -70,8 +70,7 @@ class router(router_tech):
self.boundary = self.layout.measureBoundary(self.top_name)
# These must be un-indexed to get rid of the matrix type
self.ll = vector(self.boundary[0][0], self.boundary[0][1])
# Pad the UR by a few tracks to add an extra rail possibly
self.ur = vector(self.boundary[1][0], self.boundary[1][1]) + self.track_widths.scale(5,5)
self.ur = vector(self.boundary[1][0], self.boundary[1][1])
def clear_pins(self):
"""
@ -130,12 +129,8 @@ class router(router_tech):
Pin can either be a label or a location,layer pair: [[x,y],layer].
"""
debug.info(1,"Finding pins for {}.".format(pin_name))
#start_time = datetime.now()
self.retrieve_pins(pin_name)
#print_time("Retrieved pins",datetime.now(), start_time)
#start_time = datetime.now()
self.analyze_pins(pin_name)
#print_time("Analyzed pins",datetime.now(), start_time)
def find_blockages(self):
"""
@ -160,41 +155,26 @@ class router(router_tech):
# This will get all shapes as blockages and convert to grid units
# This ignores shapes that were pins
#start_time = datetime.now()
self.find_blockages()
#print_time("Find blockags",datetime.now(), start_time)
# Convert the blockages to grid units
#start_time = datetime.now()
self.convert_blockages()
#print_time("Find blockags",datetime.now(), start_time)
# This will convert the pins to grid units
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
#start_time = datetime.now()
for pin in pin_list:
self.convert_pins(pin)
#print_time("Convert pins",datetime.now(), start_time)
#start_time = datetime.now()
#for pin in pin_list:
# self.combine_adjacent_pins(pin)
#print_time("Combine pins",datetime.now(), start_time)
#self.write_debug_gds("debug_combine_pins.gds",stop_program=True)
# Combine adjacent pins into pin groups to reduce run-time
for pin in pin_list:
self.combine_adjacent_pins(pin)
# Separate any adjacent grids of differing net names that overlap
# Must be done before enclosing pins
#start_time = datetime.now()
self.separate_adjacent_pins(0)
#print_time("Separate pins",datetime.now(), start_time)
# For debug
#self.separate_adjacent_pins(1)
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
#start_time = datetime.now()
self.enclose_pins()
#print_time("Enclose pins",datetime.now(), start_time)
#self.write_debug_gds("debug_enclose_pins.gds",stop_program=True)
def combine_adjacent_pins(self, pin_name):
@ -257,18 +237,19 @@ class router(router_tech):
This will try to separate all grid pins by the supplied number of separation
tracks (default is to prevent adjacency).
"""
debug.info(1,"Separating adjacent pins.")
# Commented out to debug with SCMOS
#if separation==0:
# return
pin_names = self.pin_groups.keys()
for pin_name1 in pin_names:
for pin_name2 in pin_names:
if pin_name1==pin_name2:
continue
self.separate_adjacent_pin(pin_name1, pin_name2, separation)
pin_names = self.pin_groups.keys()
for i,pin_name1 in enumerate(pin_names):
for j,pin_name2 in enumerate(pin_names):
if i==j:
continue
if i>j:
return
self.separate_adjacent_pin(pin_name1, pin_name2, separation)
def separate_adjacent_pin(self, pin_name1, pin_name2, separation):
"""
Go through all of the pin groups and check if any other pin group is
@ -277,13 +258,18 @@ class router(router_tech):
Try to do this intelligently to keep th pins enclosed.
"""
debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2))
removed_grids = 0
for index1,pg1 in enumerate(self.pin_groups[pin_name1]):
for index2,pg2 in enumerate(self.pin_groups[pin_name2]):
adj_grids = pg1.adjacent_grids(pg2, separation)
removed_grids += len(adj_grids)
# These should have the same length, so...
if len(adj_grids)>0:
debug.info(2,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids))
debug.info(3,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids))
self.remove_adjacent_grid(pg1, pg2, adj_grids)
debug.info(1,"Removed {} adjacent grids.".format(removed_grids))
def remove_adjacent_grid(self, pg1, pg2, adj_grids):
"""
@ -304,12 +290,12 @@ class router(router_tech):
# If the adjacent grids are a subset of the secondary grids (i.e. not necessary)
# remove them from each
if adj in bigger.secondary_grids:
debug.info(2,"Removing {} from bigger secondary {}".format(adj, bigger))
debug.info(3,"Removing {} from bigger secondary {}".format(adj, bigger))
bigger.grids.remove(adj)
bigger.secondary_grids.remove(adj)
self.blocked_grids.add(adj)
elif adj in smaller.secondary_grids:
debug.info(2,"Removing {} from smaller secondary {}".format(adj, smaller))
debug.info(3,"Removing {} from smaller secondary {}".format(adj, smaller))
smaller.grids.remove(adj)
smaller.secondary_grids.remove(adj)
self.blocked_grids.add(adj)
@ -317,10 +303,10 @@ class router(router_tech):
# If we couldn't remove from a secondary grid, we must remove from the primary
# grid of at least one pin
if adj in bigger.grids:
debug.info(2,"Removing {} from bigger primary {}".format(adj, bigger))
debug.info(3,"Removing {} from bigger primary {}".format(adj, bigger))
bigger.grids.remove(adj)
elif adj in smaller.grids:
debug.info(2,"Removing {} from smaller primary {}".format(adj, smaller))
debug.info(3,"Removing {} from smaller primary {}".format(adj, smaller))
smaller.grids.remove(adj)
@ -361,17 +347,6 @@ class router(router_tech):
self.set_blockages(blockage_grids,False)
# def translate_coordinates(self, coord, mirr, angle, xyShift):
# """
# Calculate coordinates after flip, rotate, and shift
# """
# coordinate = []
# for item in coord:
# x = (item[0]*math.cos(angle)-item[1]*mirr*math.sin(angle)+xyShift[0])
# y = (item[0]*math.sin(angle)+item[1]*mirr*math.cos(angle)+xyShift[1])
# coordinate += [(x, y)]
# return coordinate
def convert_shape_to_units(self, shape):
"""
Scale a shape (two vector list) to user units
@ -498,11 +473,6 @@ class router(router_tech):
# and the track points are at the center
ll = ll.round()
ur = ur.round()
# if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5:
# debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
# debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
# pin=self.convert_track_to_shape(ll)
# debug.info(0,"Pin {}".format(pin))
return [ll,ur]
def convert_pin_to_tracks(self, pin_name, pin, expansion=0):
@ -558,7 +528,6 @@ class router(router_tech):
"""
Find a list of the single pin with the most overlap.
"""
#print("INSUFFICIENT LIST",insufficient_list)
# Find the coordinate with the most overlap
best_coord = None
best_overlap = -math.inf
@ -579,7 +548,6 @@ class router(router_tech):
Get a grid cell that is the furthest from the blocked grids.
"""
#print("INSUFFICIENT LIST",insufficient_list)
# Find the coordinate with the most overlap
best_coord = None
best_dist = math.inf
@ -596,7 +564,6 @@ class router(router_tech):
Given a pin and a list of grid cells (probably non-overlapping),
return the nearest grid cell (center to center).
"""
#print("INSUFFICIENT LIST",insufficient_list)
# Find the coordinate with the most overlap
best_coord = None
best_dist = math.inf
@ -638,10 +605,6 @@ class router(router_tech):
else:
debug.info(2," No overlap: {0} {1}".format(overlap_length,0))
return (None,None)
def convert_track_to_pin(self, track):
@ -764,8 +727,6 @@ class router(router_tech):
pg.enclose_pin()
pg.add_enclosure(self.cell)
#self.write_debug_gds("pin_debug.gds", False)
def add_source(self, pin_name):
"""
This will mark the grids for all pin components as a source.
@ -835,9 +796,6 @@ class router(router_tech):
"""
debug.info(4,"Set path: " + str(path))
# Keep track of path for future blockages
#path.set_blocked()
# This is marked for debug
path.set_path()
@ -906,44 +864,10 @@ class router(router_tech):
(abs_ll,unused) = pin.rect
pin = self.convert_track_to_pin(ur)
(unused,abs_ur) = pin.rect
#print("enclose ll={0} ur={1}".format(ll,ur))
#print("enclose ll={0} ur={1}".format(abs_ll,abs_ur))
pin = pin_layout(name, [abs_ll, abs_ur], layer)
return pin
# def compute_wide_enclosure(self, ll, ur, zindex, name=""):
# """
# Enclose the tracks from ll to ur in a single rectangle that meets the track DRC rules.
# """
# # Find the pin enclosure of the whole track shape (ignoring DRCs)
# (abs_ll,unused) = self.convert_track_to_shape(ll)
# (unused,abs_ur) = self.convert_track_to_shape(ur)
# # Get the layer information
# x_distance = abs(abs_ll.x-abs_ur.x)
# y_distance = abs(abs_ll.y-abs_ur.y)
# shape_width = min(x_distance, y_distance)
# shape_length = max(x_distance, y_distance)
# # Get the DRC rule for the grid dimensions
# (width, space) = self.get_supply_layer_width_space(zindex)
# layer = self.get_layer(zindex)
# if zindex==0:
# spacing = vector(0.5*self.track_width, 0.5*space)
# else:
# spacing = vector(0.5*space, 0.5*self.track_width)
# # Compute the shape offsets with correct spacing
# new_ll = abs_ll + spacing
# new_ur = abs_ur - spacing
# pin = pin_layout(name, [new_ll, new_ur], layer)
# return pin
def contract_path(self,path):
"""

View File

@ -48,9 +48,9 @@ class router_tech:
self.track_width = max(self.horiz_track_width,self.vert_track_width)
debug.info(1,"Track width: {:.3f}".format(self.track_width))
self.track_space = max(self.horiz_layer_spacing,self.vert_layer_spacing)
debug.info(1,"Track spacing: {:.3f}".format(self.track_space))
debug.info(1,"Track space: {:.3f}".format(self.track_space))
self.track_wire = self.track_width - self.track_space
debug.info(1,"Wire width: {:.3f}".format(self.track_wire))
debug.info(1,"Track wire width: {:.3f}".format(self.track_wire))
self.track_widths = vector([self.track_width] * 2)
self.track_factor = vector([1/self.track_width] * 2)

View File

@ -64,17 +64,10 @@ class supply_router(router):
# but this is simplest for now.
self.create_routing_grid()
# Compute the grid dimensions
self.compute_supply_rail_dimensions()
# Get the pin shapes
#start_time = datetime.now()
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
#print_time("Pins and blockages",datetime.now(), start_time)
#self.write_debug_gds("pin_enclosures.gds",stop_program=True)
# Add the supply rails in a mesh network and connect H/V with vias
#start_time = datetime.now()
# Block everything
self.prepare_blockages(self.gnd_name)
# Determine the rail locations
@ -84,23 +77,15 @@ class supply_router(router):
self.prepare_blockages(self.vdd_name)
# Determine the rail locations
self.route_supply_rails(self.vdd_name,1)
#self.write_debug_gds("debug_rails.gds",stop_program=True)
#print_time("Supply rails",datetime.now(), start_time)
#start_time = datetime.now()
self.route_simple_overlaps(vdd_name)
self.route_simple_overlaps(gnd_name)
#print_time("Simple overlaps",datetime.now(), start_time)
#self.write_debug_gds("debug_simple_route.gds",stop_program=False)
# Route the supply pins to the supply rails
# Route vdd first since we want it to be shorter
#start_time = datetime.now()
self.route_pins_to_rails(vdd_name)
self.route_pins_to_rails(gnd_name)
#print_time("Routing",datetime.now(), start_time)
#self.write_debug_gds("debug_pin_routes.gds",stop_program=True)
#self.write_debug_gds("final.gds",False)
return True
@ -116,7 +101,7 @@ class supply_router(router):
# These are the wire tracks
wire_tracks = self.supply_rail_tracks[pin_name]
routed_count=0
for pg in self.pin_groups[pin_name]:
if pg.is_routed():
continue
@ -124,6 +109,7 @@ class supply_router(router):
# First, check if we just overlap, if so, we are done.
overlap_grids = wire_tracks & pg.grids
if len(overlap_grids)>0:
routed_count += 1
pg.set_routed()
continue
@ -131,7 +117,7 @@ class supply_router(router):
#pg.create_simple_overlap_enclosure(pg.grids)
#pg.add_enclosure(self.cell)
debug.info(1,"Routed {} simple overlap pins".format(routed_count))
def finalize_supply_rails(self, name):
"""
@ -227,40 +213,6 @@ class supply_router(router):
width=pin.width(),
height=pin.height())
def compute_supply_rail_dimensions(self):
"""
Compute the supply rail dimensions including wide metal spacing rules.
"""
self.max_yoffset = self.rg.ur.y
self.max_xoffset = self.rg.ur.x
# # Longest length is conservative
# rail_length = max(self.max_yoffset,self.max_xoffset)
# # Convert the number of tracks to dimensions to get the design rule spacing
# rail_width = self.track_width*self.rail_track_width
# # Get the conservative width and spacing of the top rails
# (horizontal_width, horizontal_space) = self.get_supply_layer_width_space(0)
# (vertical_width, vertical_space) = self.get_supply_layer_width_space(1)
# width = max(horizontal_width, vertical_width)
# space = max(horizontal_space, vertical_space)
# track_pitch = width + space
# # Determine the pitch (in tracks) of the rail wire + spacing
# self.supply_rail_width = math.ceil(track_pitch/self.track_width)
# debug.info(1,"Rail step: {}".format(self.supply_rail_width))
# # Conservatively determine the number of tracks that the rail actually occupies
# space_tracks = math.ceil(space/self.track_width)
# self.supply_rail_wire_width = self.supply_rail_width - space_tracks
# debug.info(1,"Rail wire tracks: {}".format(self.supply_rail_wire_width))
# total_space = self.supply_rail_width - self.supply_rail_wire_width
# self.supply_rail_space_width = math.floor(0.5*total_space)
# debug.info(1,"Rail space tracks: {} (on both sides)".format(self.supply_rail_space_width))
def compute_supply_rails(self, name, supply_number):
"""
Compute the unblocked locations for the horizontal and vertical supply rails.
@ -270,14 +222,19 @@ class supply_router(router):
self.supply_rails[name]=[]
start_offset = supply_number
max_yoffset = self.rg.ur.y
max_xoffset = self.rg.ur.x
min_yoffset = self.rg.ll.y
min_xoffset = self.rg.ll.x
# Horizontal supply rails
for offset in range(start_offset, self.max_yoffset, 2):
start_offset = min_yoffset + supply_number
for offset in range(start_offset, max_yoffset, 2):
# Seed the function at the location with the given width
wave = [vector3d(0,offset,0)]
wave = [vector3d(min_xoffset,offset,0)]
# While we can keep expanding east in this horizontal track
while wave and wave[0].x < self.max_xoffset:
while wave and wave[0].x < max_xoffset:
added_rail = self.find_supply_rail(name, wave, direction.EAST)
if not added_rail:
# Just seed with the next one
@ -287,12 +244,12 @@ class supply_router(router):
wave = added_rail.neighbor(direction.EAST)
# Vertical supply rails
max_offset = self.rg.ur.x
for offset in range(start_offset, self.max_xoffset, 2):
start_offset = min_xoffset + supply_number
for offset in range(start_offset, max_xoffset, 2):
# Seed the function at the location with the given width
wave = [vector3d(offset,0,1)]
wave = [vector3d(offset,min_yoffset,1)]
# While we can keep expanding north in this vertical track
while wave and wave[0].y < self.max_yoffset:
while wave and wave[0].y < max_yoffset:
added_rail = self.find_supply_rail(name, wave, direction.NORTH)
if not added_rail:
# Just seed with the next one
@ -410,8 +367,8 @@ class supply_router(router):
"""
remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name])
debug.info(1,"Routing {0} with {1} pin components to route.".format(pin_name,
remaining_components))
debug.info(1,"Maze routing {0} with {1} pin components to connect.".format(pin_name,
remaining_components))
for index,pg in enumerate(self.pin_groups[pin_name]):
if pg.is_routed():

View File

@ -14,7 +14,6 @@ class sram():
"""
def __init__(self, sram_config, name):
sram_config.compute_sizes()
sram_config.set_local_config(self)
# reset the static duplicate name checker for unit tests

View File

@ -10,6 +10,7 @@ from globals import OPTS, print_time
from sram_base import sram_base
from bank import bank
from contact import m2m3
from dff_buf_array import dff_buf_array
from dff_array import dff_array
@ -21,11 +22,6 @@ class sram_1bank(sram_base):
def __init__(self, name, sram_config):
sram_base.__init__(self, name, sram_config)
def create_netlist(self):
sram_base.create_netlist(self)
self.create_modules()
def create_modules(self):
"""
This adds the modules for a single bank SRAM with control
@ -207,9 +203,8 @@ class sram_1bank(sram_base):
offset=clk_steiner_pos,
rotate=90)
# Note, the via to the control logic is taken care of when we route
# the control logic to the bank
self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, clk_steiner_pos, control_clk_buf_pos])
# Note, the via to the control logic is taken care of above
self.add_wire(("metal3","via2","metal2"),[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")
@ -221,6 +216,9 @@ class sram_1bank(sram_base):
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
data_dff_clk_pos = data_dff_clk_pin.center()
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
# In some designs, the steiner via will be too close to the mid_pos via
# so make the wire as wide as the contacts
self.add_path("metal2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])

View File

@ -2,6 +2,7 @@ import sys
import datetime
import getpass
import debug
from datetime import datetime
from importlib import reload
from vector import vector
from globals import OPTS, print_time
@ -63,37 +64,52 @@ class sram_base(design):
def create_netlist(self):
""" Netlist creation """
start_time = 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.now(), start_time)
def create_layout(self):
""" Layout creation """
start_time = datetime.now()
self.place_instances()
if not OPTS.is_unit_test:
print_time("Placement",datetime.now(), start_time)
start_time = datetime.now()
self.route_layout()
self.route_supplies()
if not OPTS.is_unit_test:
print_time("Routing",datetime.now(), start_time)
self.add_lvs_correspondence_points()
self.offset_all_coordinates()
# Must be done after offsetting lower-left
self.route_supplies()
highest_coord = self.find_highest_coords()
self.width = highest_coord[0]
self.height = highest_coord[1]
start_time = datetime.now()
self.DRC_LVS(final_verification=True)
if not OPTS.is_unit_test:
print_time("Verification",datetime.now(), start_time)
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. """

View File

@ -14,7 +14,7 @@ class sram_config:
# This will get over-written when we determine the organization
self.words_per_row = None
# Move the module names to this?
self.compute_sizes()
def set_local_config(self, module):
@ -54,6 +54,20 @@ class sram_config:
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
debug.info(1,"Words per row: {}".format(self.words_per_row))
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
SRAM for testing.
"""
# 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 = int(self.num_words_per_bank/self.words_per_row)
@ -64,7 +78,6 @@ class sram_config:
self.bank_addr_size = self.col_addr_size + self.row_addr_size
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
debug.info(1,"Words per row: {}".format(self.words_per_row))
def estimate_words_per_row(self,tentative_num_cols, word_size):
"""
@ -74,10 +87,14 @@ class sram_config:
if tentative_num_cols < 1.5*word_size:
return 1
elif tentative_num_cols > 3*word_size:
elif tentative_num_cols < 3*word_size:
return 2
elif tentative_num_cols < 6*word_size:
return 4
else:
return 2
if tentative_num_cols > 16*word_size:
debug.warning("Reaching column mux size limit. Consider increasing above 8-way.")
return 8
def amend_words_per_row(self,tentative_num_rows, words_per_row):
"""

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
"""
Run a regression test on a 2-row buffer cell
"""
import unittest
from testutils import header,openram_test
import sys,os
sys.path.append(os.path.join(sys.path[0],".."))
import globals
from globals import OPTS
import debug
@unittest.skip("SKIPPING 04_pdriver_test, LVS error in FreePDK45")
class pdriver_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
global verify
import verify
import pdriver
debug.info(2, "Testing inverter/buffer 4x 8x")
# a tests the error message for specifying conflicting conditions
#a = pdriver.pdriver(c_load = 4,size_list = [1,2,4,8])
b = pdriver.pdriver(size_list = [1,2,4,8])
c = pdriver.pdriver(c_load = 50)
d = pdriver.pdriver(c_load = 50, neg_polarity = True)
e = pdriver.pdriver(c_load = 64)
f = pdriver.pdriver(c_load = 64, neg_polarity = True)
#self.local_check(a)
self.local_check(b)
self.local_check(c)
self.local_check(d)
self.local_check(e)
self.local_check(f)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -24,18 +24,21 @@ class multi_bank_test(openram_test):
c.num_banks=2
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "No column mux")
a = bank(c, name="bank1_multi")
self.local_check(a)
c.num_words=32
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = bank(c, name="bank2_multi")
self.local_check(a)
c.num_words=64
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = bank(c, name="bank3_multi")
self.local_check(a)
@ -43,6 +46,7 @@ class multi_bank_test(openram_test):
c.word_size=2
c.num_words=128
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = bank(c, name="bank4_multi")
self.local_check(a)

View File

@ -31,6 +31,7 @@ class psingle_bank_test(openram_test):
num_words=16)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "No column mux")
name = "bank1_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name)
@ -38,6 +39,7 @@ class psingle_bank_test(openram_test):
c.num_words=32
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two way column mux")
name = "bank2_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name)
@ -45,6 +47,7 @@ class psingle_bank_test(openram_test):
c.num_words=64
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Four way column mux")
name = "bank3_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name)
@ -53,6 +56,7 @@ class psingle_bank_test(openram_test):
c.word_size=2
c.num_words=128
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Four way column mux")
name = "bank4_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name)

View File

@ -30,6 +30,7 @@ class psram_1bank_2mux_1rw_1w_test(openram_test):
num_banks=1)
c.num_words=32
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -30,6 +30,7 @@ class psram_1bank_2mux_1w_1r_test(openram_test):
num_banks=1)
c.num_words=32
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -31,6 +31,7 @@ class psram_1bank_2mux_test(openram_test):
num_banks=1)
c.num_words=32
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class psram_1bank_4mux_1rw_1r_test(openram_test):
num_banks=1)
c.num_words=64
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_2mux_1rw_1r_test(openram_test):
num_banks=1)
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_2mux_test(openram_test):
num_banks=1)
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_4mux_test(openram_test):
num_banks=1)
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_8mux_1rw_1r_test(openram_test):
num_banks=1)
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_8mux_test(openram_test):
num_banks=1)
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_nomux_1rw_1r_test(openram_test):
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_nomux_test(openram_test):
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -23,18 +23,21 @@ class sram_2bank_test(openram_test):
num_banks=2)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Two bank, no column mux with control logic")
a = sram(c, "sram1")
self.local_check(a, final_verification=True)
c.num_words=64
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two bank two way column mux with control logic")
a = sram(c, "sram2")
self.local_check(a, final_verification=True)
c.num_words=128
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Two bank, four way column mux with control logic")
a = sram(c, "sram3")
self.local_check(a, final_verification=True)
@ -42,6 +45,7 @@ class sram_2bank_test(openram_test):
c.word_size=2
c.num_words=256
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Two bank, eight way column mux with control logic")
a = sram(c, "sram4")
self.local_check(a, final_verification=True)

View File

@ -30,6 +30,7 @@ class timing_sram_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram(c, name="sram1")

View File

@ -30,6 +30,7 @@ class timing_sram_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram(c, name="sram1")

View File

@ -35,6 +35,7 @@ class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test):
num_words=64,
num_banks=1)
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -35,6 +35,7 @@ class psram_1bank_4mux_func_test(openram_test):
num_words=256,
num_banks=1)
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -35,6 +35,7 @@ class psram_1bank_8mux_func_test(openram_test):
num_words=256,
num_banks=1)
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -35,6 +35,7 @@ class psram_1bank_nomux_func_test(openram_test):
num_words=32,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports,

View File

@ -30,6 +30,7 @@ class sram_1bank_2mux_func_test(openram_test):
num_words=64,
num_banks=1)
c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,

View File

@ -30,6 +30,7 @@ class sram_1bank_4mux_func_test(openram_test):
num_words=256,
num_banks=1)
c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,

View File

@ -33,6 +33,7 @@ class sram_1bank_8mux_func_test(openram_test):
num_words=256,
num_banks=1)
c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,

View File

@ -30,6 +30,7 @@ class sram_1bank_nomux_func_test(openram_test):
num_words=32,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,

View File

@ -35,6 +35,7 @@ class psram_1bank_nomux_func_test(openram_test):
num_words=32,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,

View File

@ -23,6 +23,7 @@ class lib_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -32,6 +32,7 @@ class lib_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -32,6 +32,7 @@ class lib_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -23,6 +23,7 @@ class lef_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -22,6 +22,7 @@ class verilog_test(openram_test):
num_words=16,
num_banks=1)
c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -39,7 +39,7 @@ class worst_case_timing_sram_test(openram_test):
num_words=num_words,
num_banks=num_banks)
c.words_per_row=1
#c.compute_sizes()
c.recompute_sizes()
debug.info(1, "Testing the timing different bitecells inside a {}bit, {} words SRAM with {} bank".format(
word_size, num_words, num_banks))
s = sram(c, name="sram1")