Added wmask flip flop. Need work on placement still.

This commit is contained in:
jsowash 2019-07-04 10:34:14 -07:00
parent 474ac67af5
commit 125112b562
5 changed files with 90 additions and 15 deletions

View File

@ -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)

View File

@ -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):

View File

@ -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:

View File

@ -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. """

View File

@ -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 """