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) self.well_extend_active = max(self.well_extend_active, self.nwell_extend_active)
if "pwell" in layer: if "pwell" in layer:
self.well_extend_active = max(self.well_extend_active, self.pwell_extend_active) 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 # These are for debugging previous manual rules
if False: if False:

View File

@ -695,8 +695,8 @@ class layout():
# we should add a boundary just for DRC in some technologies # we should add a boundary just for DRC in some technologies
if not self.is_library_cell and not self.bounding_box: 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 there is a boundary layer, and we didn't create one, add one.
if "stdc" in techlayer.keys(): if "boundary" in techlayer.keys():
boundary_layer = "stdc" boundary_layer = "boundary"
boundary = [self.find_lowest_coords(), boundary = [self.find_lowest_coords(),
self.find_highest_coords()] self.find_highest_coords()]
debug.check(boundary[0] and boundary[1], "No shapes to make a boundary.") debug.check(boundary[0] and boundary[1], "No shapes to make a boundary.")
@ -1259,10 +1259,7 @@ class layout():
if OPTS.netlist_only: if OPTS.netlist_only:
return return
if "stdc" in techlayer.keys(): boundary_layer = "boundary"
boundary_layer = "stdc"
else:
boundary_layer = "boundary"
if not ur: if not ur:
self.bounding_box = self.add_rect(layer=boundary_layer, self.bounding_box = self.add_rect(layer=boundary_layer,
offset=ll, offset=ll,
@ -1307,13 +1304,10 @@ class layout():
pin.ll(), pin.ll(),
pin.width(), pin.width(),
pin.height()) 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"): 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 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 debug
import design import design
from tech import parameter from tech import parameter, layer
from tech import cell_properties as props from tech import cell_properties as props
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
@ -52,7 +52,6 @@ class dff_buf(design.design):
def create_layout(self): def create_layout(self):
self.place_instances() self.place_instances()
self.width = self.inv2_inst.rx() self.width = self.inv2_inst.rx()
self.height = self.dff.height self.height = self.dff.height
self.route_wires() self.route_wires()
self.add_layout_pins() self.add_layout_pins()
@ -120,39 +119,37 @@ class dff_buf(design.design):
except AttributeError: except AttributeError:
pass pass
self.inv1_inst.place(vector(self.dff_inst.rx() + well_spacing + self.well_extend_active, 0)) self.inv1_inst.place(vector(self.dff_inst.rx() + well_spacing + self.well_extend_active, 0))
# Add INV2 to the right # Add INV2 to the right
self.inv2_inst.place(vector(self.inv1_inst.rx(), 0)) self.inv2_inst.place(vector(self.inv1_inst.rx(), 0))
def route_wires(self): def route_wires(self):
if "li" in layer:
self.route_layer = "li"
else:
self.route_layer = "m1"
# Route dff q to inv1 a # Route dff q to inv1 a
q_pin = self.dff_inst.get_pin("Q") q_pin = self.dff_inst.get_pin("Q")
a1_pin = self.inv1_inst.get_pin("A") a1_pin = self.inv1_inst.get_pin("A")
mid_x_offset = 0.5 * (a1_pin.cx() + q_pin.cx()) mid1 = vector(a1_pin.cx(), q_pin.cy())
mid1 = vector(mid_x_offset, q_pin.cy()) self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()])
mid2 = vector(mid_x_offset, a1_pin.cy()) self.add_via_stack_center(from_layer=a1_pin.layer,
self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()]) to_layer=q_pin.layer,
self.add_via_center(layers=self.m2_stack, offset=a1_pin.center())
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())
# Route inv1 z to inv2 a # Route inv1 z to inv2 a
z1_pin = self.inv1_inst.get_pin("Z") z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A") a2_pin = self.inv2_inst.get_pin("A")
mid_x_offset = 0.5 * (z1_pin.cx() + a2_pin.cx()) self.mid_qb_pos = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_pin.cy())
self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy()) self.add_zjog(z1_pin.layer, z1_pin.center(), a2_pin.center())
mid2 = vector(mid_x_offset, a2_pin.cy())
self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()])
def add_layout_pins(self): def add_layout_pins(self):
# Continous vdd rail along with label. # Continous vdd rail along with label.
vdd_pin=self.dff_inst.get_pin("vdd") vdd_pin=self.dff_inst.get_pin("vdd")
self.add_layout_pin(text="vdd", self.add_layout_pin(text="vdd",
layer="m1", layer=vdd_pin.layer,
offset=vdd_pin.ll(), offset=vdd_pin.ll(),
width=self.width, width=self.width,
height=vdd_pin.height()) height=vdd_pin.height())
@ -160,7 +157,7 @@ class dff_buf(design.design):
# Continous gnd rail along with label. # Continous gnd rail along with label.
gnd_pin=self.dff_inst.get_pin("gnd") gnd_pin=self.dff_inst.get_pin("gnd")
self.add_layout_pin(text="gnd", self.add_layout_pin(text="gnd",
layer="m1", layer=gnd_pin.layer,
offset=gnd_pin.ll(), offset=gnd_pin.ll(),
width=self.width, width=self.width,
height=vdd_pin.height()) height=vdd_pin.height())
@ -185,17 +182,20 @@ class dff_buf(design.design):
self.add_layout_pin_rect_center(text="Q", self.add_layout_pin_rect_center(text="Q",
layer="m2", layer="m2",
offset=q_pos) offset=q_pos)
self.add_path("m1", [dout_pin.center(), mid_pos, q_pos]) self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos])
self.add_via_center(layers=self.m1_stack, self.add_via_stack_center(from_layer=dout_pin.layer,
offset=q_pos) to_layer="m2",
offset=q_pos)
qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch) qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch)
self.add_layout_pin_rect_center(text="Qb", self.add_layout_pin_rect_center(text="Qb",
layer="m2", layer="m2",
offset=qb_pos) offset=qb_pos)
self.add_path("m1", [self.mid_qb_pos, qb_pos]) self.add_path(self.route_layer, [self.mid_qb_pos, qb_pos])
self.add_via_center(layers=self.m1_stack, a2_pin = self.inv2_inst.get_pin("A")
offset=qb_pos) self.add_via_stack_center(from_layer=a2_pin.layer,
to_layer="m2",
offset=qb_pos)
def get_clk_cin(self): def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff""" """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) bl_pin = self.cell_inst[0].get_pin(bl_name)
self.add_layout_pin(text=bl_name, self.add_layout_pin(text=bl_name,
layer=bl_pin.layer, layer=bl_pin.layer,
offset=bl_pin.ll(), offset=bl_pin.ll().scale(1, 0),
width=bl_pin.width(), width=bl_pin.width(),
height=self.height) 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 # 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 contact_to_vdd_rail_space = 0.5 * self.m1_width + self.m1_space
# This is a poly-to-poly of a flipped cell # 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, self.top_bottom_space = max(contact_to_vdd_rail_space,
poly_to_poly_gate_space) poly_to_poly_gate_space)

