mirror of https://github.com/VLSIDA/OpenRAM.git
Commiting working version of multi-port that can generate a netlist on the sram level. Changes that will clean up the code are forthcoming.
This commit is contained in:
parent
c91735b23b
commit
1429b9ab1a
|
|
@ -67,13 +67,27 @@ class bank(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
self.din_list = []
|
||||
self.dout_list = []
|
||||
port_number = 0
|
||||
for port in range(OPTS.num_rw_ports):
|
||||
self.din_list.append("din{}".format(port_number))
|
||||
self.dout_list.append("dout{}".format(port_number))
|
||||
port_number += 1
|
||||
for port in range(OPTS.num_w_ports):
|
||||
self.din_list.append("din{}".format(port_number))
|
||||
port_number += 1
|
||||
for port in range(OPTS.num_r_ports):
|
||||
self.dout_list.append("dout{}".format(port_number))
|
||||
port_number += 1
|
||||
|
||||
""" Adding pins for Bank module"""
|
||||
for port in range(self.total_read):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout{0}[{1}]".format(port,bit),"OUT")
|
||||
self.add_pin(self.dout_list[port]+"[{0}]".format(bit),"OUT")
|
||||
for port in range(self.total_write):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("din{0}[{1}]".format(port,bit),"IN")
|
||||
self.add_pin(self.din_list[port]+"[{0}]".format(bit),"IN")
|
||||
for port in range(self.total_ports):
|
||||
for bit in range(self.addr_size):
|
||||
self.add_pin("addr{0}[{1}]".format(port,bit),"INPUT")
|
||||
|
|
@ -350,7 +364,7 @@ class bank(design.design):
|
|||
|
||||
temp = []
|
||||
for bit in range(self.word_size):
|
||||
temp.append("dout{0}[{1}]".format(port,bit))
|
||||
temp.append(self.dout_list[port]+"[{0}]".format(bit))
|
||||
if self.words_per_row == 1:
|
||||
temp.append(self.read_bl_list[port]+"[{0}]".format(bit))
|
||||
temp.append(self.read_br_list[port]+"[{0}]".format(bit))
|
||||
|
|
@ -379,7 +393,7 @@ class bank(design.design):
|
|||
|
||||
temp = []
|
||||
for bit in range(self.word_size):
|
||||
temp.append("din{0}[{1}]".format(port,bit))
|
||||
temp.append(self.din_list[port]+"[{0}]".format(bit))
|
||||
for bit in range(self.word_size):
|
||||
if (self.words_per_row == 1):
|
||||
temp.append(self.write_bl_list[port]+"[{0}]".format(bit))
|
||||
|
|
@ -547,29 +561,35 @@ class bank(design.design):
|
|||
|
||||
# These are the instances that every bank has
|
||||
top_instances = [self.bitcell_array_inst]
|
||||
|
||||
for port in range(self.total_read):
|
||||
#top_instances.append(self.precharge_array_inst[port])
|
||||
top_instances.append(self.sense_amp_array_inst[port])
|
||||
for port in range(self.total_write):
|
||||
top_instances.append(self.write_driver_array_inst[port])
|
||||
for port in range(self.total_ports):
|
||||
top_instances.extend([self.precharge_array_inst[port],
|
||||
self.sense_amp_array_inst[port],
|
||||
self.write_driver_array_inst[port],
|
||||
self.row_decoder_inst[port],
|
||||
top_instances.extend([self.row_decoder_inst[port],
|
||||
self.wordline_driver_inst[port]])
|
||||
# Add these if we use the part...
|
||||
if self.col_addr_size > 0:
|
||||
top_instances.append(self.col_decoder_inst[port])
|
||||
top_instances.append(self.col_mux_array_inst[port])
|
||||
#top_instances.append(self.col_mux_array_inst[port])
|
||||
|
||||
if self.num_banks > 1:
|
||||
top_instances.append(self.bank_select_inst[port])
|
||||
|
||||
|
||||
if self.col_addr_size > 0:
|
||||
for port in range(self.total_ports):
|
||||
self.copy_layout_pin(self.col_mux_array_inst[port], "gnd")
|
||||
for port in range(self.total_read):
|
||||
self.copy_layout_pin(self.precharge_array_inst[port], "vdd")
|
||||
|
||||
for inst in top_instances:
|
||||
# Column mux has no vdd
|
||||
if self.col_addr_size==0 or (self.col_addr_size>0 and inst != self.col_mux_array_inst[0]):
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
#if self.col_addr_size==0 or (self.col_addr_size>0 and inst != self.col_mux_array_inst[0]):
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
# Precharge has no gnd
|
||||
if inst != self.precharge_array_inst[0]:
|
||||
self.copy_layout_pin(inst, "gnd")
|
||||
#if inst != self.precharge_array_inst[port]:
|
||||
self.copy_layout_pin(inst, "gnd")
|
||||
|
||||
def route_bank_select(self):
|
||||
""" Route the bank select logic. """
|
||||
|
|
|
|||
|
|
@ -128,7 +128,21 @@ class replica_bitline(design.design):
|
|||
|
||||
self.rbl_inst=self.add_inst(name="load",
|
||||
mod=self.rbl)
|
||||
self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.bitcell_loads + ["vdd", "gnd"])
|
||||
|
||||
total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||
temp = []
|
||||
temp.append("bl[0]")
|
||||
temp.append("br[0]")
|
||||
for port in range(total_ports - 1):
|
||||
temp.append("gnd")
|
||||
temp.append("gnd")
|
||||
for wl in range(self.bitcell_loads):
|
||||
for port in range(total_ports):
|
||||
temp.append("gnd")
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
#self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.bitcell_loads + ["vdd", "gnd"])
|
||||
|
||||
def place_modules(self):
|
||||
""" Add all of the module instances in the logical netlist """
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ class sram_1bank(sram_base):
|
|||
|
||||
self.bank_inst=self.create_bank(0)
|
||||
|
||||
self.control_logic_inst = self.create_control_logic()
|
||||
self.control_logic_inst = [None] * self.total_ports
|
||||
for port in range(self.total_ports):
|
||||
self.control_logic_inst[port] = self.create_control_logic(port)
|
||||
|
||||
self.row_addr_dff_inst = self.create_row_addr_dff()
|
||||
|
||||
|
|
@ -59,11 +61,11 @@ class sram_1bank(sram_base):
|
|||
# up to the row address DFFs.
|
||||
control_pos = vector(-self.control_logic.width - 2*self.m2_pitch,
|
||||
self.bank.bank_center.y - self.control_logic.control_logic_center.y)
|
||||
self.control_logic_inst.place(control_pos)
|
||||
self.control_logic_inst[0].place(control_pos)
|
||||
|
||||
# The row address bits are placed above the control logic aligned on the right.
|
||||
row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width,
|
||||
self.control_logic_inst.uy())
|
||||
row_addr_pos = vector(self.control_logic_inst[0].rx() - self.row_addr_dff.width,
|
||||
self.control_logic_inst[0].uy())
|
||||
self.row_addr_dff_inst.place(row_addr_pos)
|
||||
|
||||
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
|
||||
|
|
@ -95,7 +97,7 @@ class sram_1bank(sram_base):
|
|||
"""
|
||||
# Connect the control pins as inputs
|
||||
for n in self.control_logic_inputs + ["clk"]:
|
||||
self.copy_layout_pin(self.control_logic_inst, n)
|
||||
self.copy_layout_pin(self.control_logic_inst[0], n)
|
||||
|
||||
for i in range(self.word_size):
|
||||
dout_name = "dout0[{}]".format(i)
|
||||
|
|
@ -134,7 +136,7 @@ class sram_1bank(sram_base):
|
|||
""" Route the clock network """
|
||||
|
||||
# This is the actual input to the SRAM
|
||||
self.copy_layout_pin(self.control_logic_inst, "clk")
|
||||
self.copy_layout_pin(self.control_logic_inst[0], "clk")
|
||||
|
||||
# Connect all of these clock pins to the clock in the central bus
|
||||
# This is something like a "spine" clock distribution. The two spines
|
||||
|
|
@ -158,7 +160,7 @@ class sram_1bank(sram_base):
|
|||
|
||||
# This uses a metal2 track to the right of the control/row addr DFF
|
||||
# to route vertically.
|
||||
control_clk_buf_pin = self.control_logic_inst.get_pin("clk_buf")
|
||||
control_clk_buf_pin = self.control_logic_inst[0].get_pin("clk_buf")
|
||||
control_clk_buf_pos = control_clk_buf_pin.rc()
|
||||
row_addr_clk_pin = self.row_addr_dff_inst.get_pin("clk")
|
||||
row_addr_clk_pos = row_addr_clk_pin.rc()
|
||||
|
|
@ -177,7 +179,7 @@ class sram_1bank(sram_base):
|
|||
top_instances = [self.bank_inst,
|
||||
self.row_addr_dff_inst,
|
||||
self.data_dff_inst,
|
||||
self.control_logic_inst]
|
||||
self.control_logic_inst[0]]
|
||||
if self.col_addr_dff:
|
||||
top_instances.append(self.col_addr_dff_inst)
|
||||
|
||||
|
|
@ -193,7 +195,7 @@ class sram_1bank(sram_base):
|
|||
top_instances = [self.bank_inst,
|
||||
self.row_addr_dff_inst,
|
||||
self.data_dff_inst,
|
||||
self.control_logic_inst]
|
||||
self.control_logic_inst[0]]
|
||||
if self.col_addr_dff:
|
||||
top_instances.append(self.col_addr_dff_inst)
|
||||
|
||||
|
|
@ -267,7 +269,7 @@ class sram_1bank(sram_base):
|
|||
def route_control_logic(self):
|
||||
""" Route the outputs from the control logic module """
|
||||
for n in self.control_logic_outputs:
|
||||
src_pin = self.control_logic_inst.get_pin(n)
|
||||
src_pin = self.control_logic_inst[0].get_pin(n)
|
||||
dest_pin = self.bank_inst.get_pin(n)
|
||||
self.connect_rail_from_left_m2m3(src_pin, dest_pin)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
|
|
@ -332,7 +334,7 @@ class sram_1bank(sram_base):
|
|||
"""
|
||||
|
||||
for n in self.control_logic_outputs:
|
||||
pin = self.control_logic_inst.get_pin(n)
|
||||
pin = self.control_logic_inst[0].get_pin(n)
|
||||
self.add_label(text=n,
|
||||
layer=pin.layer,
|
||||
offset=pin.center())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class sram_base(design):
|
|||
self.sram_config = sram_config
|
||||
sram_config.set_local_config(self)
|
||||
|
||||
print("PORTS: {} - {} - {}".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports))
|
||||
self.total_write = OPTS.num_rw_ports + OPTS.num_w_ports
|
||||
self.total_read = OPTS.num_rw_ports + OPTS.num_r_ports
|
||||
self.total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||
|
|
@ -28,10 +29,29 @@ class sram_base(design):
|
|||
|
||||
def add_pins(self):
|
||||
""" Add pins for entire SRAM. """
|
||||
self.din_list = []
|
||||
self.DIN_list = []
|
||||
self.dout_list = []
|
||||
self.DOUT_list = []
|
||||
port_number = 0
|
||||
for port in range(OPTS.num_rw_ports):
|
||||
self.din_list.append("din{}".format(port_number))
|
||||
self.dout_list.append("dout{}".format(port_number))
|
||||
self.DIN_list.append("DIN{}".format(port_number))
|
||||
self.DOUT_list.append("DOUT{}".format(port_number))
|
||||
port_number += 1
|
||||
for port in range(OPTS.num_w_ports):
|
||||
self.din_list.append("din{}".format(port_number))
|
||||
self.DIN_list.append("DIN{}".format(port_number))
|
||||
port_number += 1
|
||||
for port in range(OPTS.num_r_ports):
|
||||
self.dout_list.append("dout{}".format(port_number))
|
||||
self.DOUT_list.append("DOUT{}".format(port_number))
|
||||
port_number += 1
|
||||
|
||||
for port in range(self.total_write):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("DIN{0}[{1}]".format(port,bit),"INPUT")
|
||||
self.add_pin(self.DIN_list[port]+"[{0}]".format(bit),"INPUT")
|
||||
|
||||
for port in range(self.total_ports):
|
||||
for bit in range(self.addr_size):
|
||||
|
|
@ -41,11 +61,15 @@ class sram_base(design):
|
|||
self.control_logic_inputs=self.control_logic.get_inputs()
|
||||
self.control_logic_outputs=self.control_logic.get_outputs()
|
||||
|
||||
self.add_pin_list(self.control_logic_inputs,"INPUT")
|
||||
#self.add_pin_list(self.control_logic_inputs,"INPUT")
|
||||
self.add_pin("csb","INPUT")
|
||||
for port in range(self.total_write):
|
||||
self.add_pin("web{}".format(port),"INPUT")
|
||||
self.add_pin("clk","INPUT")
|
||||
|
||||
for port in range(self.total_read):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("DOUT{0}[{1}]".format(port,bit),"OUTPUT")
|
||||
self.add_pin(self.DOUT_list[port]+"[{0}]".format(bit),"OUTPUT")
|
||||
|
||||
self.add_pin("vdd","POWER")
|
||||
self.add_pin("gnd","GROUND")
|
||||
|
|
@ -234,9 +258,11 @@ class sram_base(design):
|
|||
else:
|
||||
self.col_addr_dff = None
|
||||
|
||||
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size*self.total_ports)
|
||||
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size*self.total_write)
|
||||
self.add_mod(self.data_dff)
|
||||
|
||||
print("PORTS: {} - {} - {}".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports))
|
||||
|
||||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
self.bank = bank(self.sram_config,
|
||||
|
|
@ -262,7 +288,7 @@ class sram_base(design):
|
|||
temp = []
|
||||
for port in range(self.total_read):
|
||||
for bit in range(self.word_size):
|
||||
temp.append("DOUT{0}[{1}]".format(port,bit))
|
||||
temp.append(self.DOUT_list[port]+"[{0}]".format(bit))
|
||||
for port in range(self.total_write):
|
||||
for bit in range(self.word_size):
|
||||
temp.append("BANK_DIN{0}[{1}]".format(port,bit))
|
||||
|
|
@ -321,10 +347,10 @@ class sram_base(design):
|
|||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
for i in range(self.row_addr_size):
|
||||
inputs.append("ADDR{}[{}]".format(k,i+self.col_addr_size))
|
||||
outputs.append("A{}[{}]".format(k,i+self.col_addr_size))
|
||||
inputs.append("ADDR{}[{}]".format(port,i+self.col_addr_size))
|
||||
outputs.append("A{}[{}]".format(port,i+self.col_addr_size))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
|
||||
return inst
|
||||
|
|
@ -337,10 +363,10 @@ class sram_base(design):
|
|||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
for i in range(self.col_addr_size):
|
||||
inputs.append("ADDR{}[{}]".format(k,i))
|
||||
outputs.append("A{}[{}]".format(k,i))
|
||||
inputs.append("ADDR{}[{}]".format(port,i))
|
||||
outputs.append("A{}[{}]".format(port,i))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
|
||||
return inst
|
||||
|
|
@ -353,20 +379,24 @@ class sram_base(design):
|
|||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for k in range(self.total_write):
|
||||
for port in range(self.total_write):
|
||||
for i in range(self.word_size):
|
||||
inputs.append("DIN{}[{}]".format(k,i))
|
||||
outputs.append("BANK_DIN{}[{}]".format(k,i))
|
||||
inputs.append("DIN{}[{}]".format(port,i))
|
||||
outputs.append("BANK_DIN{}[{}]".format(port,i))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
|
||||
return inst
|
||||
|
||||
def create_control_logic(self):
|
||||
def create_control_logic(self, port):
|
||||
""" Add and place control logic """
|
||||
inst = self.add_inst(name="control",
|
||||
mod=self.control_logic)
|
||||
|
||||
self.connect_inst(self.control_logic_inputs + self.control_logic_outputs + ["vdd", "gnd"])
|
||||
self.connect_inst(["csb", "web{}".format(port), "clk",
|
||||
"s_en{}".format(port), "w_en{}".format(port), "clk_buf_bar", "clk_buf",
|
||||
"vdd", "gnd"])
|
||||
|
||||
#self.connect_inst(self.control_logic_inputs + self.control_logic_outputs + ["vdd", "gnd"])
|
||||
return inst
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a regression test on a 1 bank SRAM
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
class sram_1bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
c.words_per_row=1
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.netlist_only = True
|
||||
|
||||
debug.info(1, "Single bank, no column mux with control logic")
|
||||
a = sram(c, "sram1")
|
||||
self.local_check(a, final_verification=True)
|
||||
"""
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Single bank two way column mux with control logic")
|
||||
a = sram(c, "sram2")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Single bank, four way column mux with control logic")
|
||||
a = sram(c, "sram3")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Single bank, eight way column mux with control logic")
|
||||
a = sram(c, "sram4")
|
||||
self.local_check(a, final_verification=True)
|
||||
"""
|
||||
#globals.end_openram()
|
||||
|
||||
# instantiate a copy 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()
|
||||
Loading…
Reference in New Issue