From 289d3b3988f0a47a11390cebb4753333c5d32714 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 27 Sep 2019 14:18:49 -0700 Subject: [PATCH] Feedthru port edits. Comment about write driver size for write through to work, but disable write through in functional simulation. Provide warning in Verilog about write throughs. --- compiler/base/verilog.py | 30 ++++++++++++++++++- compiler/characterizer/functional.py | 18 +++++++----- compiler/modules/control_logic.py | 44 ++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index ff13c4f4..04344738 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -122,6 +122,9 @@ class verilog: if self.write_size: self.vf.write(" wmask{0}_reg = wmask{0};\n".format(port)) self.vf.write(" addr{0}_reg = addr{0};\n".format(port)) + if port in self.read_ports: + self.add_write_read_checks(port) + if port in self.write_ports: self.vf.write(" din{0}_reg = din{0};\n".format(port)) if port in self.read_ports: @@ -211,4 +214,29 @@ class verilog: self.vf.write(" if (!csb{0}_reg)\n".format(port)) self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port)) self.vf.write(" end\n") - + + def add_address_check(self, wport, rport): + """ Output a warning if the two addresses match """ + # If the rport is actually reading... and addresses match. + if rport in self.readwrite_ports: + rport_control = "!csb{0} && web{0}".format(rport) + else: + rport_control = "!csb{0}".format(rport) + if wport in self.readwrite_ports: + wport_control = "!csb{0} && !web{0}".format(wport) + else: + wport_control = "!csb{0}".format(wport) + + self.vf.write(" if ({1} && {3} && (addr{0} == addr{2}))\n".format(wport,wport_control,rport,rport_control)) + self.vf.write(" $display($time,\" WARNING: Writing and reading addr{0}=%b and addr{1}=%b simultaneously!\",addr{0},addr{1});\n".format(wport,rport)) + + def add_write_read_checks(self, rport): + """ + Add a warning if we read from an address that we are currently writing. + Can be fixed if we appropriately size the write drivers to do this . + """ + for wport in self.write_ports: + if wport == rport: + continue + else: + self.add_address_check(wport,rport) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 50d55d59..6d827aa3 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -180,14 +180,16 @@ class functional(simulation): w_addrs.append(addr) else: (addr,word) = random.choice(list(self.stored_words.items())) - ## cannot read from an address that is currently being written to - # Yes, you can!! - #if addr in w_addrs: - # self.add_noop_one_port(port) - #else: - comment = self.gen_cycle_comment("read", word, addr, "0"*self.num_wmasks, port, self.t_current) - self.add_read_one_port(comment, addr, port) - self.add_read_check(word, port) + # The write driver is not sized sufficiently to drive through the two + # bitcell access transistors to the read port. So, for now, we do not allow + # a simultaneous write and read to the same address on different ports. This + # could be even more difficult with multiple simultaneous read ports. + if addr in w_addrs: + self.add_noop_one_port(port) + else: + comment = self.gen_cycle_comment("read", word, addr, "0"*self.num_wmasks, port, self.t_current) + self.add_read_one_port(comment, addr, port) + self.add_read_check(word, port) self.cycle_times.append(self.t_current) self.t_current += self.period diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 79db4d61..3256c9ac 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -125,7 +125,7 @@ class control_logic(design.design): self.add_mod(self.wl_en_driver) # w_en drives every write driver - self.wen_and = factory.create(module_type="pand2", + self.wen_and = factory.create(module_type="pand3", size=self.word_size+8, height=dff_height) self.add_mod(self.wen_and) @@ -344,11 +344,11 @@ class control_logic(design.design): # list of output control signals (for making a vertical bus) if self.port_type == "rw": - self.internal_bus_list = ["rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "we_bar", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "we_bar", "cs"] elif self.port_type == "r": - self.internal_bus_list = ["rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"] else: - self.internal_bus_list = ["rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"] # leave space for the bus plus one extra space self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch @@ -382,6 +382,7 @@ class control_logic(design.design): self.create_gated_clk_buf_row() self.create_wlen_row() if (self.port_type == "rw") or (self.port_type == "w"): + self.create_rbl_delay_row() self.create_wen_row() if (self.port_type == "rw") or (self.port_type == "r"): self.create_sen_row() @@ -419,6 +420,9 @@ class control_logic(design.design): row += 1 self.place_pen_row(row) row += 1 + if (self.port_type == "rw") or (self.port_type == "w"): + self.place_rbl_delay_row(row) + row += 1 if (self.port_type == "rw") or (self.port_type == "r"): self.place_sen_row(row) row += 1 @@ -443,6 +447,7 @@ class control_logic(design.design): self.route_dffs() self.route_wlen() if (self.port_type == "rw") or (self.port_type == "w"): + self.route_rbl_delay() self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): self.route_sen() @@ -671,7 +676,34 @@ class control_logic(design.design): self.connect_output(self.s_en_gate_inst, "Z", "s_en") + def create_rbl_delay_row(self): + + self.rbl_bl_delay_inv_inst = self.add_inst(name="rbl_bl_delay_inv", + mod=self.inv) + self.connect_inst(["rbl_bl_delay", "rbl_bl_delay_bar", "vdd", "gnd"]) + + def place_rbl_delay_row(self,row): + x_offset = self.control_x_offset + + x_offset = self.place_util(self.rbl_bl_delay_inv_inst, x_offset, row) + self.row_end_inst.append(self.rbl_bl_delay_inv_inst) + + def route_rbl_delay(self): + # Connect from delay line + # Connect to rail + + rbl_map = zip(["Z"], ["rbl_bl_delay_bar"]) + self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + # The pin is on M1, so we need another via as well + self.add_via_center(layers=("metal1","via1","metal2"), + offset=self.rbl_bl_delay_inv_inst.get_pin("Z").center()) + + + rbl_map = zip(["A"], ["rbl_bl_delay"]) + self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets) + + def create_wen_row(self): # input: we (or cs) output: w_en @@ -685,7 +717,7 @@ class control_logic(design.design): self.w_en_gate_inst = self.add_inst(name="w_en_and", mod=self.wen_and) # Only drive the writes in the second half of the clock cycle during a write operation. - self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) + self.connect_inst([input_name, "rbl_bl_delay_bar", "gated_clk_bar", "w_en", "vdd", "gnd"]) def place_wen_row(self,row): @@ -702,7 +734,7 @@ class control_logic(design.design): # No we for write-only reports, so use cs input_name = "cs" - wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) + wen_map = zip(["A", "B", "C"], [input_name, "rbl_bl_delay_bar", "gated_clk_bar"]) self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) self.connect_output(self.w_en_gate_inst, "Z", "w_en")