diff --git a/compiler/base/design.py b/compiler/base/design.py index 7a570b28..1fded37e 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -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: diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index d3b84ca5..362c0f9e 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -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 diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 0366b10b..81629771 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -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""" diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index afe87497..603bebfe 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -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) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 8e18d4d2..67ba4a18 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -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) diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index fe376bc4..5b286e9b 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -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""" diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 51581e61..5816adcf 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -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 diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 6cbd7cca..31024d82 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -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, diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 76fc8676..07b4f21b 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -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) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index f6716a1f..6fba247e 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -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 diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/04_dff_buf_test.py similarity index 100% rename from compiler/tests/11_dff_buf_test.py rename to compiler/tests/04_dff_buf_test.py diff --git a/compiler/tests/04_pand2_test.py b/compiler/tests/04_pand2_test.py index 21a0a38e..f7e5f304 100755 --- a/compiler/tests/04_pand2_test.py +++ b/compiler/tests/04_pand2_test.py @@ -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 diff --git a/compiler/tests/04_pand3_test.py b/compiler/tests/04_pand3_test.py index f851077b..e58f1ee9 100755 --- a/compiler/tests/04_pand3_test.py +++ b/compiler/tests/04_pand3_test.py @@ -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 diff --git a/compiler/tests/04_precharge_1rw_1r_test.py b/compiler/tests/04_precharge_1rw_1r_test.py new file mode 100755 index 00000000..4765c77c --- /dev/null +++ b/compiler/tests/04_precharge_1rw_1r_test.py @@ -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()) diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_array_1rw_1r_test.py similarity index 96% rename from compiler/tests/05_bitcell_1rw_1r_array_test.py rename to compiler/tests/05_bitcell_array_1rw_1r_test.py index 0683d127..0e7d5665 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_array_1rw_1r_test.py @@ -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")) diff --git a/compiler/tests/09_sense_amp_array_1rw_1r_test.py b/compiler/tests/09_sense_amp_array_1rw_1r_test.py new file mode 100755 index 00000000..a8ed4d2f --- /dev/null +++ b/compiler/tests/09_sense_amp_array_1rw_1r_test.py @@ -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()) diff --git a/compiler/tests/14_replica_bitcell_1rw_1r_array_test.py b/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py similarity index 95% rename from compiler/tests/14_replica_bitcell_1rw_1r_array_test.py rename to compiler/tests/14_replica_bitcell_array_1rw_1r_test.py index 3f869255..a36fc80f 100755 --- a/compiler/tests/14_replica_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py @@ -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")) diff --git a/compiler/tests/14_replica_column_1rw_1r_test.py b/compiler/tests/14_replica_column_1rw_1r_test.py new file mode 100755 index 00000000..3c1a0e1e --- /dev/null +++ b/compiler/tests/14_replica_column_1rw_1r_test.py @@ -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()) diff --git a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py index 145d1723..ecbd0863 100755 --- a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py +++ b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py @@ -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): diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index e60b010d..3fd5d6eb 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -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 diff --git a/compiler/tests/skip_tests_s8.txt b/compiler/tests/skip_tests_s8.txt new file mode 100644 index 00000000..68a6549b --- /dev/null +++ b/compiler/tests/skip_tests_s8.txt @@ -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 diff --git a/technology/freepdk45/gds_lib/dff.gds b/technology/freepdk45/gds_lib/dff.gds index 526a1861..2a6004d1 100644 Binary files a/technology/freepdk45/gds_lib/dff.gds and b/technology/freepdk45/gds_lib/dff.gds differ