Merge branch 'tech_migration' into dev

This commit is contained in:
mrg 2020-06-10 17:09:05 -07:00
commit dff28a9997
22 changed files with 340 additions and 103 deletions

View File

@ -172,6 +172,20 @@ class design(hierarchy_design):
self.well_extend_active = max(self.well_extend_active, self.nwell_extend_active)
if "pwell" in layer:
self.well_extend_active = max(self.well_extend_active, self.pwell_extend_active)
# The active offset is due to the well extension
if "pwell" in layer:
self.pwell_enclose_active = drc("pwell_enclose_active")
else:
self.pwell_enclose_active = 0
if "nwell" in layer:
self.nwell_enclose_active = drc("nwell_enclose_active")
else:
self.nwell_enclose_active = 0
# Use the max of either so that the poly gates will align properly
self.well_enclose_active = max(self.pwell_enclose_active,
self.nwell_enclose_active,
self.active_space)
# These are for debugging previous manual rules
if False:

View File

@ -695,8 +695,8 @@ class layout():
# we should add a boundary just for DRC in some technologies
if not self.is_library_cell and not self.bounding_box:
# If there is a boundary layer, and we didn't create one, add one.
if "stdc" in techlayer.keys():
boundary_layer = "stdc"
if "boundary" in techlayer.keys():
boundary_layer = "boundary"
boundary = [self.find_lowest_coords(),
self.find_highest_coords()]
debug.check(boundary[0] and boundary[1], "No shapes to make a boundary.")
@ -1259,10 +1259,7 @@ class layout():
if OPTS.netlist_only:
return
if "stdc" in techlayer.keys():
boundary_layer = "stdc"
else:
boundary_layer = "boundary"
boundary_layer = "boundary"
if not ur:
self.bounding_box = self.add_rect(layer=boundary_layer,
offset=ll,
@ -1307,13 +1304,10 @@ class layout():
pin.ll(),
pin.width(),
pin.height())
elif pin.layer == "m1":
self.add_power_pin(name, pin.center())
else:
debug.warning("{0} pins of {1} should be on {2} or metal1 for "\
"supply router."
.format(name, inst.name, self.pwr_grid_layer))
else:
self.add_power_pin(name, pin.center(), start_layer=pin.layer)
def add_power_pin(self, name, loc, size=[1, 1], directions=None, start_layer="m1"):
"""
Add a single power pin from the lowest power_grid layer down to M1 (or li) at

View File

@ -7,7 +7,7 @@
#
import debug
import design
from tech import parameter
from tech import parameter, layer
from tech import cell_properties as props
from vector import vector
from globals import OPTS
@ -52,7 +52,6 @@ class dff_buf(design.design):
def create_layout(self):
self.place_instances()
self.width = self.inv2_inst.rx()
self.height = self.dff.height
self.route_wires()
self.add_layout_pins()
@ -120,39 +119,37 @@ class dff_buf(design.design):
except AttributeError:
pass
self.inv1_inst.place(vector(self.dff_inst.rx() + well_spacing + self.well_extend_active, 0))
# Add INV2 to the right
self.inv2_inst.place(vector(self.inv1_inst.rx(), 0))
def route_wires(self):
if "li" in layer:
self.route_layer = "li"
else:
self.route_layer = "m1"
# Route dff q to inv1 a
q_pin = self.dff_inst.get_pin("Q")
a1_pin = self.inv1_inst.get_pin("A")
mid_x_offset = 0.5 * (a1_pin.cx() + q_pin.cx())
mid1 = vector(mid_x_offset, q_pin.cy())
mid2 = vector(mid_x_offset, a1_pin.cy())
self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()])
self.add_via_center(layers=self.m2_stack,
offset=q_pin.center())
self.add_via_center(layers=self.m2_stack,
offset=a1_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=a1_pin.center())
mid1 = vector(a1_pin.cx(), q_pin.cy())
self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()])
self.add_via_stack_center(from_layer=a1_pin.layer,
to_layer=q_pin.layer,
offset=a1_pin.center())
# Route inv1 z to inv2 a
z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A")
mid_x_offset = 0.5 * (z1_pin.cx() + a2_pin.cx())
self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy())
mid2 = vector(mid_x_offset, a2_pin.cy())
self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()])
self.mid_qb_pos = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_pin.cy())
self.add_zjog(z1_pin.layer, z1_pin.center(), a2_pin.center())
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin=self.dff_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="m1",
layer=vdd_pin.layer,
offset=vdd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -160,7 +157,7 @@ class dff_buf(design.design):
# Continous gnd rail along with label.
gnd_pin=self.dff_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="m1",
layer=gnd_pin.layer,
offset=gnd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -185,17 +182,20 @@ class dff_buf(design.design):
self.add_layout_pin_rect_center(text="Q",
layer="m2",
offset=q_pos)
self.add_path("m1", [dout_pin.center(), mid_pos, q_pos])
self.add_via_center(layers=self.m1_stack,
offset=q_pos)
self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos])
self.add_via_stack_center(from_layer=dout_pin.layer,
to_layer="m2",
offset=q_pos)
qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch)
self.add_layout_pin_rect_center(text="Qb",
layer="m2",
offset=qb_pos)
self.add_path("m1", [self.mid_qb_pos, qb_pos])
self.add_via_center(layers=self.m1_stack,
offset=qb_pos)
self.add_path(self.route_layer, [self.mid_qb_pos, qb_pos])
a2_pin = self.inv2_inst.get_pin("A")
self.add_via_stack_center(from_layer=a2_pin.layer,
to_layer="m2",
offset=qb_pos)
def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""

View File

@ -154,7 +154,7 @@ class replica_column(design.design):
bl_pin = self.cell_inst[0].get_pin(bl_name)
self.add_layout_pin(text=bl_name,
layer=bl_pin.layer,
offset=bl_pin.ll(),
offset=bl_pin.ll().scale(1, 0),
width=bl_pin.width(),
height=self.height)

View File

@ -46,7 +46,8 @@ class pgate(design.design):
# This is the space from a S/D contact to the supply rail
contact_to_vdd_rail_space = 0.5 * self.m1_width + self.m1_space
# This is a poly-to-poly of a flipped cell
poly_to_poly_gate_space = self.poly_extend_active + self.poly_space
poly_to_poly_gate_space = self.poly_extend_active + 0.5 * self.poly_space
self.top_bottom_space = max(contact_to_vdd_rail_space,
poly_to_poly_gate_space)

View File

@ -9,7 +9,7 @@ import debug
import pgate
from vector import vector
from sram_factory import factory
from tech import layer
class pinvbuf(pgate.pgate):
"""
@ -111,33 +111,45 @@ class pinvbuf(pgate.pgate):
mirror="MX")
def route_wires(self):
if "li" in layer:
route_stack = self.li_stack
else:
route_stack = self.m1_stack
# inv1 Z to inv2 A
z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A")
mid_point = vector(z1_pin.cx(), a2_pin.cy())
self.add_path("m1", [z1_pin.center(), mid_point, a2_pin.center()])
self.add_path(z1_pin.layer, [z1_pin.center(), mid_point, a2_pin.center()])
self.add_via_stack_center(from_layer=z1_pin.layer,
to_layer=a2_pin.layer,
offset=a2_pin.center())
# inv2 Z to inv3 A
z2_pin = self.inv2_inst.get_pin("Z")
a3_pin = self.inv3_inst.get_pin("A")
mid_point = vector(z2_pin.cx(), a3_pin.cy())
self.add_path("m1", [z2_pin.center(), mid_point, a3_pin.center()])
self.add_path(z2_pin.layer, [z2_pin.center(), mid_point, a3_pin.center()])
self.add_via_stack_center(from_layer=z2_pin.layer,
to_layer=a3_pin.layer,
offset=a3_pin.center())
# inv1 Z to inv4 A (up and over)
z1_pin = self.inv1_inst.get_pin("Z")
a4_pin = self.inv4_inst.get_pin("A")
mid_point = vector(z1_pin.cx(), a4_pin.cy())
self.add_wire(self.m1_stack,
self.add_wire(route_stack,
[z1_pin.center(), mid_point, a4_pin.center()])
self.add_via_center(layers=self.m1_stack,
offset=z1_pin.center())
self.add_via_stack_center(from_layer=z1_pin.layer,
to_layer=route_stack[2],
offset=z1_pin.center())
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv1_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="m1",
layer=vdd_pin.layer,
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -145,7 +157,7 @@ class pinvbuf(pgate.pgate):
# Continous vdd rail along with label.
gnd_pin = self.inv4_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="m1",
layer=gnd_pin.layer,
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=gnd_pin.height())
@ -153,31 +165,25 @@ class pinvbuf(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv1_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="m1",
layer=gnd_pin.layer,
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
z_pin = self.inv4_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Z",
layer="m2",
layer=z_pin.layer,
offset=z_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=z_pin.center())
zb_pin = self.inv3_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Zb",
layer="m2",
layer=zb_pin.layer,
offset=zb_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=zb_pin.center())
a_pin = self.inv1_inst.get_pin("A")
self.add_layout_pin_rect_center(text="A",
layer="m2",
layer=a_pin.layer,
offset=a_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=a_pin.center())
def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False):
"""Get the stage efforts of the clk -> clk_buf path"""

