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 math
import tech import tech
class spice(): class spice():
""" """
This provides a set of useful generic types for hierarchy This provides a set of useful generic types for hierarchy
@ -126,13 +127,13 @@ class spice():
"""Adds a subckt/submodule to the subckt hierarchy""" """Adds a subckt/submodule to the subckt hierarchy"""
self.mods.append(mod) self.mods.append(mod)
def connect_inst(self, args, check=True): def connect_inst(self, args, check=True):
"""Connects the pins of the last instance added """Connects the pins of the last instance added
It is preferred to use the function with the check to find if 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 there is a problem. The check option can be set to false
where we dynamically generate groups of connections after a where we dynamically generate groups of connections after a
group of modules are generated.""" group of modules are generated."""
if (check and (len(self.insts[-1].mod.pins) != len(args))): if (check and (len(self.insts[-1].mod.pins) != len(args))):
from pprint import pformat from pprint import pformat
modpins_string=pformat(self.insts[-1].mod.pins) modpins_string=pformat(self.insts[-1].mod.pins)

View File

@ -18,10 +18,16 @@ class verilog:
def verilog_write(self,verilog_name): def verilog_write(self,verilog_name):
""" Write a behavioral Verilog model. """ """ Write a behavioral Verilog model. """
self.vf = open(verilog_name, "w") 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("// OpenRAM SRAM model\n")
self.vf.write("// Words: {0}\n".format(self.num_words)) 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)) self.vf.write("module {0}(\n".format(self.name))
for port in self.all_ports: for port in self.all_ports:
@ -32,9 +38,15 @@ class verilog:
elif port in self.write_ports: elif port in self.write_ports:
self.vf.write("// Port {0}: W\n".format(port)) self.vf.write("// Port {0}: W\n".format(port))
if port in self.readwrite_ports: 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: 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: elif port in self.read_ports:
self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port)) self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port))
# Continue for every port on a new line # 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 DATA_WIDTH = {0} ;\n".format(self.word_size))
self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_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(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n")
self.vf.write(" // FIXME: This delay is arbitrary.\n") self.vf.write(" // FIXME: This delay is arbitrary.\n")
self.vf.write(" parameter DELAY = 3 ;\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)) self.vf.write(" input csb{0}; // active low chip select\n".format(port))
if port in self.readwrite_ports: if port in self.readwrite_ports:
self.vf.write(" input web{0}; // active low write control\n".format(port)) 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)) self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port))
if port in self.write_ports: if port in self.write_ports:
self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port)) 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)) self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port))
else: else:
self.vf.write(" if (!csb{0}_reg)\n".format(port)) 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") self.vf.write(" end\n")
def add_read_block(self, port): def add_read_block(self, port):

View File

@ -75,7 +75,6 @@ class control_logic(design.design):
def add_pins(self): def add_pins(self):
""" Add the pins to the control logic module. """ """ Add the pins to the control logic module. """
for pin in self.input_list + ["clk"]: for pin in self.input_list + ["clk"]:
print(pin)
self.add_pin(pin,"INPUT") self.add_pin(pin,"INPUT")
for pin in self.output_list: for pin in self.output_list:
self.add_pin(pin,"OUTPUT") self.add_pin(pin,"OUTPUT")
@ -317,12 +316,14 @@ class control_logic(design.design):
else: else:
self.input_list = ["csb"] self.input_list = ["csb"]
if self.word_size != self.write_size: # if self.word_size != self.write_size:
print(self.word_size, self.write_size) # self.input_list = ["wmask"]
self.input_list = ["wmask"]
if self.port_type == "rw": if self.port_type == "rw":
self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] 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: else:
self.dff_output_list = ["cs_bar", "cs"] self.dff_output_list = ["cs_bar", "cs"]
@ -758,7 +759,9 @@ class control_logic(design.design):
def route_dffs(self): def route_dffs(self):
if self.port_type == "rw": 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": elif self.port_type == "r":
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"]) dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
else: else:

View File

@ -45,6 +45,9 @@ class sram_1bank(sram_base):
self.col_addr_dff_insts = self.create_col_addr_dff() self.col_addr_dff_insts = self.create_col_addr_dff()
self.data_dff_insts = self.create_data_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): def place_instances(self):
""" """
@ -64,6 +67,7 @@ class sram_1bank(sram_base):
row_addr_pos = [None]*len(self.all_ports) row_addr_pos = [None]*len(self.all_ports)
col_addr_pos = [None]*len(self.all_ports) col_addr_pos = [None]*len(self.all_ports)
data_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 # 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 # 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) -max_gap_size - self.data_dff_insts[port].height)
self.data_dff_insts[port].place(data_pos[port]) 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: if len(self.all_ports)>1:
# Port 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, 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.bank.height + max_gap_size + self.data_dff_insts[port].height)
self.data_dff_insts[port].place(data_pos[port], mirror="MX") 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): def add_layout_pins(self):
""" """
@ -311,10 +329,13 @@ class sram_1bank(sram_base):
offset=pin.center()) offset=pin.center())
def graph_exclude_data_dff(self): def graph_exclude_data_dff(self):
"""Removes data dff from search graph. """ """Removes data dff and wmask dff (if applicable) from search graph. """
#Data dffs are only for writing so are not useful for evaluating read delay. #Data dffs and wmask dffs are only for writing so are not useful for evaluating read delay.
for inst in self.data_dff_insts: for inst in self.data_dff_insts:
self.graph_inst_exclude.add(inst) 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): def graph_exclude_addr_dff(self):
"""Removes data dff from search graph. """ """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.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size)
self.add_mod(self.data_dff) 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) # Create the bank module (up to four are instantiated)
from bank import bank 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, 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,
write_size=self.write_size, sram=self,
sram=self,
port_type="r") port_type="r")
self.add_mod(self.control_logic_r) self.add_mod(self.control_logic_r)
@ -447,6 +449,29 @@ class sram_base(design, verilog, lef):
return insts 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): def create_control_logic(self):
""" Add control logic instances """ """ Add control logic instances """