From 125112b562471418f54555560397f1e020a8186b Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 4 Jul 2019 10:34:14 -0700 Subject: [PATCH] Added wmask flip flop. Need work on placement still. --- compiler/base/hierarchy_spice.py | 3 ++- compiler/base/verilog.py | 33 +++++++++++++++++++++++++++---- compiler/modules/control_logic.py | 13 +++++++----- compiler/sram/sram_1bank.py | 27 ++++++++++++++++++++++--- compiler/sram/sram_base.py | 29 +++++++++++++++++++++++++-- 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index f4fc9d8a..496d7534 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -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) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 1f2ebd7b..435b6912 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -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): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index fa269e26..09528509 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -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: diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 7025d228..6e771feb 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -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. """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 934869d8..23d0a8bd 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -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 """