From 69cab426760def426a363934bb66a4e818ac15b2 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 Jul 2020 13:59:55 -0700 Subject: [PATCH] Add pbuf_dec gate --- compiler/pgates/pbuf_dec.py | 125 ++++++++++++++++++++++++++ compiler/tests/04_pbuf_dec_8x_test.py | 40 +++++++++ 2 files changed, 165 insertions(+) create mode 100644 compiler/pgates/pbuf_dec.py create mode 100755 compiler/tests/04_pbuf_dec_8x_test.py diff --git a/compiler/pgates/pbuf_dec.py b/compiler/pgates/pbuf_dec.py new file mode 100644 index 00000000..e5018b62 --- /dev/null +++ b/compiler/pgates/pbuf_dec.py @@ -0,0 +1,125 @@ +# 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 debug +from vector import vector +import pgate +from sram_factory import factory + + +class pbuf_dec(pgate.pgate): + """ + This is a simple buffer used for driving wordlines. + """ + def __init__(self, name, size=4, height=None): + + debug.info(1, "creating {0} with size of {1}".format(name, size)) + self.add_comment("size: {}".format(size)) + + self.stage_effort = 4 + self.size = size + self.height = height + + # Creates the netlist and layout + pgate.pgate.__init__(self, name, height) + + def create_netlist(self): + self.add_pins() + self.create_modules() + self.create_insts() + + def create_layout(self): + self.width = self.inv1.width + self.inv2.width + self.place_insts() + self.add_wires() + self.add_layout_pins() + self.route_supply_rails() + self.add_boundary() + + def add_pins(self): + self.add_pin("A", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def create_modules(self): + # Shield the cap, but have at least a stage effort of 4 + input_size = max(1, int(self.size / self.stage_effort)) + self.inv1 = factory.create(module_type="pinv_dec", + size=input_size, + height=self.height) + self.add_mod(self.inv1) + + self.inv2 = factory.create(module_type="pinv_dec", + size=self.size, + height=self.height) + self.add_mod(self.inv2) + + def create_insts(self): + self.inv1_inst = self.add_inst(name="buf_inv1", + mod=self.inv1) + self.connect_inst(["A", "zb_int", "vdd", "gnd"]) + + self.inv2_inst = self.add_inst(name="buf_inv2", + mod=self.inv2) + self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) + + def place_insts(self): + # Add INV1 to the right + self.inv1_inst.place(vector(0, 0)) + + # Add INV2 to the right + self.inv2_inst.place(vector(self.inv1_inst.rx(), 0)) + + def add_wires(self): + # inv1 Z to inv2 A + z1_pin = self.inv1_inst.get_pin("Z") + a2_pin = self.inv2_inst.get_pin("A") + mid_loc = vector(a2_pin.cx(), z1_pin.cy()) + self.add_path(self.route_layer, + [z1_pin.rc(), mid_loc, a2_pin.lc()], + width=a2_pin.width()) + + def route_supply_rails(self): + """ Add vdd/gnd rails to the top, (middle), and bottom. """ + self.copy_layout_pin(self.inv1_inst, "vdd") + self.copy_layout_pin(self.inv1_inst, "gnd") + self.copy_layout_pin(self.inv2_inst, "vdd") + self.copy_layout_pin(self.inv2_inst, "gnd") + + def add_layout_pins(self): + z_pin = self.inv2_inst.get_pin("Z") + self.add_layout_pin_rect_center(text="Z", + layer=z_pin.layer, + offset=z_pin.center(), + width=z_pin.width(), + height=z_pin.height()) + + a_pin = self.inv1_inst.get_pin("A") + self.add_layout_pin_rect_center(text="A", + layer=a_pin.layer, + offset=a_pin.center(), + width=a_pin.width(), + height=a_pin.height()) + + def get_stage_efforts(self, external_cout, inp_is_rise=False): + """Get the stage efforts of the A -> Z path""" + stage_effort_list = [] + stage1_cout = self.inv2.get_cin() + stage1 = self.inv1.get_stage_effort(stage1_cout, inp_is_rise) + stage_effort_list.append(stage1) + last_stage_is_rise = stage1.is_rise + + stage2 = self.inv2.get_stage_effort(external_cout, last_stage_is_rise) + stage_effort_list.append(stage2) + + return stage_effort_list + + def get_cin(self): + """Returns the relative capacitance of the input""" + input_cin = self.inv1.get_cin() + return input_cin diff --git a/compiler/tests/04_pbuf_dec_8x_test.py b/compiler/tests/04_pbuf_dec_8x_test.py new file mode 100755 index 00000000..ad1665fe --- /dev/null +++ b/compiler/tests/04_pbuf_dec_8x_test.py @@ -0,0 +1,40 @@ +#!/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 pbuf_dec_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, "Checking 8x size decoder buffer") + a = factory.create(module_type="pbuf_dec", size=8) + self.local_check(a) + + globals.end_openram() + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner())