mirror of https://github.com/VLSIDA/OpenRAM.git
Added wmask flip flop. Need work on placement still.
This commit is contained in:
parent
474ac67af5
commit
125112b562
|
|
@ -11,6 +11,7 @@ import os
|
|||
import math
|
||||
import tech
|
||||
|
||||
|
||||
class spice():
|
||||
"""
|
||||
This provides a set of useful generic types for hierarchy
|
||||
|
|
@ -126,13 +127,13 @@ class spice():
|
|||
"""Adds a subckt/submodule to the subckt hierarchy"""
|
||||
self.mods.append(mod)
|
||||
|
||||
|
||||
def connect_inst(self, args, check=True):
|
||||
"""Connects the pins of the last instance added
|
||||
It is preferred to use the function with the check to find if
|
||||
there is a problem. The check option can be set to false
|
||||
where we dynamically generate groups of connections after a
|
||||
group of modules are generated."""
|
||||
|
||||
if (check and (len(self.insts[-1].mod.pins) != len(args))):
|
||||
from pprint import pformat
|
||||
modpins_string=pformat(self.insts[-1].mod.pins)
|
||||
|
|
|
|||
|
|
@ -18,10 +18,16 @@ class verilog:
|
|||
def verilog_write(self,verilog_name):
|
||||
""" Write a behavioral Verilog model. """
|
||||
self.vf = open(verilog_name, "w")
|
||||
# Determine if optional write mask is used
|
||||
self.wmask_enabled = False
|
||||
if self.word_size != self.write_size:
|
||||
self.wmask_enabled = True
|
||||
|
||||
self.vf.write("// OpenRAM SRAM model\n")
|
||||
self.vf.write("// Words: {0}\n".format(self.num_words))
|
||||
self.vf.write("// Word size: {0}\n\n".format(self.word_size))
|
||||
self.vf.write("// Word size: {0}\n".format(self.word_size))
|
||||
if self.wmask_enabled:
|
||||
self.vf.write("// Write size: {0}\n\n".format(self.write_size))
|
||||
|
||||
self.vf.write("module {0}(\n".format(self.name))
|
||||
for port in self.all_ports:
|
||||
|
|
@ -32,9 +38,15 @@ class verilog:
|
|||
elif port in self.write_ports:
|
||||
self.vf.write("// Port {0}: W\n".format(port))
|
||||
if port in self.readwrite_ports:
|
||||
self.vf.write(" clk{0},csb{0},web{0},ADDR{0},DIN{0},DOUT{0}".format(port))
|
||||
self.vf.write(" clk{0},csb{0},web{0},".format(port))
|
||||
if self.wmask_enabled:
|
||||
self.vf.write("wmask{},".format(port))
|
||||
self.vf.write("ADDR{0},DIN{0},DOUT{0}".format(port))
|
||||
elif port in self.write_ports:
|
||||
self.vf.write(" clk{0},csb{0},ADDR{0},DIN{0}".format(port))
|
||||
self.vf.write(" clk{0},csb{0},".format(port))
|
||||
if self.wmask_enabled:
|
||||
self.vf.write("wmask{},".format(port))
|
||||
self.vf.write("ADDR{0},DIN{0}".format(port))
|
||||
elif port in self.read_ports:
|
||||
self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port))
|
||||
# Continue for every port on a new line
|
||||
|
|
@ -44,6 +56,9 @@ class verilog:
|
|||
|
||||
self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size))
|
||||
self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size))
|
||||
if self.wmask_enabled:
|
||||
self.num_wmask = int(self.word_size/self.write_size)
|
||||
self.vf.write(" parameter NUM_WMASK = {0} ;\n".format(self.num_wmask))
|
||||
self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n")
|
||||
self.vf.write(" // FIXME: This delay is arbitrary.\n")
|
||||
self.vf.write(" parameter DELAY = 3 ;\n")
|
||||
|
|
@ -131,6 +146,8 @@ class verilog:
|
|||
self.vf.write(" input csb{0}; // active low chip select\n".format(port))
|
||||
if port in self.readwrite_ports:
|
||||
self.vf.write(" input web{0}; // active low write control\n".format(port))
|
||||
if (self.wmask_enabled):
|
||||
self.vf.write(" input [NUM_WMASK-1:0] wmask{0}; // write mask\n".format(port))
|
||||
self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port))
|
||||
if port in self.write_ports:
|
||||
self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port))
|
||||
|
|
@ -151,7 +168,15 @@ class verilog:
|
|||
self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port))
|
||||
else:
|
||||
self.vf.write(" if (!csb{0}_reg)\n".format(port))
|
||||
self.vf.write(" mem[ADDR{0}_reg] = DIN{0}_reg;\n".format(port))
|
||||
|
||||
if self.wmask_enabled:
|
||||
for mask in range(0,self.num_wmask):
|
||||
lower = mask * self.write_size
|
||||
upper = lower + self.write_size-1
|
||||
self.vf.write(" if(wmask[{}])\n".format(mask))
|
||||
self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower))
|
||||
else:
|
||||
self.vf.write(" mem[ADDR{0}_reg] = DIN_reg{0};\n".format(port))
|
||||
self.vf.write(" end\n")
|
||||
|
||||
def add_read_block(self, port):
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ class control_logic(design.design):
|
|||
def add_pins(self):
|
||||
""" Add the pins to the control logic module. """
|
||||
for pin in self.input_list + ["clk"]:
|
||||
print(pin)
|
||||
self.add_pin(pin,"INPUT")
|
||||
for pin in self.output_list:
|
||||
self.add_pin(pin,"OUTPUT")
|
||||
|
|
@ -317,12 +316,14 @@ class control_logic(design.design):
|
|||
else:
|
||||
self.input_list = ["csb"]
|
||||
|
||||
if self.word_size != self.write_size:
|
||||
print(self.word_size, self.write_size)
|
||||
self.input_list = ["wmask"]
|
||||
# if self.word_size != self.write_size:
|
||||
# self.input_list = ["wmask"]
|
||||
|
||||
if self.port_type == "rw":
|
||||
self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"]
|
||||
# if self.word_size != self.write_size:
|
||||
# self.dff_output_list.append("wm_bar")
|
||||
# self.dff_output_list.append("wm")
|
||||
else:
|
||||
self.dff_output_list = ["cs_bar", "cs"]
|
||||
|
||||
|
|
@ -758,7 +759,9 @@ class control_logic(design.design):
|
|||
|
||||
def route_dffs(self):
|
||||
if self.port_type == "rw":
|
||||
dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"])
|
||||
#print("hi")
|
||||
#if (self.word_size == self.write_size):
|
||||
dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"])
|
||||
elif self.port_type == "r":
|
||||
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ class sram_1bank(sram_base):
|
|||
self.col_addr_dff_insts = self.create_col_addr_dff()
|
||||
|
||||
self.data_dff_insts = self.create_data_dff()
|
||||
|
||||
if (self.write_size != self.word_size):
|
||||
self.wmask_dff_insts = self.create_wmask_dff()
|
||||
|
||||
def place_instances(self):
|
||||
"""
|
||||
|
|
@ -64,6 +67,7 @@ class sram_1bank(sram_base):
|
|||
row_addr_pos = [None]*len(self.all_ports)
|
||||
col_addr_pos = [None]*len(self.all_ports)
|
||||
data_pos = [None]*len(self.all_ports)
|
||||
wmask_pos = [None]*len(self.all_ports)
|
||||
|
||||
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
|
||||
# The M1 pitch is for supply rail spacings
|
||||
|
|
@ -101,6 +105,13 @@ class sram_1bank(sram_base):
|
|||
-max_gap_size - self.data_dff_insts[port].height)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
# Add the write mask flops to the left of the din flops.
|
||||
if (self.write_size != self.word_size):
|
||||
if port in self.write_ports:
|
||||
wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + max_gap_size + self.data_dff_insts[port].height)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
|
||||
|
||||
|
||||
if len(self.all_ports)>1:
|
||||
# Port 1
|
||||
|
|
@ -134,7 +145,14 @@ class sram_1bank(sram_base):
|
|||
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + max_gap_size + self.data_dff_insts[port].height)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
|
||||
# Add the write mask flops to the left of the din flops.
|
||||
if (self.write_size != self.word_size):
|
||||
if port in self.write_ports:
|
||||
wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + max_gap_size + self.data_dff_insts[port].height)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
"""
|
||||
|
|
@ -311,10 +329,13 @@ class sram_1bank(sram_base):
|
|||
offset=pin.center())
|
||||
|
||||
def graph_exclude_data_dff(self):
|
||||
"""Removes data dff from search graph. """
|
||||
#Data dffs are only for writing so are not useful for evaluating read delay.
|
||||
"""Removes data dff and wmask dff (if applicable) from search graph. """
|
||||
#Data dffs and wmask dffs are only for writing so are not useful for evaluating read delay.
|
||||
for inst in self.data_dff_insts:
|
||||
self.graph_inst_exclude.add(inst)
|
||||
if (self.write_size != self.word_size):
|
||||
for inst in self.wmask_dff_insts:
|
||||
self.graph_inst_exclude.add(inst)
|
||||
|
||||
def graph_exclude_addr_dff(self):
|
||||
"""Removes data dff from search graph. """
|
||||
|
|
|
|||
|
|
@ -276,6 +276,9 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size)
|
||||
self.add_mod(self.data_dff)
|
||||
|
||||
self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=int(self.word_size/self.write_size))
|
||||
self.add_mod(self.wmask_dff)
|
||||
|
||||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
|
|
@ -319,8 +322,7 @@ class sram_base(design, verilog, lef):
|
|||
self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows,
|
||||
words_per_row=self.words_per_row,
|
||||
word_size=self.word_size,
|
||||
write_size=self.write_size,
|
||||
sram=self,
|
||||
sram=self,
|
||||
port_type="r")
|
||||
self.add_mod(self.control_logic_r)
|
||||
|
||||
|
|
@ -447,6 +449,29 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
return insts
|
||||
|
||||
def create_wmask_dff(self):
|
||||
""" Add and place all wmask flops """
|
||||
num_wmask = int(self.word_size/self.write_size)
|
||||
insts = []
|
||||
for port in self.all_ports:
|
||||
if port in self.write_ports:
|
||||
insts.append(self.add_inst(name="wmask_dff{}".format(port),
|
||||
mod=self.wmask_dff))
|
||||
else:
|
||||
insts.append(None)
|
||||
continue
|
||||
|
||||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for bit in range(num_wmask):
|
||||
inputs.append("wmask{}[{}]".format(port, bit))
|
||||
outputs.append("BANK_WMASK{}[{}]".format(port, bit))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"])
|
||||
|
||||
return insts
|
||||
|
||||
|
||||
def create_control_logic(self):
|
||||
""" Add control logic instances """
|
||||
|
|
|
|||
Loading…
Reference in New Issue