Merge remote-tracking branch 'origin/multiport' into multiport

This commit is contained in:
Matt Guthaus 2018-09-04 10:47:55 -07:00
commit 19c0e1638b
10 changed files with 154 additions and 51 deletions

View File

@ -81,7 +81,8 @@ class bank(design.design):
# For more than one bank, we have a bank select and name
# the signals gated_*.
if self.num_banks > 1:
self.add_pin("bank_sel","INPUT")
for port in range(self.total_ports):
self.add_pin("bank_sel{}".format(port),"INPUT")
for port in range(self.total_read):
self.add_pin("s_en{0}".format(port), "INPUT")
for port in range(self.total_write):
@ -513,12 +514,12 @@ class bank(design.design):
self.bank_select_inst = []
for port in range(self.total_ports):
self.bank_select_inst.append(self.add_inst(name="bank_select",
self.bank_select_inst.append(self.add_inst(name="bank_select{}".format(port),
mod=self.bank_select))
temp = []
temp.extend(self.input_control_signals)
temp.append("bank_sel")
temp.append("bank_sel{}".format(port))
temp.extend(self.control_signals)
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)

View File

@ -30,7 +30,11 @@ class sense_amp_array(design.design):
def create_layout(self):
self.height = self.amp.height
self.width = self.amp.width * self.word_size * self.words_per_row
if self.bitcell.width > self.amp.width:
self.width = self.bitcell.width * self.word_size * self.words_per_row
else:
self.width = self.amp.width * self.word_size * self.words_per_row
self.place_sense_amp_array()
self.add_layout_pins()
@ -53,6 +57,10 @@ class sense_amp_array(design.design):
self.amp = self.mod_sense_amp("sense_amp")
self.add_mod(self.amp)
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.add_mod(self.bitcell)
def create_sense_amp_array(self):
self.local_insts = []
@ -68,7 +76,10 @@ class sense_amp_array(design.design):
def place_sense_amp_array(self):
amp_spacing = self.amp.width * self.words_per_row
if self.bitcell.width > self.amp.width:
amp_spacing = self.bitcell.width * self.words_per_row
else:
amp_spacing = self.amp.width * self.words_per_row
for i in range(0,self.word_size):
amp_position = vector(amp_spacing * i, 0)
self.local_insts[i].place(amp_position)

View File

@ -58,6 +58,12 @@ class wordline_driver(design.design):
self.nand2 = pnand2()
self.add_mod(self.nand2)
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.add_mod(self.bitcell)
def route_vdd_gnd(self):
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
@ -125,16 +131,20 @@ class wordline_driver(design.design):
nand2_xoffset = inv1_xoffset + self.inv.width
inv2_xoffset = nand2_xoffset + self.nand2.width
self.width = inv2_xoffset + self.inv.width
self.height = self.inv.height * self.rows
self.width = inv2_xoffset + self.inv.height
if self.bitcell.height > self.inv.height:
self.height = self.bitcell.height * self.rows
driver_height = self.bitcell.height
else:
self.height = self.inv.height * self.rows
driver_height = self.inv.height
for row in range(self.rows):
if (row % 2):
y_offset = self.inv.height*(row + 1)
y_offset = driver_height*(row + 1)
inst_mirror = "MX"
else:
y_offset = self.inv.height*row
y_offset = driver_height*row
inst_mirror = "R0"
inv1_offset = [inv1_xoffset, y_offset]

View File

@ -30,7 +30,12 @@ class write_driver_array(design.design):
self.create_write_array()
def create_layout(self):
self.width = self.columns * self.driver.width
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()
@ -53,6 +58,11 @@ class write_driver_array(design.design):
self.mod_write_driver = getattr(c, OPTS.write_driver)
self.driver = self.mod_write_driver("write_driver")
self.add_mod(self.driver)
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.add_mod(self.bitcell)
def create_write_array(self):
self.driver_insts = {}
@ -69,9 +79,14 @@ class write_driver_array(design.design):
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 * self.driver.width,0)
base = vector(i * driver_spacing,0)
self.driver_insts[index].place(base)

