From 04af5480d21bd2b634e9e728a84f5e88ca23182f Mon Sep 17 00:00:00 2001 From: Matthew Guthaus Date: Wed, 30 Oct 2019 21:34:03 +0000 Subject: [PATCH 1/2] Add skeleton files for pwrite_driver --- compiler/pgates/pwrite_driver.py | 304 ++++++++++++++++++++++++ compiler/tests/04_pwrite_driver_test.py | 36 +++ 2 files changed, 340 insertions(+) create mode 100644 compiler/pgates/pwrite_driver.py create mode 100644 compiler/tests/04_pwrite_driver_test.py diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py new file mode 100644 index 00000000..a808737b --- /dev/null +++ b/compiler/pgates/pwrite_driver.py @@ -0,0 +1,304 @@ +# See LICENSE for licensing information. +# +#Copyright (c) 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 design +from tech import drc, parameter, spice +import debug +import math +from tech import drc +from vector import vector +from globals import OPTS +from sram_factory import factory + +class pwrite_driver(design.design): + """ + The pwrite_driver is two tristate inverters that drive the bitlines. + The data input is first inverted before one tristate. + The inverted enable is also generated to control one tristate. + """ + def __init__(self, name, size=0): + debug.error("pwrite_driver not implemented yet.", -1) + debug.info(1, "creating pwrite_driver {}".format(name)) + design.design.__init__(self, name) + self.size = size + self.beta = parameter["beta"] + self.pmos_width = self.beta*self.size*parameter["min_tx_size"] + self.nmos_width = self.size*parameter["min_tx_size"] + + # The tech M2 pitch is based on old via orientations + self.m2_pitch = self.m2_space + self.m2_width + + # Width is matched to the bitcell, + # Height will be variable + self.bitcell = factory.create(module_type="bitcell") + self.width = self.bitcell.width + + # Creates the netlist and layout + # Since it has variable height, it is not a pgate. + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + self.DRC_LVS() + + + + def create_netlist(self): + self.add_pins() + self.add_modules() + self.create_insts() + + def create_layout(self): + self.place_modules() + self.route_wires() + self.route_supplies() + + + + def add_pins(self): + self.add_pin("din", "INPUT") + self.add_pin("bl", "OUTPUT") + self.add_pin("br", "OUTPUT") + self.add_pin("en", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + + def add_modules(self): + + # Tristate inverter + self.tri = factory.create(module_type="ptristate_inv", height="min") + self.add_mod(self.tri) + debug.check(self.tri.width Date: Fri, 15 Nov 2019 03:59:57 +0000 Subject: [PATCH 2/2] Non-power of 2 address decode tentative --- compiler/modules/hierarchical_decoder.py | 61 ++++++++++--------- .../tests/06_hierarchical_decoder_test.py | 36 +++++++++++ 2 files changed, 69 insertions(+), 28 deletions(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 0e70db55..4648519a 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -10,6 +10,7 @@ import debug import design from math import log from math import sqrt +from math import ceil import math import contact from sram_factory import factory @@ -31,7 +32,7 @@ class hierarchical_decoder(design.design): self.cell_height = height self.rows = rows - self.num_inputs = int(math.log(self.rows, 2)) + self.num_inputs = math.ceil(math.log(self.rows, 2)) (self.no_of_pre2x4,self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs) self.create_netlist() @@ -338,14 +339,15 @@ class hierarchical_decoder(design.design): for i in range(len(self.predec_groups[0])): for j in range(len(self.predec_groups[1])): row = len(self.predec_groups[0])*j + i - name = self.NAND_FORMAT.format(row) - self.nand_inst.append(self.add_inst(name=name, - mod=self.nand2)) - pins =["out_{0}".format(i), - "out_{0}".format(j + len(self.predec_groups[0])), - "Z_{0}".format(row), - "vdd", "gnd"] - self.connect_inst(pins) + if (row < self.rows): + name = self.NAND_FORMAT.format(row) + self.nand_inst.append(self.add_inst(name=name, + mod=self.nand2)) + pins =["out_{0}".format(i), + "out_{0}".format(j + len(self.predec_groups[0])), + "Z_{0}".format(row), + "vdd", "gnd"] + self.connect_inst(pins) # Row Decoder NAND GATE array for address inputs >5. @@ -356,16 +358,17 @@ class hierarchical_decoder(design.design): row = (len(self.predec_groups[0])*len(self.predec_groups[1])) * k \ + len(self.predec_groups[0])*j + i - name = self.NAND_FORMAT.format(row) - self.nand_inst.append(self.add_inst(name=name, - mod=self.nand3)) + if (row < self.rows): + name = self.NAND_FORMAT.format(row) + self.nand_inst.append(self.add_inst(name=name, + mod=self.nand3)) - pins = ["out_{0}".format(i), - "out_{0}".format(j + len(self.predec_groups[0])), - "out_{0}".format(k + len(self.predec_groups[0]) + len(self.predec_groups[1])), - "Z_{0}".format(row), - "vdd", "gnd"] - self.connect_inst(pins) + pins = ["out_{0}".format(i), + "out_{0}".format(j + len(self.predec_groups[0])), + "out_{0}".format(k + len(self.predec_groups[0]) + len(self.predec_groups[1])), + "Z_{0}".format(row), + "vdd", "gnd"] + self.connect_inst(pins) def create_decoder_inv_array(self): @@ -527,10 +530,11 @@ class hierarchical_decoder(design.design): for index_B in self.predec_groups[1]: for index_A in self.predec_groups[0]: # FIXME: convert to connect_bus? - predecode_name = "predecode_{}".format(index_A) - self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A")) - predecode_name = "predecode_{}".format(index_B) - self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B")) + if (row_index < self.rows): + predecode_name = "predecode_{}".format(index_A) + self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A")) + predecode_name = "predecode_{}".format(index_B) + self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B")) row_index = row_index + 1 elif (self.num_inputs > 5): @@ -538,12 +542,13 @@ class hierarchical_decoder(design.design): for index_B in self.predec_groups[1]: for index_A in self.predec_groups[0]: # FIXME: convert to connect_bus? - predecode_name = "predecode_{}".format(index_A) - self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A")) - predecode_name = "predecode_{}".format(index_B) - self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B")) - predecode_name = "predecode_{}".format(index_C) - self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("C")) + if (row_index < self.rows): + predecode_name = "predecode_{}".format(index_A) + self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A")) + predecode_name = "predecode_{}".format(index_B) + self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B")) + predecode_name = "predecode_{}".format(index_C) + self.route_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("C")) row_index = row_index + 1 def route_vdd_gnd(self): diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index c349e889..5b901e0c 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -34,14 +34,30 @@ class hierarchical_decoder_test(openram_test): a = factory.create(module_type="hierarchical_decoder", rows=16) self.local_check(a) + debug.info(1, "Testing 17 row sample for hierarchical_decoder") + a = factory.create(module_type="hierarchical_decoder", rows=17) + self.local_check(a) + + debug.info(1, "Testing 23 row sample for hierarchical_decoder") + a = factory.create(module_type="hierarchical_decoder", rows=23) + self.local_check(a) + debug.info(1, "Testing 32 row sample for hierarchical_decoder") a = factory.create(module_type="hierarchical_decoder", rows=32) self.local_check(a) + debug.info(1, "Testing 65 row sample for hierarchical_decoder") + a = factory.create(module_type="hierarchical_decoder", rows=65) + self.local_check(a) + debug.info(1, "Testing 128 row sample for hierarchical_decoder") a = factory.create(module_type="hierarchical_decoder", rows=128) self.local_check(a) + debug.info(1, "Testing 341 row sample for hierarchical_decoder") + a = factory.create(module_type="hierarchical_decoder", rows=341) + self.local_check(a) + debug.info(1, "Testing 512 row sample for hierarchical_decoder") a = factory.create(module_type="hierarchical_decoder", rows=512) self.local_check(a) @@ -57,14 +73,34 @@ class hierarchical_decoder_test(openram_test): a = factory.create(module_type="hierarchical_decoder", rows=16) self.local_check(a) + factory.reset() + debug.info(1, "Testing 17 row sample for hierarchical_decoder (multi-port case)") + a = factory.create(module_type="hierarchical_decoder", rows=17) + self.local_check(a) + + factory.reset() + debug.info(1, "Testing 23 row sample for hierarchical_decoder (multi-port case)") + a = factory.create(module_type="hierarchical_decoder", rows=23) + self.local_check(a) + debug.info(1, "Testing 32 row sample for hierarchical_decoder (multi-port case)") a = factory.create(module_type="hierarchical_decoder", rows=32) self.local_check(a) + factory.reset() + debug.info(1, "Testing 65 row sample for hierarchical_decoder (multi-port case)") + a = factory.create(module_type="hierarchical_decoder", rows=65) + self.local_check(a) + debug.info(1, "Testing 128 row sample for hierarchical_decoder (multi-port case)") a = factory.create(module_type="hierarchical_decoder", rows=128) self.local_check(a) + factory.reset() + debug.info(1, "Testing 341 row sample for hierarchical_decoder (multi-port case)") + a = factory.create(module_type="hierarchical_decoder", rows=341) + self.local_check(a) + debug.info(1, "Testing 512 row sample for hierarchical_decoder (multi-port case)") a = factory.create(module_type="hierarchical_decoder", rows=512) self.local_check(a)