From 774f08da513ea0c62f244fda46939892cbd12689 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 31 Jul 2019 14:11:37 -0700 Subject: [PATCH] Added layout pins to and test for write_mask_and_array. --- compiler/modules/write_driver_array.py | 2 - compiler/modules/write_mask_and_array.py | 141 +++++++++------------- compiler/tests/10_write_mask_and_array.py | 57 +++++++++ 3 files changed, 113 insertions(+), 87 deletions(-) create mode 100644 compiler/tests/10_write_mask_and_array.py diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 5f71b038..7da57b37 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -150,8 +150,6 @@ class write_driver_array(design.design): layer="metal3", offset=pin_pos) - - self.add_layout_pin(text="en", layer="metal1", offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 9a9a8f12..b43399e0 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -16,8 +16,8 @@ from globals import OPTS class write_mask_and_array(design.design): """ - Array of tristate drivers to write to the bitlines through the column mux. - Dynamically generated write driver array of all bitlines. + Array of AND gates to turn write mask signal on only when w_en is on. + The write mask AND array goes between the write driver array and the sense amp array. """ def __init__(self, name, columns, word_size, write_size): @@ -34,29 +34,25 @@ class write_mask_and_array(design.design): self.num_wmasks = int(word_size / write_size) self.create_netlist() - # if not OPTS.netlist_only: - # self.create_layout() + if not OPTS.netlist_only: + self.create_layout() def create_netlist(self): self.add_modules() self.add_pins() -# self.create_write_mask_array() self.create_and2_array() - # def create_layout(self): - # - # if self.bitcell.width > self.driver.width: - # self.width = self.columns * self.bitcell.width - # else: - # self.width = self.columns * self.driver.width - # - # self.height = self.driver.height - # - # self.place_write_array() - # self.add_layout_pins() - # self.add_boundary() - # self.DRC_LVS() + def create_layout(self): + + self.width = self.num_wmasks * self.and2.width + + self.height = self.and2.height + + self.place_and2_array() + self.add_layout_pins() + self.add_boundary() + self.DRC_LVS() def add_pins(self): for bit in range(self.num_wmasks): @@ -68,28 +64,10 @@ class write_mask_and_array(design.design): self.add_pin("gnd","GROUND") def add_modules(self): - self.wmask = factory.create(module_type="dff_buf") - #self.add_mod(self.wmask) - dff_height = self.wmask.height - - self.and2 = factory.create(module_type="pand2", - size=4, - height=dff_height) + self.and2 = factory.create(module_type="pand2") self.add_mod(self.and2) - # def create_write_mask_array(self): - # self.wmask_insts = {} - # for bit in range(self.num_wmask): - # name = "write_mask_{}".format(bit) - # self.wmask_insts[bit] = self.add_inst(name=name, - # mod=self.wmask) - # - # self.connect_inst(["wmask_{}".format(bit), - # "bank_wmask_{}".format(bit), - # "bank_wmask_bar_{}".format(bit), - # "clk", "vdd", "gnd"]) - def create_and2_array(self): self.and2_insts = {} for bit in range(self.num_wmasks): @@ -102,55 +80,48 @@ class write_mask_and_array(design.design): "vdd", "gnd"]) - # def place_write_array(self): - # if self.bitcell.width > self.driver.width: - # driver_spacing = self.bitcell.width - # else: - # driver_spacing = self.driver.width - # - # for i in range(0, self.columns, self.words_per_row): - # index = int(i / self.words_per_row) - # base = vector(i * driver_spacing, 0) - # self.driver_insts[index].place(base) + def place_and2_array(self): + # place the write mask AND array below the write driver array + and2_spacing = self.and2.width + for i in range(self.num_wmasks): + base = vector(i * and2_spacing, 0) + self.and2_insts[i].place(base) + + + def add_layout_pins(self): + for i in range(self.num_wmasks): + wmask_in_pin = self.and2_insts[i].get_pin("A") + self.add_layout_pin(text="wmask_in_{0}".format(i), + layer=wmask_in_pin.layer, + offset=wmask_in_pin.ll(), + width=wmask_in_pin.width(), + height=wmask_in_pin.height()) + + en_pin = self.and2_insts[i].get_pin("B") + self.add_layout_pin(text="en", + layer=en_pin.layer, + offset=en_pin.ll(), + width=en_pin.width(), + height=en_pin.height()) + + wmask_out_pin = self.and2_insts[i].get_pin("Z") + self.add_layout_pin(text="wmask_out_{0}".format(i), + layer=wmask_out_pin.layer, + offset=wmask_out_pin.ll(), + width=wmask_out_pin.width(), + height=wmask_out_pin.height()) + + for n in ["vdd", "gnd"]: + pin_list = self.and2_insts[i].get_pins(n) + for pin in pin_list: + pin_pos = pin.center() + # Add the M2->M3 stack + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=pin_pos) + self.add_layout_pin_rect_center(text=n, + layer="metal3", + offset=pin_pos) - # def add_layout_pins(self): - # for i in range(self.word_size): - # din_pin = self.driver_insts[i].get_pin("din") - # self.add_layout_pin(text="data_{0}".format(i), - # layer="metal2", - # offset=din_pin.ll(), - # width=din_pin.width(), - # height=din_pin.height()) - # bl_pin = self.driver_insts[i].get_pin("bl") - # self.add_layout_pin(text="bl_{0}".format(i), - # layer="metal2", - # offset=bl_pin.ll(), - # width=bl_pin.width(), - # height=bl_pin.height()) - # - # br_pin = self.driver_insts[i].get_pin("br") - # self.add_layout_pin(text="br_{0}".format(i), - # layer="metal2", - # offset=br_pin.ll(), - # width=br_pin.width(), - # height=br_pin.height()) - # - # for n in ["vdd", "gnd"]: - # pin_list = self.driver_insts[i].get_pins(n) - # for pin in pin_list: - # pin_pos = pin.center() - # # Add the M2->M3 stack - # self.add_via_center(layers=("metal2", "via2", "metal3"), - # offset=pin_pos) - # self.add_layout_pin_rect_center(text=n, - # layer="metal3", - # offset=pin_pos) - # - # self.add_layout_pin(text="en", - # layer="metal1", - # offset=self.driver_insts[0].get_pin("en").ll().scale(0, 1), - # width=self.width, - # height=drc('minwidth_metal1')) # def get_w_en_cin(self): # """Get the relative capacitance of all the enable connections in the bank""" diff --git a/compiler/tests/10_write_mask_and_array.py b/compiler/tests/10_write_mask_and_array.py new file mode 100644 index 00000000..c79b8fc6 --- /dev/null +++ b/compiler/tests/10_write_mask_and_array.py @@ -0,0 +1,57 @@ +#!/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 write_mask_and_array_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + # check write driver array for single port + debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4") + a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2") + a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) + self.local_check(a) + + # check write driver array for multi-port + OPTS.bitcell = "pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_w_ports = 0 + OPTS.num_r_ports = 0 + + factory.reset() + debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4 (multi-port case)") + a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2 (multi-port case)") + a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=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()) \ No newline at end of file