View File

@ -177,9 +177,9 @@ class pnand2(pgate.pgate):
# Top of NMOS drain
nmos_pin = self.nmos2_inst.get_pin("D")
bottom_pin_offset = nmos_pin.uy()
self.inputA_yoffset = bottom_pin_offset + self.m1_pitch
bottom_pin = self.nmos2_inst.get_pin("D")
self.inputA_yoffset = max(bottom_pin.uy() + self.m1_pitch,
self.nmos2_inst.uy() + self.poly_to_active)
self.inputB_yoffset = self.inputA_yoffset + self.m3_pitch

View File

@ -12,7 +12,7 @@ from vector import vector
import logical_effort
from sram_factory import factory
from globals import OPTS
import contact
class pnand3(pgate.pgate):
"""
@ -209,13 +209,21 @@ class pnand3(pgate.pgate):
def route_inputs(self):
""" Route the A and B and C inputs """
# We can use this pitch because the contacts and overlap won't be adjacent
non_contact_pitch = 0.5 * self.m1_width + self.m1_space + 0.5 * contact.poly_contact.second_layer_height
pmos_drain_bottom = self.pmos1_inst.get_pin("D").by()
self.output_yoffset = pmos_drain_bottom - 0.5 * self.route_layer_width - self.route_layer_space
# This is a more compact offset, but the bottom one works better in the decoders to "center" the pins
# in the height of the gates
self.inputA_yoffset = self.output_yoffset - 0.5 * self.route_layer_width - self.route_layer_space
# self.inputA_yoffset = self.output_yoffset - self.m1_pitch
bottom_pin = self.nmos1_inst.get_pin("D")
# active contact metal to poly contact metal spacing
active_contact_to_poly_contact = bottom_pin.uy() + self.m1_space + 0.5 * contact.poly_contact.second_layer_height
# active diffusion to poly contact spacing
# doesn't use nmos uy because that is calculated using offset + poly height
active_to_poly_contact = self.nmos1_inst.by() + self.nmos1_inst.mod.active_height \
+ self.poly_to_active + 0.5 * contact.poly_contact.first_layer_height
self.inputA_yoffset = max(active_contact_to_poly_contact,
active_to_poly_contact)
self.route_input_gate(self.pmos1_inst,
self.nmos1_inst,
self.inputA_yoffset,
@ -223,14 +231,14 @@ class pnand3(pgate.pgate):
position="left")
# Put B right on the well line
self.inputB_yoffset = self.inputA_yoffset - self.m1_pitch
self.inputB_yoffset = self.inputA_yoffset + non_contact_pitch
self.route_input_gate(self.pmos2_inst,
self.nmos2_inst,
self.inputB_yoffset,
"B",
position="center")
self.inputC_yoffset = self.inputB_yoffset - self.m1_pitch
self.inputC_yoffset = self.inputB_yoffset + non_contact_pitch
self.route_input_gate(self.pmos3_inst,
self.nmos3_inst,
self.inputC_yoffset,

View File

@ -149,13 +149,9 @@ class precharge(design.design):
# Compute the other pmos2 location,
# but determining offset to overlap the source and drain pins
overlap_offset = self.pmos.get_pin("D").ll() - self.pmos.get_pin("S").ll()
# This is how much the contact is placed inside the ptx active
contact_xdiff = self.pmos.get_pin("S").lx()
# adds the lower pmos to layout
bl_xoffset = self.bitcell_bl_pin.lx()
self.lower_pmos_position = vector(max(bl_xoffset - contact_xdiff,
self.nwell_enclose_active),
self.lower_pmos_position = vector(self.well_enclose_active + 0.5 * self.m1_width,
self.initial_yoffset)
self.lower_pmos_inst.place(self.lower_pmos_position)
@ -218,7 +214,7 @@ class precharge(design.design):
# adds the contact from active to metal1
offset_height = self.upper_pmos1_inst.uy() + \
0.5 * contact.active_contact.height + \
contact.active_contact.height + \
self.nwell_extend_active
self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) + \
vector(0, offset_height)

View File

@ -205,28 +205,15 @@ class ptx(design.design):
# Poly height must include poly extension over active
self.poly_height = self.tx_width + 2 * self.poly_extend_active
# The active offset is due to the well extension
if "pwell" in layer:
pwell_enclose_active = drc("pwell_enclose_active")
else:
pwell_enclose_active = 0
if "nwell" in layer:
nwell_enclose_active = drc("nwell_enclose_active")
else:
nwell_enclose_active = 0
# Use the max of either so that the poly gates will align properly
well_enclose_active = max(pwell_enclose_active,
nwell_enclose_active)
self.active_offset = vector([well_enclose_active] * 2)
self.active_offset = vector([self.well_enclose_active] * 2)
# Well enclosure of active, ensure minwidth as well
well_name = "{}well".format(self.well_type)
if well_name in layer:
well_width_rule = drc("minwidth_" + well_name)
well_enclose_active = drc(well_name + "_enclose_active")
self.well_width = max(self.active_width + 2 * well_enclose_active,
self.well_width = max(self.active_width + 2 * self.well_enclose_active,
well_width_rule)
self.well_height = max(self.active_height + 2 * well_enclose_active,
self.well_height = max(self.active_height + 2 * self.well_enclose_active,
well_width_rule)
# We are going to shift the 0,0, so include that in the width and height
self.height = self.well_height - self.active_offset.y

View File

@ -29,10 +29,6 @@ class pand2_test(openram_test):
a = pand2.pand2(name="pand2x4", size=4)
self.local_check(a)
debug.info(2, "Testing vertical pand2 gate 4x")
a = pand2.pand2(name="pand2x4", size=4, vertical=True)
self.local_check(a)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test

View File

@ -29,10 +29,6 @@ class pand3_test(openram_test):
a = pand3.pand3(name="pand3x4", size=4)
self.local_check(a)
debug.info(2, "Testing vertical pand3 gate 4x")
a = pand3.pand3(name="pand3x4", size=4, vertical=True)
self.local_check(a)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test

View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# 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 unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class precharge_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check precharge array in multi-port
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
globals.setup_bitcell()
debug.info(2, "Checking precharge for 1rw1r port 0")
tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(tx)
factory.reset()
debug.info(2, "Checking precharge for 1rw1r port 1")
tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl1", bitcell_br="br1")
self.local_check(tx)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -17,7 +17,7 @@ import debug
#@unittest.skip("SKIPPING 05_bitcell_1rw_1r_array_test")
class bitcell_1rw_1r_array_test(openram_test):
class bitcell_array_1rw_1r_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))

View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# 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 unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class sense_amp_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
globals.setup_bitcell()
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=1")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=1)
self.local_check(a)
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=2)
self.local_check(a)
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=4)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -13,7 +13,7 @@ from globals import OPTS
from sram_factory import factory
import debug
class replica_bitcell_array_test(openram_test):
class replica_bitcell_array_1rw_1r_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class replica_column_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
globals.setup_bitcell()
debug.info(2, "Testing replica column for 6t_cell")
a = factory.create(module_type="replica_column", rows=4, left_rbl=1, right_rbl=0, replica_bit=1)
self.local_check(a)
debug.info(2, "Testing replica column for 6t_cell")
a = factory.create(module_type="replica_column", rows=4, left_rbl=1, right_rbl=1, replica_bit=6)
self.local_check(a)
debug.info(2, "Testing replica column for 6t_cell")
a = factory.create(module_type="replica_column", rows=4, left_rbl=2, right_rbl=0, replica_bit=2)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -15,7 +15,6 @@ from globals import OPTS
from sram_factory import factory
import debug
@unittest.skip("SKIPPING 20_psram_1bank_4mux_1rw_1r_test - Matt sucks, don't do this")
class psram_1bank_4mux_1rw_1r_test(openram_test):
def runTest(self):

View File

@ -22,14 +22,26 @@ header(__file__, OPTS.tech_name)
# get a list of all files in the tests directory
files = os.listdir(sys.path[0])
# load a file with all tests to skip in a given technology
# since tech_name is dynamically loaded, we can't use @skip directives
try:
skip_file_name = "{0}/tests/skip_tests_{1}.txt".format(os.getenv("OPENRAM_HOME"), OPTS.tech_name)
skip_file = open(skip_file_name, "r")
skip_tests = skip_file.read().splitlines()
for st in skip_tests:
debug.warning("Skipping: " + st)
except FileNotFoundError:
skip_tests = []
# assume any file that ends in "test.py" in it is a regression test
nametest = re.compile("test\.py$", re.IGNORECASE)
tests = list(filter(nametest.search, files))
tests.sort()
all_tests = list(filter(nametest.search, files))
filtered_tests = list(filter(lambda i: i not in skip_tests, all_tests))
filtered_tests.sort()
# import all of the modules
filenameToModuleName = lambda f: os.path.splitext(f)[0]
moduleNames = map(filenameToModuleName, tests)
moduleNames = map(filenameToModuleName, filtered_tests)
modules = map(__import__, moduleNames)
suite = unittest.TestSuite()
load = unittest.defaultTestLoader.loadTestsFromModule

View File

@ -0,0 +1,87 @@
04_dummy_pbitcell_test.py
04_pbitcell_test.py
04_precharge_pbitcell_test.py
04_replica_pbitcell_test.py
04_single_level_column_mux_pbitcell_test.py
05_bitcell_1rw_1r_array_test.py
05_bitcell_array_test.py
05_dummy_array_test.py
05_pbitcell_array_test.py
06_hierarchical_decoder_pbitcell_test.py
06_hierarchical_decoder_test.py
06_hierarchical_predecode2x4_pbitcell_test.py
06_hierarchical_predecode2x4_test.py
06_hierarchical_predecode3x8_pbitcell_test.py
06_hierarchical_predecode3x8_test.py
06_hierarchical_predecode4x16_test.py
07_single_level_column_mux_array_pbitcell_test.py
08_wordline_driver_array_pbitcell_test.py
08_wordline_driver_array_test.py
09_sense_amp_array_test_pbitcell.py
09_sense_amp_array_test.py
10_write_driver_array_pbitcell_test.py
10_write_driver_array_test.py
10_write_driver_array_wmask_pbitcell_test.py
10_write_driver_array_wmask_test.py
10_write_mask_and_array_pbitcell_test.py
10_write_mask_and_array_test.py
12_tri_gate_array_test.py
14_replica_pbitcell_array_test.py
14_replica_bitcell_array_test.py
14_replica_column_test.py
14_replica_column_1rw_1r_test.py
18_port_address_test.py
18_port_data_test.py
18_port_data_wmask_test.py
19_bank_select_pbitcell_test.py
19_bank_select_test.py
19_psingle_bank_test.py
19_bank_select_pbitcell_test.py
19_pmulti_bank_test.py
19_multi_bank_test.py
19_psingle_bank_test.py
19_single_bank_1w_1r_test.py
19_single_bank_wmask_1rw_1r_test.py
19_single_bank_1rw_1r_test.py
19_single_bank_test.py
19_single_bank_wmask_test.py
20_psram_1bank_2mux_1rw_1w_test.py
20_psram_1bank_2mux_1rw_1w_wmask_test.py
20_psram_1bank_2mux_1w_1r_test.py
20_psram_1bank_2mux_test.py
20_psram_1bank_4mux_1rw_1r_test.py
20_sram_1bank_2mux_1w_1r_test.py
20_sram_1bank_2mux_test.py
20_sram_1bank_2mux_wmask_test.py
20_sram_1bank_32b_1024_wmask_test.py
20_sram_1bank_4mux_test.py
20_sram_1bank_8mux_test.py
20_sram_1bank_nomux_test.py
20_sram_1bank_nomux_wmask_test.py
20_sram_2bank_test.py
21_hspice_delay_test.py
21_hspice_setuphold_test.py
21_model_delay_test.py
21_ngspice_delay_test.py
21_ngspice_setuphold_test.py
22_psram_1bank_2mux_func_test.py
22_psram_1bank_4mux_func_test.py
22_psram_1bank_8mux_func_test.py
22_psram_1bank_nomux_func_test.py
22_sram_1bank_2mux_func_test.py
22_sram_1bank_4mux_func_test.py
22_sram_1bank_8mux_func_test.py
22_sram_1bank_nomux_func_test.py
22_sram_1rw_1r_1bank_nomux_func_test.py
22_sram_wmask_func_test.py
23_lib_sram_model_corners_test.py
23_lib_sram_model_test.py
23_lib_sram_prune_test.py
23_lib_sram_test.py
24_lef_sram_test.py
25_verilog_sram_test.py
26_hspice_pex_pinv_test.py
26_ngspice_pex_pinv_test.py
26_pex_test.py
30_openram_back_end_test.py
30_openram_front_end_test.py

Binary file not shown.