mirror of https://github.com/VLSIDA/OpenRAM.git
Spare columns in full sram layout
This commit is contained in:
parent
a5c211bd90
commit
8bd1052fc2
|
|
@ -20,7 +20,7 @@ class control_logic(design.design):
|
||||||
Dynamically generated Control logic for the total SRAM circuit.
|
Dynamically generated Control logic for the total SRAM circuit.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, num_rows, words_per_row, word_size, sram=None, port_type="rw", name=""):
|
def __init__(self, num_rows, words_per_row, word_size, spare_columns=None, sram=None, port_type="rw", name=""):
|
||||||
""" Constructor """
|
""" Constructor """
|
||||||
name = "control_logic_" + port_type
|
name = "control_logic_" + port_type
|
||||||
design.design.__init__(self, name)
|
design.design.__init__(self, name)
|
||||||
|
|
@ -35,7 +35,12 @@ class control_logic(design.design):
|
||||||
self.word_size = word_size
|
self.word_size = word_size
|
||||||
self.port_type = port_type
|
self.port_type = port_type
|
||||||
|
|
||||||
self.num_cols = word_size * words_per_row
|
if not spare_columns:
|
||||||
|
self.num_spare_cols = spare_columns
|
||||||
|
else:
|
||||||
|
self.num_spare_cols = 0
|
||||||
|
|
||||||
|
self.num_cols = word_size * words_per_row + self.num_spare_cols
|
||||||
self.num_words = num_rows * words_per_row
|
self.num_words = num_rows * words_per_row
|
||||||
|
|
||||||
self.enable_delay_chain_resizing = False
|
self.enable_delay_chain_resizing = False
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ class sram_1bank(sram_base):
|
||||||
self.wmask_bus_size = self.m2_nonpref_pitch * (max(self.num_wmasks + 1, self.col_addr_size + 1)) + self.wmask_bus_gap
|
self.wmask_bus_size = self.m2_nonpref_pitch * (max(self.num_wmasks + 1, self.col_addr_size + 1)) + self.wmask_bus_gap
|
||||||
else:
|
else:
|
||||||
self.data_bus_gap = self.m3_nonpref_pitch * 2
|
self.data_bus_gap = self.m3_nonpref_pitch * 2
|
||||||
self.data_bus_size = self.m3_nonpref_pitch * (max(self.word_size + 1, self.col_addr_size + 1)) + self.data_bus_gap
|
self.data_bus_size = self.m3_nonpref_pitch * (max(self.word_size + self.num_spare_cols + 1, self.col_addr_size + 1)) + self.data_bus_gap
|
||||||
|
|
||||||
self.col_addr_bus_gap = self.m2_nonpref_pitch * 2
|
self.col_addr_bus_gap = self.m2_nonpref_pitch * 2
|
||||||
self.col_addr_bus_size = self.m2_nonpref_pitch * (self.col_addr_size) + self.col_addr_bus_gap
|
self.col_addr_bus_size = self.m2_nonpref_pitch * (self.col_addr_size) + self.col_addr_bus_gap
|
||||||
|
|
@ -191,7 +191,7 @@ class sram_1bank(sram_base):
|
||||||
signal + "{}".format(port))
|
signal + "{}".format(port))
|
||||||
|
|
||||||
if port in self.read_ports:
|
if port in self.read_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.copy_layout_pin(self.bank_inst,
|
self.copy_layout_pin(self.bank_inst,
|
||||||
"dout{0}_{1}".format(port, bit),
|
"dout{0}_{1}".format(port, bit),
|
||||||
"dout{0}[{1}]".format(port, bit))
|
"dout{0}[{1}]".format(port, bit))
|
||||||
|
|
@ -208,7 +208,7 @@ class sram_1bank(sram_base):
|
||||||
"addr{0}[{1}]".format(port, bit + self.col_addr_size))
|
"addr{0}[{1}]".format(port, bit + self.col_addr_size))
|
||||||
|
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.copy_layout_pin(self.data_dff_insts[port],
|
self.copy_layout_pin(self.data_dff_insts[port],
|
||||||
"din_{}".format(bit),
|
"din_{}".format(bit),
|
||||||
"din{0}[{1}]".format(port, bit))
|
"din{0}[{1}]".format(port, bit))
|
||||||
|
|
@ -218,6 +218,10 @@ class sram_1bank(sram_base):
|
||||||
self.copy_layout_pin(self.wmask_dff_insts[port],
|
self.copy_layout_pin(self.wmask_dff_insts[port],
|
||||||
"din_{}".format(bit),
|
"din_{}".format(bit),
|
||||||
"wmask{0}[{1}]".format(port, bit))
|
"wmask{0}[{1}]".format(port, bit))
|
||||||
|
for bit in range(self.num_spare_cols):
|
||||||
|
self.copy_layout_pin(self.bank_inst,
|
||||||
|
"spare_wen{0}_{1}".format(port, bit),
|
||||||
|
"spare_wen{0}[{1}]".format(port, bit))
|
||||||
|
|
||||||
def route_layout(self):
|
def route_layout(self):
|
||||||
""" Route a single bank SRAM """
|
""" Route a single bank SRAM """
|
||||||
|
|
@ -380,7 +384,7 @@ class sram_1bank(sram_base):
|
||||||
else:
|
else:
|
||||||
offset = self.data_dff_insts[port].ul() + vector(0, self.data_bus_gap)
|
offset = self.data_dff_insts[port].ul() + vector(0, self.data_bus_gap)
|
||||||
|
|
||||||
dff_names = ["dout_{}".format(x) for x in range(self.word_size)]
|
dff_names = ["dout_{}".format(x) for x in range(self.word_size + self.num_spare_cols)]
|
||||||
dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names]
|
dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names]
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
for x in dff_names:
|
for x in dff_names:
|
||||||
|
|
@ -393,7 +397,7 @@ class sram_1bank(sram_base):
|
||||||
to_layer="m4",
|
to_layer="m4",
|
||||||
offset=pin_offset)
|
offset=pin_offset)
|
||||||
|
|
||||||
bank_names = ["din{0}_{1}".format(port, x) for x in range(self.word_size)]
|
bank_names = ["din{0}_{1}".format(port, x) for x in range(self.word_size + self.num_spare_cols)]
|
||||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
for x in bank_names:
|
for x in bank_names:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ class sram_base(design, verilog, lef):
|
||||||
else:
|
else:
|
||||||
self.num_wmasks = 0
|
self.num_wmasks = 0
|
||||||
|
|
||||||
|
if not self.num_spare_cols:
|
||||||
|
self.num_spare_cols = 0
|
||||||
|
|
||||||
# For logical effort delay calculations.
|
# For logical effort delay calculations.
|
||||||
self.all_mods_except_control_done = False
|
self.all_mods_except_control_done = False
|
||||||
|
|
||||||
|
|
@ -44,7 +47,7 @@ class sram_base(design, verilog, lef):
|
||||||
""" Add pins for entire SRAM. """
|
""" Add pins for entire SRAM. """
|
||||||
|
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.add_pin("din{0}[{1}]".format(port, bit), "INPUT")
|
self.add_pin("din{0}[{1}]".format(port, bit), "INPUT")
|
||||||
|
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
|
|
@ -75,8 +78,10 @@ class sram_base(design, verilog, lef):
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
self.add_pin("wmask{0}[{1}]".format(port, bit), "INPUT")
|
self.add_pin("wmask{0}[{1}]".format(port, bit), "INPUT")
|
||||||
|
for bit in range(self.num_spare_cols):
|
||||||
|
self.add_pin("spare_wen{0}[{1}]".format(port, bit), "INPUT")
|
||||||
for port in self.read_ports:
|
for port in self.read_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.add_pin("dout{0}[{1}]".format(port, bit), "OUTPUT")
|
self.add_pin("dout{0}[{1}]".format(port, bit), "OUTPUT")
|
||||||
|
|
||||||
self.add_pin("vdd", "POWER")
|
self.add_pin("vdd", "POWER")
|
||||||
|
|
@ -274,7 +279,7 @@ class sram_base(design, verilog, lef):
|
||||||
else:
|
else:
|
||||||
self.col_addr_dff = None
|
self.col_addr_dff = None
|
||||||
|
|
||||||
self.data_dff = factory.create("dff_array", module_name="data_dff", rows=1, columns=self.word_size)
|
self.data_dff = factory.create("dff_array", module_name="data_dff", rows=1, columns=self.word_size + self.num_spare_cols)
|
||||||
self.add_mod(self.data_dff)
|
self.add_mod(self.data_dff)
|
||||||
|
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
|
|
@ -303,6 +308,7 @@ class sram_base(design, verilog, lef):
|
||||||
self.control_logic_rw = self.mod_control_logic(num_rows=self.num_rows,
|
self.control_logic_rw = self.mod_control_logic(num_rows=self.num_rows,
|
||||||
words_per_row=self.words_per_row,
|
words_per_row=self.words_per_row,
|
||||||
word_size=self.word_size,
|
word_size=self.word_size,
|
||||||
|
spare_columns=self.num_spare_cols,
|
||||||
sram=self,
|
sram=self,
|
||||||
port_type="rw")
|
port_type="rw")
|
||||||
self.add_mod(self.control_logic_rw)
|
self.add_mod(self.control_logic_rw)
|
||||||
|
|
@ -310,6 +316,7 @@ class sram_base(design, verilog, lef):
|
||||||
self.control_logic_w = self.mod_control_logic(num_rows=self.num_rows,
|
self.control_logic_w = self.mod_control_logic(num_rows=self.num_rows,
|
||||||
words_per_row=self.words_per_row,
|
words_per_row=self.words_per_row,
|
||||||
word_size=self.word_size,
|
word_size=self.word_size,
|
||||||
|
spare_columns=self.num_spare_cols,
|
||||||
sram=self,
|
sram=self,
|
||||||
port_type="w")
|
port_type="w")
|
||||||
self.add_mod(self.control_logic_w)
|
self.add_mod(self.control_logic_w)
|
||||||
|
|
@ -317,6 +324,7 @@ class sram_base(design, verilog, lef):
|
||||||
self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows,
|
self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows,
|
||||||
words_per_row=self.words_per_row,
|
words_per_row=self.words_per_row,
|
||||||
word_size=self.word_size,
|
word_size=self.word_size,
|
||||||
|
spare_columns=self.num_spare_cols,
|
||||||
sram=self,
|
sram=self,
|
||||||
port_type="r")
|
port_type="r")
|
||||||
self.add_mod(self.control_logic_r)
|
self.add_mod(self.control_logic_r)
|
||||||
|
|
@ -328,12 +336,12 @@ class sram_base(design, verilog, lef):
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for port in self.read_ports:
|
for port in self.read_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
temp.append("dout{0}[{1}]".format(port, bit))
|
temp.append("dout{0}[{1}]".format(port, bit))
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
temp.append("rbl_bl{0}".format(port))
|
temp.append("rbl_bl{0}".format(port))
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
temp.append("bank_din{0}[{1}]".format(port, bit))
|
temp.append("bank_din{0}[{1}]".format(port, bit))
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
for bit in range(self.bank_addr_size):
|
for bit in range(self.bank_addr_size):
|
||||||
|
|
@ -349,6 +357,8 @@ class sram_base(design, verilog, lef):
|
||||||
temp.append("w_en{0}".format(port))
|
temp.append("w_en{0}".format(port))
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
temp.append("bank_wmask{}[{}]".format(port, bit))
|
temp.append("bank_wmask{}[{}]".format(port, bit))
|
||||||
|
for bit in range(self.num_spare_cols):
|
||||||
|
temp.append("spare_wen{0}[{1}]".format(port, bit))
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
temp.append("wl_en{0}".format(port))
|
temp.append("wl_en{0}".format(port))
|
||||||
temp.extend(["vdd", "gnd"])
|
temp.extend(["vdd", "gnd"])
|
||||||
|
|
@ -436,7 +446,7 @@ class sram_base(design, verilog, lef):
|
||||||
# inputs, outputs/output/bar
|
# inputs, outputs/output/bar
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = []
|
outputs = []
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
inputs.append("din{}[{}]".format(port, bit))
|
inputs.append("din{}[{}]".format(port, bit))
|
||||||
outputs.append("bank_din{}[{}]".format(port, bit))
|
outputs.append("bank_din{}[{}]".format(port, bit))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
#!/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 sram_1bank_2mux_1rw_1r_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
from sram_config import sram_config
|
||||||
|
|
||||||
|
OPTS.bitcell = "bitcell_1rw_1r"
|
||||||
|
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||||
|
OPTS.dummy_bitcell="dummy_bitcell_1rw_1r"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
|
||||||
|
c = sram_config(word_size=4,
|
||||||
|
num_words=32,
|
||||||
|
num_spare_cols=3,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
c.words_per_row=2
|
||||||
|
c.recompute_sizes()
|
||||||
|
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||||
|
"with {} bit words, {} words, {} words per "
|
||||||
|
"row, {} banks".format(OPTS.num_rw_ports,
|
||||||
|
OPTS.num_r_ports,
|
||||||
|
OPTS.num_w_ports,
|
||||||
|
c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
a = factory.create(module_type="sram", sram_config=c)
|
||||||
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
#@unittest.skip("SKIPPING 20_psram_1bank_2mux_1w_1r_test, odd supply routing error")
|
||||||
|
class psram_1bank_2mux_1w_1r_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
from sram_config import sram_config
|
||||||
|
|
||||||
|
OPTS.bitcell = "bitcell_1w_1r"
|
||||||
|
OPTS.replica_bitcell="replica_bitcell_1w_1r"
|
||||||
|
OPTS.dummy_bitcell="dummy_bitcell_1w_1r"
|
||||||
|
OPTS.num_rw_ports = 0
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
|
c = sram_config(word_size=4,
|
||||||
|
num_words=32,
|
||||||
|
num_spare_cols=3,
|
||||||
|
num_banks=1)
|
||||||
|
c.num_words=32
|
||||||
|
c.words_per_row=2
|
||||||
|
c.recompute_sizes()
|
||||||
|
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||||
|
"with {} bit words, {} words, {} words per "
|
||||||
|
"row, {} banks".format(OPTS.num_rw_ports,
|
||||||
|
OPTS.num_r_ports,
|
||||||
|
OPTS.num_w_ports,
|
||||||
|
c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
a = factory.create(module_type="sram", sram_config=c)
|
||||||
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/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 sram_1bank_nomux_1rw_1r_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||||
|
globals.init_openram(config_file)
|
||||||
|
from sram_config import sram_config
|
||||||
|
|
||||||
|
OPTS.bitcell = "bitcell_1rw_1r"
|
||||||
|
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||||
|
OPTS.dummy_bitcell = "dummy_bitcell_1rw_1r"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
|
||||||
|
c = sram_config(word_size=4,
|
||||||
|
num_words=16,
|
||||||
|
num_spare_cols=4,
|
||||||
|
num_banks=1)
|
||||||
|
|
||||||
|
c.words_per_row=1
|
||||||
|
c.recompute_sizes()
|
||||||
|
debug.info(1, "Layout test for {}rw,{}r,{}w sram "
|
||||||
|
"with {} bit words, {} words, {} words per "
|
||||||
|
"row, {} spare columns, {} banks".format(OPTS.num_rw_ports,
|
||||||
|
OPTS.num_r_ports,
|
||||||
|
OPTS.num_w_ports,
|
||||||
|
c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_spare_cols,
|
||||||
|
c.num_banks))
|
||||||
|
a = factory.create(module_type="sram", sram_config=c)
|
||||||
|
self.local_check(a, final_verification=True)
|
||||||
|
|
||||||
|
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())
|
||||||
Loading…
Reference in New Issue