diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 718f8f62..1f807d63 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -523,25 +523,9 @@ class bank(design.design): if self.col_addr_size == 0: return - elif self.col_addr_size == 1: - self.column_decoder = factory.create(module_type="pinvbuf", - height=self.dff.height) - elif self.col_addr_size == 2: - self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", - column_decoder=True, - height=self.dff.height) - - elif self.col_addr_size == 3: - self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", - column_decoder=True, - height=self.dff.height) - elif self.col_addr_size == 4: - self.column_decoder = factory.create(module_type="hierarchical_predecode4x16", - column_decoder=True, - height=self.dff.height) else: - # No error checking before? - debug.error("Invalid column decoder?", -1) + self.column_decoder = factory.create(module_type="column_decoder", + col_addr_size=self.col_addr_size) self.column_decoder_inst = [None] * len(self.all_ports) for port in self.all_ports: @@ -927,23 +911,14 @@ class bank(design.design): stack = getattr(self, layer_props.bank.stack) pitch = getattr(self, layer_props.bank.pitch) - if self.col_addr_size == 1: + decode_names = [] + for i in range(self.num_col_addr_lines): + decode_names.append("out_{}".format(i)) - # Connect to sel[0] and sel[1] - decode_names = ["Zb", "Z"] - - # The Address LSB - self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port)) - - elif self.col_addr_size > 1: - decode_names = [] - for i in range(self.num_col_addr_lines): - decode_names.append("out_{}".format(i)) - - for i in range(self.col_addr_size): - decoder_name = "in_{}".format(i) - addr_name = "addr{0}_{1}".format(port, i) - self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name) + for i in range(self.col_addr_size): + decoder_name = "in_{}".format(i) + addr_name = "addr{0}_{1}".format(port, i) + self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name) if port % 2: offset = self.column_decoder_inst[port].ll() - vector((self.num_col_addr_lines + 1) * pitch, 0) diff --git a/compiler/modules/column_decoder.py b/compiler/modules/column_decoder.py index 09de25fb..9cb08284 100644 --- a/compiler/modules/column_decoder.py +++ b/compiler/modules/column_decoder.py @@ -24,7 +24,7 @@ class column_decoder(design.design): self.col_addr_size = col_addr_size self.num_inputs = col_addr_size - self.num_outputs = pow(col_addr_size, 2) + self.num_outputs = pow(2, col_addr_size) debug.info(2, "create column decoder of {0} inputs and {1} outputs".format(self.num_inputs, self.num_outputs)) @@ -68,11 +68,16 @@ class column_decoder(design.design): def route_layout_pins(self): """ Add the pins. """ - for i in range(self.num_inputs): - self.copy_layout_pin(self.column_decoder_inst, "in_{0}".format(i)) + if self.col_addr_size == 1: + self.copy_layout_pin(self.column_decoder_inst, "A", "in_0") + self.copy_layout_pin(self.column_decoder_inst, "Zb", "out_0") + self.copy_layout_pin(self.column_decoder_inst, "Z", "out_1") + elif self.col_addr_size > 1: + for i in range(self.num_inputs): + self.copy_layout_pin(self.column_decoder_inst, "in_{0}".format(i)) - for i in range(self.num_outputs): - self.copy_layout_pin(self.column_decoder_inst, "out_{0}".format(i)) + for i in range(self.num_outputs): + self.copy_layout_pin(self.column_decoder_inst, "out_{0}".format(i)) def route_layout(self): """ Create routing among the modules """ @@ -81,9 +86,12 @@ class column_decoder(design.design): def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ - - self.route_vertical_pins("vdd", self.insts, xside="rx",) - self.route_vertical_pins("gnd", self.insts, xside="lx",) + if self.col_addr_size == 1: + self.copy_power_pins(self.column_decoder_inst, "vdd") + self.copy_power_pins(self.column_decoder_inst, "gnd") + else: + self.route_vertical_pins("vdd", self.insts, xside="rx",) + self.route_vertical_pins("gnd", self.insts, xside="lx",) def add_modules(self): diff --git a/compiler/options.py b/compiler/options.py index c7c062ba..26bcb099 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -171,6 +171,7 @@ class options(optparse.Values): bitcell_array = "bitcell_array" bitcell = "bitcell" buf_dec = "pbuf" + column_decoder = "column_decoder" column_mux_array = "column_mux_array" control_logic = "control_logic" decoder = "hierarchical_decoder" diff --git a/compiler/tests/06_column_decoder_16row_test.py b/compiler/tests/06_column_decoder_16row_test.py new file mode 100755 index 00000000..2823b647 --- /dev/null +++ b/compiler/tests/06_column_decoder_16row_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 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 column_decoder_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 = 0 + OPTS.num_w_ports = 0 + globals.setup_bitcell() + + # Checks 2x4 and 2-input NAND decoder + debug.info(1, "Testing 16 row sample for column_decoder") + a = factory.create(module_type="column_decoder", col_addr_size=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())