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())