View File

@ -99,18 +99,18 @@ class sram_1bank(sram_base):
for i in range(self.word_size):
dout_name = "dout0[{}]".format(i)
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT[{}]".format(i))
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT0[{}]".format(i))
# Lower address bits
for i in range(self.col_addr_size):
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i))
# Upper address bits
for i in range(self.row_addr_size):
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i+self.col_addr_size))
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i+self.col_addr_size))
for i in range(self.word_size):
din_name = "din[{}]".format(i)
self.copy_layout_pin(self.data_dff_inst, din_name, din_name.upper())
self.copy_layout_pin(self.data_dff_inst, din_name, "DIN0[{}]".format(i))
def route(self):
""" Route a single bank SRAM """

View File

@ -24,11 +24,14 @@ class sram_base(design):
def add_pins(self):
""" Add pins for entire SRAM. """
for i in range(self.word_size):
self.add_pin("DIN[{0}]".format(i),"INPUT")
for i in range(self.addr_size):
self.add_pin("ADDR[{0}]".format(i),"INPUT")
for port in range(self.total_write):
for bit in range(self.word_size):
self.add_pin("DIN{0}[{1}]".format(port,bit),"INPUT")
for port in range(self.total_ports):
for bit in range(self.addr_size):
self.add_pin("ADDR{0}[{1}]".format(port,bit),"INPUT")
# These are used to create the physical pins too
self.control_logic_inputs=self.control_logic.get_inputs()
@ -36,8 +39,9 @@ class sram_base(design):
self.add_pin_list(self.control_logic_inputs,"INPUT")
for i in range(self.word_size):
self.add_pin("DOUT[{0}]".format(i),"OUTPUT")
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("vdd","POWER")
self.add_pin("gnd","GROUND")
@ -217,16 +221,16 @@ class sram_base(design):
# Create the address and control flops (but not the clk)
from dff_array import dff_array
self.row_addr_dff = dff_array(name="row_addr_dff", rows=self.row_addr_size, columns=1)
self.row_addr_dff = dff_array(name="row_addr_dff", rows=self.row_addr_size*self.total_ports, columns=1)
self.add_mod(self.row_addr_dff)
if self.col_addr_size > 0:
self.col_addr_dff = dff_array(name="col_addr_dff", rows=1, columns=self.col_addr_size)
self.col_addr_dff = dff_array(name="col_addr_dff", rows=1, columns=self.col_addr_size*self.total_ports)
self.add_mod(self.col_addr_dff)
else:
self.col_addr_dff = None
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size)
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size*self.total_ports)
self.add_mod(self.data_dff)
# Create the bank module (up to four are instantiated)
@ -247,20 +251,28 @@ class sram_base(design):
def create_bank(self,bank_num):
""" Create a bank """
""" Create a bank """
self.bank_insts.append(self.add_inst(name="bank{0}".format(bank_num),
mod=self.bank))
temp = []
for i in range(self.word_size):
temp.append("DOUT[{0}]".format(i))
for i in range(self.word_size):
temp.append("BANK_DIN[{0}]".format(i))
for i in range(self.bank_addr_size):
temp.append("A[{0}]".format(i))
for port in range(self.total_read):
for bit in range(self.word_size):
temp.append("DOUT{0}[{1}]".format(port,bit))
for port in range(self.total_write):
for bit in range(self.word_size):
temp.append("BANK_DIN{0}[{1}]".format(port,bit))
for port in range(self.total_ports):
for bit in range(self.bank_addr_size):
temp.append("A{0}[{1}]".format(port,bit))
if(self.num_banks > 1):
temp.append("bank_sel[{0}]".format(bank_num))
temp.extend(["s_en0", "w_en0", "clk_buf_bar","clk_buf" , "vdd", "gnd"])
for port in range(self.total_ports):
temp.append("bank_sel{0}[{1}]".format(port,bank_num))
for port in range(self.total_read):
temp.append("s_en{0}".format(port))
for port in range(self.total_write):
temp.append("w_en{0}".format(port))
temp.extend(["clk_buf_bar","clk_buf" , "vdd", "gnd"])
self.connect_inst(temp)
return self.bank_insts[-1]
@ -305,9 +317,10 @@ class sram_base(design):
# inputs, outputs/output/bar
inputs = []
outputs = []
for i in range(self.row_addr_size):
inputs.append("ADDR[{}]".format(i+self.col_addr_size))
outputs.append("A[{}]".format(i+self.col_addr_size))
for k 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))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst
@ -320,9 +333,10 @@ class sram_base(design):
# inputs, outputs/output/bar
inputs = []
outputs = []
for i in range(self.col_addr_size):
inputs.append("ADDR[{}]".format(i))
outputs.append("A[{}]".format(i))
for k 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))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst
@ -335,9 +349,10 @@ class sram_base(design):
# inputs, outputs/output/bar
inputs = []
outputs = []
for i in range(self.word_size):
inputs.append("DIN[{}]".format(i))
outputs.append("BANK_DIN[{}]".format(i))
for k 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))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst

