From 8c6d5b49bee22effd09b3b1c6ea2a2d0ab67fe42 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 13:09:52 -0700 Subject: [PATCH 01/21] Consider diffusion spacing in active offset --- compiler/pgates/ptx.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index f6716a1f..d52925ec 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -216,7 +216,8 @@ class ptx(design.design): 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) + nwell_enclose_active, + self.active_space) self.active_offset = vector([well_enclose_active] * 2) # Well enclosure of active, ensure minwidth as well From 157926960b51631f6ff8d6a74862280fd2d3f93c Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 13:48:16 -0700 Subject: [PATCH 02/21] Flip freepdk45 flop, dff_buf route layer change --- compiler/modules/dff_buf.py | 50 +++++++++++++-------------- technology/freepdk45/gds_lib/dff.gds | Bin 22528 -> 22182 bytes 2 files changed, 25 insertions(+), 25 deletions(-) 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/technology/freepdk45/gds_lib/dff.gds b/technology/freepdk45/gds_lib/dff.gds index 526a1861149039682e51578ccf5624d908940ae9..2a6004d145d7ef077006b8a6b4a6abce4d37eef4 100644 GIT binary patch literal 22182 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 F{5Nsri2DEl From 148521c458daf7540af5a3bd3ca699ff8d0529e3 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 13:48:47 -0700 Subject: [PATCH 03/21] Remove stdc layer --- compiler/base/hierarchy_layout.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index d3b84ca5..4485f622 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, From a28e747a02bad32b46039391c018aa16fd9477be Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 15:28:50 -0700 Subject: [PATCH 04/21] Fix precharge offset. Move well rules to design class. --- compiler/base/design.py | 14 +++++++ compiler/pgates/precharge.py | 8 +--- compiler/pgates/ptx.py | 20 ++------- compiler/tests/04_precharge_1rw_1r_test.py | 47 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 23 deletions(-) create mode 100755 compiler/tests/04_precharge_1rw_1r_test.py 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/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 d52925ec..6fba247e 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -205,29 +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_space) - 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/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()) From 580b0601b5d637ec2ff06919350972c3536bf251 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 16:04:39 -0700 Subject: [PATCH 05/21] Unskip 20_psram_1bank_4mux_1rw_1r_test --- compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py | 1 - 1 file changed, 1 deletion(-) 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): From fd49d3ed6ae263d873fabbaeae3e2dd935367a56 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 16:09:15 -0700 Subject: [PATCH 06/21] Add tech specific skip tests for making new techs. --- .gitlab-ci.yml | 16 ++++----- compiler/tests/regress.py | 18 ++++++++-- compiler/tests/skip_tests_s8.txt | 56 ++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 compiler/tests/skip_tests_s8.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 27431cb2..02778d35 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,14 +25,14 @@ scn4m_subm: - .coverage.* expire_in: 1 week -# s8: -# stage: test -# script: -# - coverage run -p $OPENRAM_HOME/tests/regress.py -t s8 -# artifacts: -# paths: -# - .coverage.* -# expire_in: 1 week +s8: + stage: test + script: + - coverage run -p $OPENRAM_HOME/tests/regress.py -t s8 + artifacts: + paths: + - .coverage.* + expire_in: 1 week coverage: stage: coverage diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index e60b010d..80754d0e 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -12,6 +12,7 @@ import unittest import sys,os sys.path.append(os.getenv("OPENRAM_HOME")) import globals +import debug (OPTS, args) = globals.parse_args() del sys.argv[1:] @@ -22,14 +23,25 @@ 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 = open("skip_tests_{}.txt".format(OPTS.tech_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..8e0f1746 --- /dev/null +++ b/compiler/tests/skip_tests_s8.txt @@ -0,0 +1,56 @@ +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_pbitcell_array_test.py +06_hierarchical_decoder_pbitcell_test.py +06_hierarchical_predecode2x4_pbitcell_test.py +06_hierarchical_predecode3x8_pbitcell_test.py +07_single_level_column_mux_array_pbitcell_test.py +08_wordline_driver_array_pbitcell_test.py +09_sense_amp_array_test_pbitcell.py +10_write_driver_array_pbitcell_test.py +10_write_driver_array_wmask_pbitcell_test.py +10_write_mask_and_array_pbitcell_test.py +14_replica_pbitcell_array_test.py +19_bank_select_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 +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 +05_pbitcell_array_test.py +06_hierarchical_decoder_pbitcell_test.py +06_hierarchical_decoder_pbitcell_test.py +06_hierarchical_decoder_test.py +06_hierarchical_predecode2x4_pbitcell_test.py +06_hierarchical_predecode2x4_pbitcell_test.py +06_hierarchical_predecode2x4_test.py +06_hierarchical_predecode3x8_pbitcell_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 +09_sense_amp_array_test_pbitcell.py +10_write_driver_array_pbitcell_test.py +10_write_driver_array_wmask_pbitcell_test.py +10_write_mask_and_array_pbitcell_test.py +14_replica_pbitcell_array_test.py +19_bank_select_pbitcell_test.py From c6b875146d40b6779f907bffb78141aafed5a261 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 16:33:59 -0700 Subject: [PATCH 07/21] Use local skip file --- compiler/tests/regress.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index 80754d0e..e13d250a 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -12,7 +12,6 @@ import unittest import sys,os sys.path.append(os.getenv("OPENRAM_HOME")) import globals -import debug (OPTS, args) = globals.parse_args() del sys.argv[1:] @@ -26,7 +25,8 @@ 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 = open("skip_tests_{}.txt".format(OPTS.tech_name), "r") + skip_file_name = "skip_tests_{}.txt".format(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) From e6babc301daa9956d745d72f4bc3568d8fff62a9 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 16:34:15 -0700 Subject: [PATCH 08/21] Incrase space for pnand gates --- compiler/pgates/pnand2.py | 6 +++--- compiler/pgates/pnand3.py | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) 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..fa028246 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -212,10 +212,9 @@ class pnand3(pgate.pgate): 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") + self.inputA_yoffset = max(bottom_pin.uy() + self.m1_pitch, + self.nmos1_inst.uy() + self.poly_to_active) self.route_input_gate(self.pmos1_inst, self.nmos1_inst, self.inputA_yoffset, @@ -223,14 +222,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 + self.m1_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 + self.m1_pitch self.route_input_gate(self.pmos3_inst, self.nmos3_inst, self.inputC_yoffset, From 14782914b33330181e89d3cd150774d3786ed83b Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 16:40:59 -0700 Subject: [PATCH 09/21] Remove vertical pand gates --- compiler/tests/04_pand2_test.py | 4 ---- compiler/tests/04_pand3_test.py | 4 ---- 2 files changed, 8 deletions(-) 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 From 064fe34edf55fbb1c358598652d26820d6b86d67 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 17:16:35 -0700 Subject: [PATCH 10/21] Fix pinvbuf layers --- compiler/pgates/pinvbuf.py | 42 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) 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""" From d4fc88124ad6f9127e9c2179a06a92e166409846 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 9 Jun 2020 17:18:19 -0700 Subject: [PATCH 11/21] Rename dff_buf test --- compiler/tests/{11_dff_buf_test.py => 04_dff_buf_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/tests/{11_dff_buf_test.py => 04_dff_buf_test.py} (100%) 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 From c119e60e797a2fecbcd32d2690a9343626269ec1 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 10:14:52 -0700 Subject: [PATCH 12/21] Add more s8 skip tests --- .../tests/09_sense_amp_array_1rw_1r_test.py | 48 ++++++++++++ compiler/tests/skip_tests_s8.txt | 78 +++++++++++-------- 2 files changed, 94 insertions(+), 32 deletions(-) create mode 100755 compiler/tests/09_sense_amp_array_1rw_1r_test.py 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/skip_tests_s8.txt b/compiler/tests/skip_tests_s8.txt index 8e0f1746..9f60d65e 100644 --- a/compiler/tests/skip_tests_s8.txt +++ b/compiler/tests/skip_tests_s8.txt @@ -3,18 +3,6 @@ 04_precharge_pbitcell_test.py 04_replica_pbitcell_test.py 04_single_level_column_mux_pbitcell_test.py -05_pbitcell_array_test.py -06_hierarchical_decoder_pbitcell_test.py -06_hierarchical_predecode2x4_pbitcell_test.py -06_hierarchical_predecode3x8_pbitcell_test.py -07_single_level_column_mux_array_pbitcell_test.py -08_wordline_driver_array_pbitcell_test.py -09_sense_amp_array_test_pbitcell.py -10_write_driver_array_pbitcell_test.py -10_write_driver_array_wmask_pbitcell_test.py -10_write_mask_and_array_pbitcell_test.py -14_replica_pbitcell_array_test.py -19_bank_select_pbitcell_test.py 05_bitcell_1rw_1r_array_test.py 05_bitcell_array_test.py 05_dummy_array_test.py @@ -26,31 +14,57 @@ 06_hierarchical_predecode3x8_pbitcell_test.py 06_hierarchical_predecode3x8_test.py 06_hierarchical_predecode4x16_test.py -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 -05_pbitcell_array_test.py -06_hierarchical_decoder_pbitcell_test.py -06_hierarchical_decoder_pbitcell_test.py -06_hierarchical_decoder_test.py -06_hierarchical_predecode2x4_pbitcell_test.py -06_hierarchical_predecode2x4_pbitcell_test.py -06_hierarchical_predecode2x4_test.py -06_hierarchical_predecode3x8_pbitcell_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 09_sense_amp_array_test_pbitcell.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 14_replica_pbitcell_array_test.py +18_port_address_test.py +18_port_data_test.py +18_port_data_wmask_test.py 19_bank_select_pbitcell_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 From 5e3332453b2925c689ac2c034cb1a65a10b0cc16 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 10:15:23 -0700 Subject: [PATCH 13/21] Allow power pins to start on any layer besides m1 --- compiler/base/hierarchy_layout.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 4485f622..362c0f9e 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -1304,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 From 10be2d08b5eac5e532e14366f5d143bb479337ba Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 10:23:05 -0700 Subject: [PATCH 14/21] Full path to skip tests file --- compiler/tests/regress.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index e13d250a..3fd5d6eb 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -25,7 +25,7 @@ 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 = "skip_tests_{}.txt".format(OPTS.tech_name) + 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: From f2c45a230ed929e1d08b7e9fee5c020490a44fe3 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 11:00:00 -0700 Subject: [PATCH 15/21] Add new replica column test. Add more skip tests. --- .../tests/14_replica_column_1rw_1r_test.py | 46 +++++++++++++++++++ compiler/tests/skip_tests_s8.txt | 17 +++++++ 2 files changed, 63 insertions(+) create mode 100755 compiler/tests/14_replica_column_1rw_1r_test.py 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/skip_tests_s8.txt b/compiler/tests/skip_tests_s8.txt index 9f60d65e..68a6549b 100644 --- a/compiler/tests/skip_tests_s8.txt +++ b/compiler/tests/skip_tests_s8.txt @@ -16,18 +16,35 @@ 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 From 469cd260b954cd191a9291eca69e61170dbf2bea Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 14:54:20 -0700 Subject: [PATCH 16/21] Change bitcell array name to match --- ...ell_1rw_1r_array_test.py => 05_bitcell_array_1rw_1r_test.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename compiler/tests/{05_bitcell_1rw_1r_array_test.py => 05_bitcell_array_1rw_1r_test.py} (96%) 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")) From bfd1abc79f738177c393b0137d5455bcc9d5cf2b Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 14:58:55 -0700 Subject: [PATCH 17/21] Replica column pins start at 0 height. --- compiler/modules/replica_column.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 78c66d7c3453b7bca2774012998381fd3e892c73 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 15:00:29 -0700 Subject: [PATCH 18/21] Disable CI for s8 to commit to dev --- .gitlab-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 02778d35..27431cb2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,14 +25,14 @@ scn4m_subm: - .coverage.* expire_in: 1 week -s8: - stage: test - script: - - coverage run -p $OPENRAM_HOME/tests/regress.py -t s8 - artifacts: - paths: - - .coverage.* - expire_in: 1 week +# s8: +# stage: test +# script: +# - coverage run -p $OPENRAM_HOME/tests/regress.py -t s8 +# artifacts: +# paths: +# - .coverage.* +# expire_in: 1 week coverage: stage: coverage From 0b4b5e713361277beb10cd69e51cab1d4e33afc6 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 16:19:24 -0700 Subject: [PATCH 19/21] More exact input spacing in pnand3 --- compiler/pgates/pnand3.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index fa028246..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,12 +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 bottom_pin = self.nmos1_inst.get_pin("D") - self.inputA_yoffset = max(bottom_pin.uy() + self.m1_pitch, - self.nmos1_inst.uy() + self.poly_to_active) + # 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, @@ -222,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, From fdf92d0da1fdcc88b8c0119600e80aed8ad534b5 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 16:41:26 -0700 Subject: [PATCH 20/21] Rename test 14 --- ...1r_array_test.py => 14_replica_bitcell_array_1rw_1r_test.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename compiler/tests/{14_replica_bitcell_1rw_1r_array_test.py => 14_replica_bitcell_array_1rw_1r_test.py} (95%) 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")) From 196e5998c8753f410bf31a01dc351231cdda4a99 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jun 2020 16:52:51 -0700 Subject: [PATCH 21/21] Half poly space per cell at top and bottom. --- compiler/pgates/pgate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index a8c45641..7ff73092 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)