From 3fa217e62755d11246602ed28a5ebd8db478e14f Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Sun, 16 Jul 2023 15:22:05 -0400 Subject: [PATCH 1/2] True single port memories --- primitives/memories.futil | 30 ++++---- primitives/memories.sv | 77 ++++++++------------- tests/correctness/seq-mem-d4-add.futil | 11 +-- tests/correctness/seq-mem-dot-product.futil | 13 ++-- 4 files changed, 58 insertions(+), 73 deletions(-) diff --git a/primitives/memories.futil b/primitives/memories.futil index f83353d86..223b9fd52 100644 --- a/primitives/memories.futil +++ b/primitives/memories.futil @@ -4,14 +4,13 @@ extern "memories.sv" { @reset reset: 1, @data addr0: IDX_SIZE, // Write ports - @write_together(1) @static(1) @go(1) write_en: 1, + @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, // Read ports - @static(1) @go(2) read_en: 1 + @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, - @done(1) write_done: 1, - @done(2) read_done: 1 + @done(1) done: 1 ); primitive seq_mem_d2[WIDTH, D0_SIZE, D1_SIZE, D0_IDX_SIZE, D1_IDX_SIZE]( @@ -20,14 +19,13 @@ extern "memories.sv" { @data addr0: D0_IDX_SIZE, @data addr1: D1_IDX_SIZE, // Write ports - @write_together(1) @static(1) @go(1) write_en: 1, + @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, // Read ports - @static(1) @go(2) read_en: 1 + @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, - @done(1) write_done: 1, - @done(2) read_done: 1 + @done(1) done: 1, ); primitive seq_mem_d3[WIDTH, D0_SIZE, D1_SIZE, D2_SIZE, D0_IDX_SIZE, D1_IDX_SIZE, D2_IDX_SIZE]( @@ -37,14 +35,13 @@ extern "memories.sv" { @data addr1: D1_IDX_SIZE, @data addr2: D2_IDX_SIZE, // Write ports - @write_together(1) @static(1) @go(1) write_en: 1, + @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, // Read ports - @static(1) @go(2) read_en: 1 + @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, - @done(1) write_done: 1, - @done(2) read_done: 1 + @done(1) done: 1, ); primitive seq_mem_d4[WIDTH, D0_SIZE, D1_SIZE, D2_SIZE, D3_SIZE, D0_IDX_SIZE, D1_IDX_SIZE, D2_IDX_SIZE, D3_IDX_SIZE]( @@ -55,13 +52,12 @@ extern "memories.sv" { @data addr2: D2_IDX_SIZE, @data addr3: D3_IDX_SIZE, // Write ports - @write_together(1) @static(1) @go(1) write_en: 1, + @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, // Read ports - @static(1) @go(2) read_en: 1 + @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, - @done(1) write_done: 1, - @done(2) read_done: 1 + @done(1) done: 1, ); -} \ No newline at end of file +} diff --git a/primitives/memories.sv b/primitives/memories.sv index e90a87907..43acc6869 100644 --- a/primitives/memories.sv +++ b/primitives/memories.sv @@ -14,19 +14,18 @@ module seq_mem_d1 #( input wire logic clk, input wire logic reset, input wire logic [IDX_SIZE-1:0] addr0, + input wire logic content_en, + output logic done, // Read signal - input wire logic read_en, output logic [ WIDTH-1:0] read_data, - output logic read_done, // Write signals input wire logic [ WIDTH-1:0] write_data, - input wire logic write_en, - output logic write_done + input wire logic write_en ); // Internal memory - (* ram_style = "ultra" *) logic [WIDTH-1:0] mem[SIZE-1:0]; + logic [WIDTH-1:0] mem[SIZE-1:0]; // Register for the read output logic [WIDTH-1:0] read_out; @@ -36,10 +35,10 @@ module seq_mem_d1 #( always_ff @(posedge clk) begin if (reset) begin read_out <= '0; - end else if (read_en) begin + end else if (content_en && !write_en) begin /* verilator lint_off WIDTH */ read_out <= mem[addr0]; - end else if (write_en) begin + end else if (content_en && write_en) begin // Explicitly clobber the read output when a write is performed read_out <= 'x; end else begin @@ -47,38 +46,27 @@ module seq_mem_d1 #( end end - // Propagate the read_done signal + // Propagate the done signal always_ff @(posedge clk) begin if (reset) begin - read_done <= '0; - end else if (read_en) begin - read_done <= '1; + done <= '0; + end else if (content_en) begin + done <= '1; end else begin - read_done <= '0; + done <= '0; end end // Write value to the memory always_ff @(posedge clk) begin - if (!reset && write_en) + if (!reset && content_en && write_en) mem[addr0] <= write_data; end - // Propagate the write_done signal - always_ff @(posedge clk) begin - if (reset) begin - write_done <= '0; - end else if (write_en) begin - write_done <= 1'd1; - end else begin - write_done <= '0; - end - end - // Check for out of bounds access `ifdef VERILATOR always_comb begin - if (read_en) + if (content_en && !write_en) if (addr0 >= SIZE) $error( "std_mem_d1: Out of bounds access\n", @@ -86,10 +74,6 @@ module seq_mem_d1 #( "SIZE: %0d", SIZE ); end - always_comb begin - if (read_en && write_en) - $error("Simultaneous read and write attempted\n"); - end `endif endmodule @@ -105,24 +89,23 @@ module seq_mem_d2 #( input wire logic reset, input wire logic [D0_IDX_SIZE-1:0] addr0, input wire logic [D1_IDX_SIZE-1:0] addr1, + input wire logic content_en, + output logic done, // Read signal - input wire logic read_en, output logic [WIDTH-1:0] read_data, - output logic read_done, // Write signals input wire logic write_en, - input wire logic [ WIDTH-1:0] write_data, - output logic write_done + input wire logic [ WIDTH-1:0] write_data ); wire [D0_IDX_SIZE+D1_IDX_SIZE-1:0] addr; assign addr = addr0 * D1_SIZE + addr1; seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE)) mem (.clk(clk), .reset(reset), .addr0(addr), - .read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en), - .write_done(write_done)); + .content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en), + .done(done)); endmodule module seq_mem_d3 #( @@ -140,24 +123,23 @@ module seq_mem_d3 #( input wire logic [D0_IDX_SIZE-1:0] addr0, input wire logic [D1_IDX_SIZE-1:0] addr1, input wire logic [D2_IDX_SIZE-1:0] addr2, + input wire logic content_en, + output logic done, // Read signal - input wire logic read_en, output logic [WIDTH-1:0] read_data, - output logic read_done, // Write signals input wire logic write_en, - input wire logic [ WIDTH-1:0] write_data, - output logic write_done + input wire logic [ WIDTH-1:0] write_data ); wire [D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE-1:0] addr; assign addr = addr0 * (D1_SIZE * D2_SIZE) + addr1 * (D2_SIZE) + addr2; seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE * D2_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE)) mem (.clk(clk), .reset(reset), .addr0(addr), - .read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en), - .write_done(write_done)); + .content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en), + .done(done)); endmodule module seq_mem_d4 #( @@ -178,22 +160,21 @@ module seq_mem_d4 #( input wire logic [D1_IDX_SIZE-1:0] addr1, input wire logic [D2_IDX_SIZE-1:0] addr2, input wire logic [D3_IDX_SIZE-1:0] addr3, + input wire logic content_en, + output logic done, // Read signal - input wire logic read_en, output logic [WIDTH-1:0] read_data, - output logic read_done, // Write signals input wire logic write_en, - input wire logic [ WIDTH-1:0] write_data, - output logic write_done + input wire logic [ WIDTH-1:0] write_data ); wire [D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE+D3_IDX_SIZE-1:0] addr; assign addr = addr0 * (D1_SIZE * D2_SIZE * D3_SIZE) + addr1 * (D2_SIZE * D3_SIZE) + addr2 * (D3_SIZE) + addr3; seq_mem_d1 #(.WIDTH(WIDTH), .SIZE(D0_SIZE * D1_SIZE * D2_SIZE * D3_SIZE), .IDX_SIZE(D0_IDX_SIZE+D1_IDX_SIZE+D2_IDX_SIZE+D3_IDX_SIZE)) mem (.clk(clk), .reset(reset), .addr0(addr), - .read_en(read_en), .read_data(read_data), .read_done(read_done), .write_data(write_data), .write_en(write_en), - .write_done(write_done)); -endmodule \ No newline at end of file + .content_en(content_en), .read_data(read_data), .write_data(write_data), .write_en(write_en), + .done(done)); +endmodule diff --git a/tests/correctness/seq-mem-d4-add.futil b/tests/correctness/seq-mem-d4-add.futil index 74d3ddd69..af173460d 100644 --- a/tests/correctness/seq-mem-d4-add.futil +++ b/tests/correctness/seq-mem-d4-add.futil @@ -74,8 +74,9 @@ component main() -> () { in1.addr1 = j.out; in1.addr2 = k.out; in1.addr3 = l.out; - in1.read_en = 1'd1; - in1_reg.write_en = in1.read_done; + in1.content_en = 1'd1; + in1.write_en = 1'd0; + in1_reg.write_en = in1.done; in1_reg.in = in1.read_data; read_in1[done] = in1_reg.done; } @@ -84,8 +85,9 @@ component main() -> () { in2.addr1 = j.out; in2.addr2 = k.out; in2.addr3 = l.out; - in2.read_en = 1'd1; - in2_reg.write_en = in2.read_done; + in2.content_en = 1'd1; + in2.write_en = 1'd0; + in2_reg.write_en = in2.done; in2_reg.in = in2.read_data; read_in2[done] = in2_reg.done; } @@ -96,6 +98,7 @@ component main() -> () { out.addr1 = j.out; out.addr2 = k.out; out.addr3 = l.out; + out.content_en = 1'd1; out.write_en = 1'd1; out.write_data = add.out; update_val[done] = out.write_done; diff --git a/tests/correctness/seq-mem-dot-product.futil b/tests/correctness/seq-mem-dot-product.futil index fb06e03fa..0dc2175d3 100644 --- a/tests/correctness/seq-mem-dot-product.futil +++ b/tests/correctness/seq-mem-dot-product.futil @@ -38,19 +38,22 @@ component main() -> () { // Prime memories for reading group prime_in1 { - in1.read_en = 1'd1; + in1.content_en = 1'd1; + in1.write_en = 1'd0; in1.addr0 = idx.out; - prime_in1[done] = in1.read_done; + prime_in1[done] = in1.done; } group prime_in2 { - in2.read_en = 1'd1; + in2.content_en = 1'd1; + in2.write_en = 1'd0; in2.addr0 = idx.out; - prime_in2[done] = in2.read_done; + prime_in2[done] = in2.done; } // Computation group init_tmp { tmp.in = 32'd0; + tmp.content_en = 1'd1; tmp.write_en = 1'd1; init_tmp[done] = tmp.done; } @@ -58,6 +61,7 @@ component main() -> () { add.left = tmp.out; add.right = mult.out; tmp.in = add.out; + tmp.content_en = 1'd1; tmp.write_en = 1'd1; do_add[done] = tmp.done; } @@ -65,6 +69,7 @@ component main() -> () { // Write to output group write { out.addr0 = 1'd0; + out.content_en = 1'd1; out.write_en = 1'd1; out.write_data = tmp.out; write[done] = out.write_done; From 61a45568a90471af887f3888dac0f09de0b11052 Mon Sep 17 00:00:00 2001 From: Andrew Butt Date: Sun, 16 Jul 2023 15:26:06 -0400 Subject: [PATCH 2/2] Cleanup futil declarations --- primitives/memories.futil | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/primitives/memories.futil b/primitives/memories.futil index 223b9fd52..b8b662c39 100644 --- a/primitives/memories.futil +++ b/primitives/memories.futil @@ -3,11 +3,10 @@ extern "memories.sv" { @clk clk: 1, @reset reset: 1, @data addr0: IDX_SIZE, + @static(1) @go(1) content_en: 1 // Write ports @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, - // Read ports - @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, @done(1) done: 1 @@ -18,11 +17,10 @@ extern "memories.sv" { @reset reset: 1, @data addr0: D0_IDX_SIZE, @data addr1: D1_IDX_SIZE, + @static(1) @go(1) content_en: 1 // Write ports @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, - // Read ports - @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, @done(1) done: 1, @@ -34,11 +32,10 @@ extern "memories.sv" { @data addr0: D0_IDX_SIZE, @data addr1: D1_IDX_SIZE, @data addr2: D2_IDX_SIZE, + @static(1) @go(1) content_en: 1 // Write ports @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, - // Read ports - @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, @done(1) done: 1, @@ -51,11 +48,10 @@ extern "memories.sv" { @data addr1: D1_IDX_SIZE, @data addr2: D2_IDX_SIZE, @data addr3: D3_IDX_SIZE, + @static(1) @go(1) content_en: 1 // Write ports @write_together(1) write_en: 1, @write_together(1) @data write_data: WIDTH, - // Read ports - @static(1) @go(1) content_en: 1 ) -> ( @stable read_data: WIDTH, @done(1) done: 1,