11
compiler/tests/08_wordline_driver_test.py Executable file → Normal file
View File

@ -20,10 +20,21 @@ class wordline_driver_test(openram_test):
import wordline_driver
import tech
# check wordline driver array in single port
debug.info(2, "Checking driver")
tx = wordline_driver.wordline_driver(rows=8)
self.local_check(tx)
# check wordline driver array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
debug.info(2, "Checking driver (multi-port case)")
tx = wordline_driver.wordline_driver(rows=8)
self.local_check(tx)
globals.end_openram()
# instantiate a copy of the class to actually run the test

16
compiler/tests/09_sense_amp_array_test.py Executable file → Normal file
View File

@ -17,7 +17,7 @@ class sense_amp_test(openram_test):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
import sense_amp_array
# check sense amp array in single port
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2")
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)
self.local_check(a)
@ -26,6 +26,20 @@ class sense_amp_test(openram_test):
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=4)
self.local_check(a)
# check sense amp array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)
self.local_check(a)
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4 (multi-port case)")
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=4)
self.local_check(a)
globals.end_openram()
# instantiate a copy of the class to actually run the test

15
compiler/tests/10_write_driver_array_test.py Executable file → Normal file
View File

@ -17,6 +17,7 @@ class write_driver_test(openram_test):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
import write_driver_array
# check write driver array in single port
debug.info(2, "Testing write_driver_array for columns=8, word_size=8")
a = write_driver_array.write_driver_array(columns=8, word_size=8)
self.local_check(a)
@ -25,6 +26,20 @@ class write_driver_test(openram_test):
a = write_driver_array.write_driver_array(columns=16, word_size=8)
self.local_check(a)
# check write driver array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)")
a = write_driver_array.write_driver_array(columns=8, word_size=8)
self.local_check(a)
debug.info(2, "Testing write_driver_array for columns=16, word_size=8 (multi-port case)")
a = write_driver_array.write_driver_array(columns=16, word_size=8)
self.local_check(a)
globals.end_openram()
# instantiate a copy of the class to actually run the test

23
compiler/tests/19_psingle_bank_test.py Executable file → Normal file
View File

@ -20,21 +20,32 @@ class psingle_bank_test(openram_test):
import verify
from bank import bank
OPTS.bitcell = "pbitcell"
from sram_config import sram_config
# testing all port configurations (with no column mux) to verify layout between bitcell array and peripheral circuitry
OPTS.bitcell = "pbitcell"
# testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent)
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
debug.info(1, "No column mux")
a = bank(c, name="bank1_1rw_0w_0r_single")
self.local_check(a)
"""
# multiport can't generate layout yet on the bank level
OPTS.netlist_only = True
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
debug.info(1, "No column mux")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
"""
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 2
OPTS.num_r_ports = c.num_r_ports = 2