View File

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

View File

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

View File

@ -12,7 +12,7 @@ from vector import vector
import logical_effort import logical_effort
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
import contact
class pnand3(pgate.pgate): class pnand3(pgate.pgate):
""" """
@ -209,13 +209,21 @@ class pnand3(pgate.pgate):
def route_inputs(self): def route_inputs(self):
""" Route the A and B and C inputs """ """ 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() 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 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 bottom_pin = self.nmos1_inst.get_pin("D")
# in the height of the gates # active contact metal to poly contact metal spacing
self.inputA_yoffset = self.output_yoffset - 0.5 * self.route_layer_width - self.route_layer_space active_contact_to_poly_contact = bottom_pin.uy() + self.m1_space + 0.5 * contact.poly_contact.second_layer_height
# self.inputA_yoffset = self.output_yoffset - self.m1_pitch # 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.route_input_gate(self.pmos1_inst,
self.nmos1_inst, self.nmos1_inst,
self.inputA_yoffset, self.inputA_yoffset,
@ -223,14 +231,14 @@ class pnand3(pgate.pgate):
position="left") position="left")
# Put B right on the well line # 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.route_input_gate(self.pmos2_inst,
self.nmos2_inst, self.nmos2_inst,
self.inputB_yoffset, self.inputB_yoffset,
"B", "B",
position="center") 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.route_input_gate(self.pmos3_inst,
self.nmos3_inst, self.nmos3_inst,
self.inputC_yoffset, self.inputC_yoffset,

View File

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

View File

@ -205,28 +205,15 @@ class ptx(design.design):
# Poly height must include poly extension over active # Poly height must include poly extension over active
self.poly_height = self.tx_width + 2 * self.poly_extend_active self.poly_height = self.tx_width + 2 * self.poly_extend_active
# The active offset is due to the well extension self.active_offset = vector([self.well_enclose_active] * 2)
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)
# Well enclosure of active, ensure minwidth as well # Well enclosure of active, ensure minwidth as well
well_name = "{}well".format(self.well_type) well_name = "{}well".format(self.well_type)
if well_name in layer: if well_name in layer:
well_width_rule = drc("minwidth_" + well_name) well_width_rule = drc("minwidth_" + well_name)
well_enclose_active = drc(well_name + "_enclose_active") self.well_width = max(self.active_width + 2 * self.well_enclose_active,
self.well_width = max(self.active_width + 2 * well_enclose_active,
well_width_rule) 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) well_width_rule)
# We are going to shift the 0,0, so include that in the width and height # 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 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) a = pand2.pand2(name="pand2x4", size=4)
self.local_check(a) 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() globals.end_openram()
# instantiate a copdsay of the class to actually run the test # 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) a = pand3.pand3(name="pand3x4", size=4)
self.local_check(a) 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() globals.end_openram()
# instantiate a copdsay of the class to actually run the test # 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") #@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): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) 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 from sram_factory import factory
import debug import debug
class replica_bitcell_array_test(openram_test): class replica_bitcell_array_1rw_1r_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) 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 from sram_factory import factory
import debug 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): class psram_1bank_4mux_1rw_1r_test(openram_test):
def runTest(self): def runTest(self):

View File

@ -22,14 +22,26 @@ header(__file__, OPTS.tech_name)
# get a list of all files in the tests directory # get a list of all files in the tests directory
files = os.listdir(sys.path[0]) 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 # assume any file that ends in "test.py" in it is a regression test
nametest = re.compile("test\.py$", re.IGNORECASE) nametest = re.compile("test\.py$", re.IGNORECASE)
tests = list(filter(nametest.search, files)) all_tests = list(filter(nametest.search, files))
tests.sort() filtered_tests = list(filter(lambda i: i not in skip_tests, all_tests))
filtered_tests.sort()
# import all of the modules # import all of the modules
filenameToModuleName = lambda f: os.path.splitext(f)[0] filenameToModuleName = lambda f: os.path.splitext(f)[0]
moduleNames = map(filenameToModuleName, tests) moduleNames = map(filenameToModuleName, filtered_tests)
modules = map(__import__, moduleNames) modules = map(__import__, moduleNames)
suite = unittest.TestSuite() suite = unittest.TestSuite()
load = unittest.defaultTestLoader.loadTestsFromModule 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.