From ac5fa9a83883ede45fac38c7288f8ade1887ade5 Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Tue, 10 May 2022 10:31:42 +1200 Subject: [PATCH 1/9] Addings tests for #1836 and #3205 --- tests/arch/ecp5/bug1836.mem | 32 +++++++++++++++++++++ tests/arch/ecp5/bug1836.ys | 31 ++++++++++++++++++++ tests/arch/ecp5/bug3205.ys | 57 +++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 tests/arch/ecp5/bug1836.mem create mode 100644 tests/arch/ecp5/bug1836.ys create mode 100644 tests/arch/ecp5/bug3205.ys diff --git a/tests/arch/ecp5/bug1836.mem b/tests/arch/ecp5/bug1836.mem new file mode 100644 index 000000000..1e904d87c --- /dev/null +++ b/tests/arch/ecp5/bug1836.mem @@ -0,0 +1,32 @@ +0x8000,0x8324,0x8647,0x896a,0x8c8b,0x8fab,0x92c7,0x95e1, +0x98f8,0x9c0b,0x9f19,0xa223,0xa527,0xa826,0xab1f,0xae10, +0xb0fb,0xb3de,0xb6b9,0xb98c,0xbc56,0xbf17,0xc1cd,0xc47a, +0xc71c,0xc9b3,0xcc3f,0xcebf,0xd133,0xd39a,0xd5f5,0xd842, +0xda82,0xdcb3,0xded7,0xe0eb,0xe2f1,0xe4e8,0xe6cf,0xe8a6, +0xea6d,0xec23,0xedc9,0xef5e,0xf0e2,0xf254,0xf3b5,0xf504, +0xf641,0xf76b,0xf884,0xf989,0xfa7c,0xfb5c,0xfc29,0xfce3, +0xfd89,0xfe1d,0xfe9c,0xff09,0xff61,0xffa6,0xffd8,0xfff5, +0xffff,0xfff5,0xffd8,0xffa6,0xff61,0xff09,0xfe9c,0xfe1d, +0xfd89,0xfce3,0xfc29,0xfb5c,0xfa7c,0xf989,0xf884,0xf76b, +0xf641,0xf504,0xf3b5,0xf254,0xf0e2,0xef5e,0xedc9,0xec23, +0xea6d,0xe8a6,0xe6cf,0xe4e8,0xe2f1,0xe0eb,0xded7,0xdcb3, +0xda82,0xd842,0xd5f5,0xd39a,0xd133,0xcebf,0xcc3f,0xc9b3, +0xc71c,0xc47a,0xc1cd,0xbf17,0xbc56,0xb98c,0xb6b9,0xb3de, +0xb0fb,0xae10,0xab1f,0xa826,0xa527,0xa223,0x9f19,0x9c0b, +0x98f8,0x95e1,0x92c7,0x8fab,0x8c8b,0x896a,0x8647,0x8324, +0x8000,0x7cdb,0x79b8,0x7695,0x7374,0x7054,0x6d38,0x6a1e, +0x6707,0x63f4,0x60e6,0x5ddc,0x5ad8,0x57d9,0x54e0,0x51ef, +0x4f04,0x4c21,0x4946,0x4673,0x43a9,0x40e8,0x3e32,0x3b85, +0x38e3,0x364c,0x33c0,0x3140,0x2ecc,0x2c65,0x2a0a,0x27bd, +0x257d,0x234c,0x2128,0x1f14,0x1d0e,0x1b17,0x1930,0x1759, +0x1592,0x13dc,0x1236,0x10a1,0xf1d,0xdab,0xc4a,0xafb, +0x9be,0x894,0x77b,0x676,0x583,0x4a3,0x3d6,0x31c, +0x276,0x1e2,0x163,0xf6,0x9e,0x59,0x27,0xa, +0x0,0xa,0x27,0x59,0x9e,0xf6,0x163,0x1e2, +0x276,0x31c,0x3d6,0x4a3,0x583,0x676,0x77b,0x894, +0x9be,0xafb,0xc4a,0xdab,0xf1d,0x10a1,0x1236,0x13dc, +0x1592,0x1759,0x1930,0x1b17,0x1d0e,0x1f14,0x2128,0x234c, +0x257d,0x27bd,0x2a0a,0x2c65,0x2ecc,0x3140,0x33c0,0x364c, +0x38e3,0x3b85,0x3e32,0x40e8,0x43a9,0x4673,0x4946,0x4c21, +0x4f04,0x51ef,0x54e0,0x57d9,0x5ad8,0x5ddc,0x60e6,0x63f4, +0x6707,0x6a1e,0x6d38,0x7054,0x7374,0x7695,0x79b8,0x7cdb, \ No newline at end of file diff --git a/tests/arch/ecp5/bug1836.ys b/tests/arch/ecp5/bug1836.ys new file mode 100644 index 000000000..d8533441e --- /dev/null +++ b/tests/arch/ecp5/bug1836.ys @@ -0,0 +1,31 @@ +read_verilog < Date: Thu, 7 Jul 2022 10:22:14 +1200 Subject: [PATCH 2/9] Asymmetric port ram tests with Xilinx Uses verilog code from User Guide 901 (2021.1) --- tests/arch/xilinx/asym_ram_sdp.ys | 50 ++++++++++++++ tests/arch/xilinx/asym_ram_sdp_read_wider.v | 72 ++++++++++++++++++++ tests/arch/xilinx/asym_ram_sdp_write_wider.v | 71 +++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 tests/arch/xilinx/asym_ram_sdp.ys create mode 100644 tests/arch/xilinx/asym_ram_sdp_read_wider.v create mode 100644 tests/arch/xilinx/asym_ram_sdp_write_wider.v diff --git a/tests/arch/xilinx/asym_ram_sdp.ys b/tests/arch/xilinx/asym_ram_sdp.ys new file mode 100644 index 000000000..37f6f314d --- /dev/null +++ b/tests/arch/xilinx/asym_ram_sdp.ys @@ -0,0 +1,50 @@ +# Memory bits <= 18K; Data width <= 36; Address width <= 14: -> RAMB18E1 + +# w4b | r16b +design -reset +read_verilog asym_ram_sdp_read_wider.v +synth_xilinx -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w8b | r16b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set WIDTHA 8 -set SIZEA 512 -set ADDRWIDTHA 9 asym_ram_sdp_read_wider +synth_xilinx -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w4b | r32b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set WIDTHB 32 -set SIZEB 128 -set ADDRWIDTHB 7 asym_ram_sdp_read_wider +synth_xilinx -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w16b | r4b +design -reset +read_verilog asym_ram_sdp_write_wider.v +synth_xilinx -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w16b | r8b +design -reset +read_verilog asym_ram_sdp_write_wider.v +chparam -set WIDTHB 8 -set SIZEB 512 -set ADDRWIDTHB 9 asym_ram_sdp_read_wider +synth_xilinx -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w32b | r4b +design -reset +read_verilog asym_ram_sdp_write_wider.v +chparam -set WIDTHA 32 -set SIZEA 128 -set ADDRWIDTHA 7 asym_ram_sdp_read_wider +synth_xilinx -top asym_ram_sdp_write_wider -noiopad +select -assert-count 1 t:RAMB18E1 + +# w4b | r24b +design -reset +read_verilog asym_ram_sdp_read_wider.v +chparam -set SIZEA 768 +chparam -set WIDTHB 24 -set SIZEB 128 -set ADDRWIDTHB 7 asym_ram_sdp_read_wider +synth_xilinx -top asym_ram_sdp_read_wider -noiopad +select -assert-count 1 t:RAMB18E1 + diff --git a/tests/arch/xilinx/asym_ram_sdp_read_wider.v b/tests/arch/xilinx/asym_ram_sdp_read_wider.v new file mode 100644 index 000000000..8743209e3 --- /dev/null +++ b/tests/arch/xilinx/asym_ram_sdp_read_wider.v @@ -0,0 +1,72 @@ +// Asymmetric port RAM +// Read Wider than Write. Read Statement in loop +//asym_ram_sdp_read_wider.v +module asym_ram_sdp_read_wider (clkA, clkB, enaA, weA, enaB, addrA, addrB, diA, doB); + parameter WIDTHA = 4; + parameter SIZEA = 1024; + parameter ADDRWIDTHA = 10; + + parameter WIDTHB = 16; + parameter SIZEB = 256; + parameter ADDRWIDTHB = 8; + + input clkA; + input clkB; + input weA; + input enaA, enaB; + input [ADDRWIDTHA-1:0] addrA; + input [ADDRWIDTHB-1:0] addrB; + input [WIDTHA-1:0] diA; + output [WIDTHB-1:0] doB; + + `define max(a,b) {(a) > (b) ? (a) : (b)} + `define min(a,b) {(a) < (b) ? (a) : (b)} + + function integer log2; + input integer value; + reg [31:0] shifted; + integer res; + begin + if (value < 2) + log2 = value; + else + begin + shifted = value-1; + for (res=0; shifted>0; res=res+1) + shifted = shifted>>1; + log2 = res; + end + end + endfunction + + localparam maxSIZE = `max(SIZEA, SIZEB); + localparam maxWIDTH = `max(WIDTHA, WIDTHB); + localparam minWIDTH = `min(WIDTHA, WIDTHB); + + localparam RATIO = maxWIDTH / minWIDTH; + localparam log2RATIO = log2(RATIO); + + reg [minWIDTH-1:0] RAM [0:maxSIZE-1]; + reg [WIDTHB-1:0] readB; + + always @(posedge clkA) + begin + if (enaA) begin + if (weA) + RAM[addrA] <= diA; + end + end + + always @(posedge clkB) + begin : ramread + integer i; + reg [log2RATIO-1:0] lsbaddr; + if (enaB) begin + for (i = 0; i < RATIO; i = i+1) begin + lsbaddr = i; + readB[(i+1)*minWIDTH-1 -: minWIDTH] <= RAM[{addrB, lsbaddr}]; + end + end + end + assign doB = readB; +endmodule \ No newline at end of file diff --git a/tests/arch/xilinx/asym_ram_sdp_write_wider.v b/tests/arch/xilinx/asym_ram_sdp_write_wider.v new file mode 100644 index 000000000..cd61a3ccc --- /dev/null +++ b/tests/arch/xilinx/asym_ram_sdp_write_wider.v @@ -0,0 +1,71 @@ +// Asymmetric port RAM +// Write wider than Read. Write Statement in a loop. +// asym_ram_sdp_write_wider.v +module asym_ram_sdp_write_wider (clkA, clkB, weA, enaA, enaB, addrA, addrB, diA, doB); + parameter WIDTHB = 4; + parameter SIZEB = 1024; + parameter ADDRWIDTHB = 10; + + parameter WIDTHA = 16; + parameter SIZEA = 256; + parameter ADDRWIDTHA = 8; + + input clkA; + input clkB; + input weA; + input enaA, enaB; + input [ADDRWIDTHA-1:0] addrA; + input [ADDRWIDTHB-1:0] addrB; + input [WIDTHA-1:0] diA; + output [WIDTHB-1:0] doB; + + `define max(a,b) {(a) > (b) ? (a) : (b)} + `define min(a,b) {(a) < (b) ? (a) : (b)} + + function integer log2; + input integer value; + reg [31:0] shifted; + integer res; + begin + if (value < 2) + log2 = value; + else + begin + shifted = value-1; + for (res=0; shifted>0; res=res+1) + shifted = shifted>>1; + log2 = res; + end + end + endfunction + + localparam maxSIZE = `max(SIZEA, SIZEB); + localparam maxWIDTH = `max(WIDTHA, WIDTHB); + localparam minWIDTH = `min(WIDTHA, WIDTHB); + + localparam RATIO = maxWIDTH / minWIDTH; + localparam log2RATIO = log2(RATIO); + + reg [minWIDTH-1:0] RAM [0:maxSIZE-1]; + reg [WIDTHB-1:0] readB; + + always @(posedge clkB) begin + if (enaB) begin + readB <= RAM[addrB]; + end + end + assign doB = readB; + + always @(posedge clkA) + begin : ramwrite + integer i; + reg [log2RATIO-1:0] lsbaddr; + for (i=0; i< RATIO; i= i+ 1) begin : write1 + lsbaddr = i; + if (enaA) begin + if (weA) + RAM[{addrA, lsbaddr}] <= diA[(i+1)*minWIDTH-1 -: minWIDTH]; + end + end + end +endmodule \ No newline at end of file From de2f140c090742ec8ccded4cfacc2dc6bac2a562 Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Tue, 5 Jul 2022 11:18:43 +1200 Subject: [PATCH 3/9] Testing TDP synth mapping New common sync_ram_tdp. Used in ecp5 and gatemate mem*.ys. --- tests/arch/common/blockram.v | 31 +++++++++++++++++++++++++++++++ tests/arch/ecp5/memories.ys | 10 ++++++++++ tests/arch/gatemate/memory.ys | 8 ++++++++ 3 files changed, 49 insertions(+) diff --git a/tests/arch/common/blockram.v b/tests/arch/common/blockram.v index 5ed0736d0..6b557fdca 100644 --- a/tests/arch/common/blockram.v +++ b/tests/arch/common/blockram.v @@ -45,3 +45,34 @@ module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) endmodule // sync_ram_sdp + +`default_nettype none +module sync_ram_tdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) + (input wire clk_a, clk_b, + input wire write_enable_a, write_enable_b, + input wire read_enable_a, read_enable_b, + input wire [DATA_WIDTH-1:0] write_data_a, write_data_b, + input wire [ADDRESS_WIDTH-1:0] addr_a, addr_b, + output reg [DATA_WIDTH-1:0] read_data_a, read_data_b); + + localparam WORD = (DATA_WIDTH-1); + localparam DEPTH = (2**ADDRESS_WIDTH-1); + + reg [WORD:0] mem [0:DEPTH]; + + always @(posedge clk_a) begin + if (write_enable_a) + mem[addr_a] <= write_data_a; + else + read_data_a <= mem[addr_a]; + end + + always @(posedge clk_b) begin + if (write_enable_b) + mem[addr_b] <= write_data_b; + else + read_data_b <= mem[addr_b]; + end + +endmodule // sync_ram_tdp + diff --git a/tests/arch/ecp5/memories.ys b/tests/arch/ecp5/memories.ys index 5cddcb952..f075182c8 100644 --- a/tests/arch/ecp5/memories.ys +++ b/tests/arch/ecp5/memories.ys @@ -260,3 +260,13 @@ setattr -set logic_block 1 m:memory synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 0 t:DP16KD # requested LUTROM explicitly select -assert-min 9 t:LUT4 + +# ============================== TDP RAM ============================== +# RAM bits <= 18K; Data width <= 18x2; Address width <= 9: -> DP16KD + +design -reset; read_verilog -defer ../common/blockram.v +chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 18 sync_ram_tdp +hierarchy -top sync_ram_tdp +synth_ecp5 -top sync_ram_tdp; cd sync_ram_tdp +select -assert-count 1 t:DP16KD +select -assert-none t:LUT4 diff --git a/tests/arch/gatemate/memory.ys b/tests/arch/gatemate/memory.ys index e919920f8..c4bf11cd3 100644 --- a/tests/arch/gatemate/memory.ys +++ b/tests/arch/gatemate/memory.ys @@ -6,6 +6,14 @@ cd sync_ram_sdp select -assert-count 1 t:CC_BUFG select -assert-count 1 t:CC_BRAM_20K +# 512 x 20 bit x 2 -> CC_BRAM_20K TDP RAM +design -reset +read_verilog ../common/blockram.v +chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 20 sync_ram_tdp +synth_gatemate -top sync_ram_tdp -noiopad +select -assert-count 2 t:CC_BUFG +select -assert-count 1 t:CC_BRAM_20K + # 512 x 80 bit -> CC_BRAM_40K SDP RAM design -reset read_verilog ../common/blockram.v From af1b9c9e070dd5873871c73c5762fbefd345a8c9 Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Thu, 7 Jul 2022 10:27:54 +1200 Subject: [PATCH 4/9] Tests for ram_style = "huge" iCE40 SPRAM and Xilinx URAM --- tests/arch/ice40/spram.v | 22 +++++ tests/arch/ice40/spram.ys | 15 ++++ tests/arch/xilinx/priority_memory.v | 122 +++++++++++++++++++++++++++ tests/arch/xilinx/priority_memory.ys | 60 +++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 tests/arch/ice40/spram.v create mode 100644 tests/arch/ice40/spram.ys create mode 100644 tests/arch/xilinx/priority_memory.v create mode 100644 tests/arch/xilinx/priority_memory.ys diff --git a/tests/arch/ice40/spram.v b/tests/arch/ice40/spram.v new file mode 100644 index 000000000..4e1aef2c6 --- /dev/null +++ b/tests/arch/ice40/spram.v @@ -0,0 +1,22 @@ +module top (clk, write_enable, read_enable, write_data, addr, read_data); +parameter DATA_WIDTH = 8; +parameter ADDR_WIDTH = 8; +parameter SKIP_RDEN = 1; + +input clk; +input write_enable, read_enable; +input [DATA_WIDTH - 1 : 0] write_data; +input [ADDR_WIDTH - 1 : 0] addr; +output [DATA_WIDTH - 1 : 0] read_data; + +(* ram_style = "huge" *) +reg [DATA_WIDTH - 1 : 0] mem [2**ADDR_WIDTH - 1 : 0]; + +always @(posedge clk) begin + if (write_enable) + mem[addr] <= write_data; + else if (SKIP_RDEN || read_enable) + read_data <= mem[addr]; +end + +endmodule diff --git a/tests/arch/ice40/spram.ys b/tests/arch/ice40/spram.ys new file mode 100644 index 000000000..709c21862 --- /dev/null +++ b/tests/arch/ice40/spram.ys @@ -0,0 +1,15 @@ +read_verilog spram.v +hierarchy -top top +synth_ice40 +select -assert-count 1 t:SB_SPRAM256KA +select -assert-none t:SB_SPRAM256KA %% t:* %D + +# Testing with pattern as described in pattern document +design -reset +read_verilog spram.v +chparam -set SKIP_RDEN 0 +hierarchy -top top +synth_ice40 +select -assert-count 1 t:SB_SPRAM256KA +# Below fails due to extra SB_LUT4 +# select -assert-none t:SB_SPRAM256KA %% t:* %D diff --git a/tests/arch/xilinx/priority_memory.v b/tests/arch/xilinx/priority_memory.v new file mode 100644 index 000000000..fc943e209 --- /dev/null +++ b/tests/arch/xilinx/priority_memory.v @@ -0,0 +1,122 @@ +module priority_memory ( + clk, wren_a, rden_a, addr_a, wdata_a, rdata_a, + wren_b, rden_b, addr_b, wdata_b, rdata_b + ); + + parameter ABITS = 12; + parameter WIDTH = 72; + + input clk; + input wren_a, rden_a, wren_b, rden_b; + input [ABITS-1:0] addr_a, addr_b; + input [WIDTH-1:0] wdata_a, wdata_b; + output reg [WIDTH-1:0] rdata_a, rdata_b; + + `ifdef USE_HUGE + (* ram_style = "huge" *) + `endif + reg [WIDTH-1:0] mem [0:2**ABITS-1]; + + integer i; + initial begin + rdata_a <= 'h0; + rdata_b <= 'h0; + end + + `ifndef FLIP_PORTS + always @(posedge clk) begin + // A port + if (wren_a) + mem[addr_a] <= wdata_a; + else if (rden_a) + rdata_a <= mem[addr_a]; + + // B port + if (wren_b) + mem[addr_b] <= wdata_b; + else if (rden_b) + if (wren_a && addr_a == addr_b) + rdata_b <= wdata_a; + else + rdata_b <= mem[addr_b]; + end + `else // FLIP PORTS + always @(posedge clk) begin + // A port + if (wren_b) + mem[addr_b] <= wdata_b; + else if (rden_b) + rdata_b <= mem[addr_b]; + + // B port + if (wren_a) + mem[addr_a] <= wdata_a; + else if (rden_a) + if (wren_b && addr_a == addr_b) + rdata_a <= wdata_b; + else + rdata_a <= mem[addr_a]; + end + `endif +endmodule + +module sp_write_first (clk, wren_a, rden_a, addr_a, wdata_a, rdata_a); + + parameter ABITS = 12; + parameter WIDTH = 72; + + input clk; + input wren_a, rden_a; + input [ABITS-1:0] addr_a; + input [WIDTH-1:0] wdata_a; + output reg [WIDTH-1:0] rdata_a; + + (* ram_style = "huge" *) + reg [WIDTH-1:0] mem [0:2**ABITS-1]; + + integer i; + initial begin + rdata_a <= 'h0; + end + + + always @(posedge clk) begin + // A port + if (wren_a) + mem[addr_a] <= wdata_a; + if (rden_a) + if (wren_a) + rdata_a <= wdata_a; + else + rdata_a <= mem[addr_a]; + end +endmodule + +module sp_read_first (clk, wren_a, rden_a, addr_a, wdata_a, rdata_a); + + parameter ABITS = 12; + parameter WIDTH = 72; + + input clk; + input wren_a, rden_a; + input [ABITS-1:0] addr_a; + input [WIDTH-1:0] wdata_a; + output reg [WIDTH-1:0] rdata_a; + + (* ram_style = "huge" *) + reg [WIDTH-1:0] mem [0:2**ABITS-1]; + + integer i; + initial begin + rdata_a <= 'h0; + end + + + always @(posedge clk) begin + // A port + if (wren_a) + mem[addr_a] <= wdata_a; + if (rden_a) + rdata_a <= mem[addr_a]; + end +endmodule diff --git a/tests/arch/xilinx/priority_memory.ys b/tests/arch/xilinx/priority_memory.ys new file mode 100644 index 000000000..d0b2a16ad --- /dev/null +++ b/tests/arch/xilinx/priority_memory.ys @@ -0,0 +1,60 @@ + +# no uram by default +design -reset +read_verilog priority_memory.v +synth_xilinx -family xcup -top priority_memory +select -assert-none t:URAM288 + +# uram parameter +design -reset +read -define USE_HUGE +read_verilog priority_memory.v +synth_xilinx -family xcup -top priority_memory -noiopad +select -assert-count 1 t:URAM288 + +# uram option +design -reset +read_verilog priority_memory.v +synth_xilinx -family xcup -top priority_memory -noiopad -uram +# check for URAM block +select -assert-count 1 t:URAM288 +# check port A in code maps to port A in hardware: +# %co:+[DOUT_A] selects everything connected to a URAM288.DOUT_A port +# w:rdata_a selects the wire rdata_a +# %i finds the intersection of the two above selections +# if the result is 1 then the wire rdata_a is connected to Port A correctly +select -assert-count 1 t:URAM288 %co:+[DOUT_A] w:rdata_a %i +# we expect no more than 2 LUT2s to control the hardware priority +# if there are extra LUTs, then it is likely emulating logic it shouldn't +# ignore anything using blif, since that doesn't seem to support priority logic +# and is indicative of using verific/tabby +select -assert-max 2 t:LUT* n:*blif* %d + +# reverse priority +design -reset +read -define FLIP_PORTS +read_verilog priority_memory.v +synth_xilinx -family xcup -top priority_memory -noiopad -uram +# test priority is mapped correctly, rdata_a should now be connected to Port B +# see above for details +select -assert-count 1 t:URAM288 %co:+[DOUT_B] w:rdata_a %i + +# sp write first +design -reset +read_verilog priority_memory.v +synth_xilinx -family xcup -top sp_write_first -noiopad +select -assert-count 1 t:URAM288 +# write first connects rdata_a to port B +# similar to above, but also tests that rdata_a *isn't* connected to port A +select -assert-none 1 t:URAM288 %co:+[DOUT_A] w:rdata_a %i +select -assert-count 1 t:URAM288 %co:+[DOUT_B] w:rdata_a %i + +# sp read first +design -reset +read_verilog priority_memory.v +synth_xilinx -family xcup -top sp_read_first -noiopad +select -assert-count 1 t:URAM288 +# read first connects rdata_a to port A +# see above for details +select -assert-count 1 t:URAM288 %co:+[DOUT_A] w:rdata_a %i +select -assert-none 1 t:URAM288 %co:+[DOUT_B] w:rdata_a %i From 7f033d3c1f4604d303da237fbc7a38ee503416ad Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Thu, 7 Jul 2022 11:10:33 +1200 Subject: [PATCH 5/9] More tests in memlib/generate.py Covers most of the todo list, at least functionally. Some minor issues with not always using hardware features. --- tests/memlib/generate.py | 677 +++++++++++++++++++++++++- tests/memlib/memlib_9b1B.txt | 31 ++ tests/memlib/memlib_9b1B.v | 68 +++ tests/memlib/memlib_block_sp_full.txt | 61 +++ tests/memlib/memlib_block_sp_full.v | 82 ++++ tests/memlib/memlib_clock_sdp.txt | 76 +++ tests/memlib/memlib_clock_sdp.v | 36 ++ tests/memlib/memlib_lut.txt | 18 +- tests/memlib/memlib_lut.v | 9 +- tests/memlib/memlib_multilut.txt | 19 + tests/memlib/memlib_multilut.v | 45 ++ tests/memlib/memlib_wren.txt | 37 ++ tests/memlib/memlib_wren.v | 33 ++ 13 files changed, 1180 insertions(+), 12 deletions(-) create mode 100644 tests/memlib/memlib_9b1B.txt create mode 100644 tests/memlib/memlib_9b1B.v create mode 100644 tests/memlib/memlib_block_sp_full.txt create mode 100644 tests/memlib/memlib_block_sp_full.v create mode 100644 tests/memlib/memlib_clock_sdp.txt create mode 100644 tests/memlib/memlib_clock_sdp.v create mode 100644 tests/memlib/memlib_multilut.txt create mode 100644 tests/memlib/memlib_multilut.v create mode 100644 tests/memlib/memlib_wren.txt create mode 100644 tests/memlib/memlib_wren.v diff --git a/tests/memlib/generate.py b/tests/memlib/generate.py index 341486584..f40210501 100644 --- a/tests/memlib/generate.py +++ b/tests/memlib/generate.py @@ -1,13 +1,6 @@ # TODO: -# - memory initialization -# - clock polarity combinations -# - CE/srst/rdwr/be interactions # - priority logic -# - byte enables, wrbe_separate -# - duplication for read ports -# - abits/dbits determination -# - mixed width # - swizzles for weird width progressions @@ -22,6 +15,7 @@ class Test: TESTS = [] ### basic sanity tests +# Asynchronous-read RAM ASYNC = """ module top(clk, ra, wa, rd, wd, we); @@ -56,6 +50,7 @@ TESTS += [ Test("async_small_block", ASYNC_SMALL, ["block_tdp"], [], {"RAM_BLOCK_TDP": 0}), ] +# Synchronous SDP read first SYNC = """ module top(clk, ra, wa, rd, wd, we); @@ -95,6 +90,261 @@ TESTS += [ Test("sync_small_block_attr", SYNC_SMALL_BLOCK, ["lut", "block_tdp"], [], {"RAM_BLOCK_TDP": 1}), ] +### initialization values testing +LUT_INIT = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output wire [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +integer i; +initial + for (i = 0; i < 2**ABITS-1; i = i + 1) + mem[i] = {ival}; + +always @(posedge clk) + if (we) + mem[wa] <= wd; + +assign rd = mem[ra]; + +endmodule +""" + +INIT_LUT_ZEROS = LUT_INIT.format(abits=4, dbits=4, ival=0); +INIT_LUT_VAL = LUT_INIT.format(abits=4, dbits=4, ival=5); +INIT_LUT_VAL2 = LUT_INIT.format(abits=6, dbits=6, ival="6'h12"); +INIT_LUT_X = LUT_INIT.format(abits=4, dbits=4, ival="4'hx") + +TESTS += [ + Test("init_lut_zeros_zero", INIT_LUT_ZEROS, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), + Test("init_lut_zeros_any", INIT_LUT_ZEROS, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), + Test("init_lut_val_zero", INIT_LUT_VAL, ["lut"], ["INIT_ZERO"], {"RAM_LUT":0}), #CHECK: no emulation? + Test("init_lut_val_any", INIT_LUT_VAL, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), + Test("init_lut_val_no_undef", INIT_LUT_VAL, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), + Test("init_lut_val2_any", INIT_LUT_VAL2, ["lut"], ["INIT_ANY"], {"RAM_LUT":8}), + Test("init_lut_val2_no_undef", INIT_LUT_VAL2, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":8}), + Test("init_lut_x_none", INIT_LUT_X, ["lut"], ["INIT_NONE"], {"RAM_LUT":1}), + Test("init_lut_x_zero", INIT_LUT_X, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), + Test("init_lut_x_any", INIT_LUT_X, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), + Test("init_lut_x_no_undef", INIT_LUT_X, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), +] + +### width testing 9-bit-per-byte +RAM_9b1B = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[wa] <= wd; + +always @(posedge clk) + rd <= mem[ra]; + +endmodule +""" + +RAM_18b2B = RAM_9b1B.format(abits=3, dbits=18); +RAM_9b1B = RAM_9b1B.format(abits=4, dbits=9); +RAM_4b1B = RAM_9b1B.format(abits=5, dbits=4); +RAM_2b1B = RAM_9b1B.format(abits=6, dbits=2); +RAM_1b1B = RAM_9b1B.format(abits=7, dbits=1); + +TESTS += [ + Test("ram_18b2B", RAM_18b2B, ["9b1B"], [], {"RAM_9b1B":1}), + Test("ram_9b1B", RAM_9b1B, ["9b1B"], [], {"RAM_9b1B":1}), + Test("ram_4b1B", RAM_4b1B, ["9b1B"], [], {"RAM_9b1B":1}), + Test("ram_2b1B", RAM_2b1B, ["9b1B"], [], {"RAM_9b1B":1}), + Test("ram_1b1B", RAM_1b1B, ["9b1B"], [], {"RAM_9b1B":1}), +] + +### initializing 9-bits-per-byte +RAM_9b1B_init = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +integer i; +initial + for (i = 0; i < 2**ABITS-1; i = i + 1) + mem[i] = {ival}; + +always @(posedge clk) + if (we) + mem[wa] <= wd; + +always @(posedge clk) + rd <= mem[ra]; + +endmodule +""" + +INIT_9b1B_ZEROS = RAM_9b1B_init.format(abits=4, dbits=9, ival=0); +INIT_9b1B_VAL = RAM_9b1B_init.format(abits=4, dbits=9, ival=275); +INIT_13b2B_VAL = RAM_9b1B_init.format(abits=3, dbits=13, ival="13'h01f3") +INIT_18b2B_VAL = RAM_9b1B_init.format(abits=4, dbits=18, ival="18'h1f39a"); +INIT_4b1B_X = RAM_9b1B_init.format(abits=5, dbits=4, ival="4'hx") + +TESTS += [ + Test("init_9b1B_zeros_zero", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), + Test("init_9b1B_zeros_any", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), + Test("init_9b1B_val_zero", INIT_9b1B_VAL, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":0}), #CHECK: no emulation? + Test("init_9b1B_val_any", INIT_9b1B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), + Test("init_9b1B_val_no_undef", INIT_9b1B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), + Test("init_13b2B_val_any", INIT_13b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), + Test("init_18b2B_val_any", INIT_18b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":2}), + Test("init_18b2B_val_no_undef", INIT_18b2B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":2}), + Test("init_4b1B_x_none", INIT_4b1B_X, ["9b1B"], ["INIT_NONE"], {"RAM_9b1B":1}), + Test("init_4b1B_x_zero", INIT_4b1B_X, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), + Test("init_4b1B_x_any", INIT_4b1B_X, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), + Test("init_4b1B_x_no_undef", INIT_4b1B_X, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), +] + +### Clock polarity combinations +# I'm not entirely convinced auto-test is correctly testing clock edging +# but they do at least all gen/synth +SYNCCLOCK = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = 8; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[wa] <= wd; + +always @(posedge clk) + rd <= mem[ra]; + +endmodule +""" +for (abits, cnt, wclk, rclk, shared) in [ + (4, 1, "ANY","ANY", False), + (4, 1, "ANY","NEG", False), + (4, 1, "ANY","POS", False), + (4, 1, "NEG","ANY", False), + (4, 1, "NEG","POS", False), + (4, 1, "NEG","NEG", False), + (4, 1, "POS","ANY", False), + (4, 1, "POS","NEG", False), + (4, 1, "POS","POS", False), + (4, 1, "ANY","ANY", True), + (4, 0, "NEG","POS", True), # FF mapping + (4, 1, "NEG","NEG", True), + (4, 0, "POS","NEG", True), # FF mapping + (4, 1, "POS","POS", True), + # cannot combine "ANY" with "POS|NEG" when using shared clock +]: + name = f"clock_a{abits}_w{wclk}r{rclk}s{shared}" + defs = ["WCLK_" + wclk, "RCLK_" + rclk] + if (shared): + defs.append("SHARED_CLK") + TESTS.append(Test( + name, SYNCCLOCK.format(abits=abits), + ["clock_sdp"], defs, {"RAM_CLOCK_SDP": cnt} + )) + +### mixed width testing +# Wide write port +MIXED_WRITE = """ +module top(clk, ra, wa, rd, wd, we); + +localparam WABITS = {wabits}; +localparam WDBITS = {wdbits}; + +localparam RABITS = {rabits}; +localparam RDBITS = {rdbits}; + +input wire clk; +input wire we; +input wire [WABITS-1:0] wa; +input wire [WDBITS-1:0] wd; +input wire [RABITS-1:0] ra; +output reg [RDBITS-1:0] rd; + +localparam DEPTH = (2**WABITS); + +localparam OFFSET = RABITS-WABITS; + +(* syn_ramstyle = "block_ram" *) +reg [WDBITS-1:0] mem [0:DEPTH-1]; + +always @(posedge clk) + if (we) + mem[wa] <= wd; + +if (OFFSET > 0) begin + reg [WDBITS-1:0] mem_read; + reg [OFFSET-1:0] subaddr_r; + always @(posedge clk) begin + mem_read <= mem[ra[RABITS-1:OFFSET]]; + subaddr_r <= ra[OFFSET-1:0]; + end + + always @(mem_read, subaddr_r) + rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; +end +else +begin + always @(posedge clk) + case (OFFSET) + 0: rd <= mem[ra]; + -1: rd <= {{ mem[ra], mem[ra+1] }}; + endcase +end +endmodule +""" + +UNMIXED = MIXED_WRITE.format(wabits=4, wdbits=9, rabits=4, rdbits=9) +MIXED_9_18 = MIXED_WRITE.format(wabits=5, wdbits=9, rabits=4, rdbits=18) +MIXED_18_9 = MIXED_WRITE.format(wabits=3, wdbits=18, rabits=4, rdbits=9) +MIXED_36_9 = MIXED_WRITE.format(wabits=3, wdbits=36, rabits=5, rdbits=9) +MIXED_4_2 = MIXED_WRITE.format(wabits=5, wdbits=4, rabits=6, rdbits=2); + +TESTS += [ + Test("unmixed", UNMIXED, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_9_18", MIXED_9_18, ["9b1B"], [], {"RAM_9b1B":4}), #CHECK: only using half the memory + Test("mixed_18_9", MIXED_18_9, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_36_9", MIXED_36_9, ["9b1B"], [], {"RAM_9b1B":2}), + Test("mixed_4_2", MIXED_4_2, ["9b1B"], [], {"RAM_9b1B":1}), +] + ### basic TDP test TDP = """ @@ -131,7 +381,7 @@ TESTS += [ ] # shared clock - +# Synchronous SDP with clock domain crossing SYNC_2CLK = """ module top(rclk, wclk, ra, wa, rd, wd, we); @@ -163,7 +413,7 @@ TESTS += [ ] # inter-port transparency - +# Synchronous SDP with write-first behaviour SYNC_TRANS = """ module top(clk, ra, wa, rd, wd, we); @@ -201,7 +451,7 @@ TESTS += [ ] # rdwr checks - +# Synchronous single-port RAM with mutually exclusive read/write SP_NO_CHANGE = """ module top(clk, addr, rd, wd, we); @@ -247,6 +497,7 @@ end endmodule """ +# Synchronous single-port RAM with write-first behaviour SP_NEW = """ module top(clk, addr, rd, wd, we); @@ -295,6 +546,7 @@ end endmodule """ +# Synchronous single-port RAM with read-first behaviour SP_OLD = """ module top(clk, addr, rd, wd, we); @@ -373,6 +625,7 @@ TESTS += [ Test("sp_old_auto_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), ] +# Synchronous read port with initial value SP_INIT = """ module top(clk, addr, rd, wd, we, re); @@ -418,6 +671,7 @@ TESTS += [ Test("sp_init_v_any_re", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), ] +# Synchronous read port with asynchronous reset SP_ARST = """ module top(clk, addr, rd, wd, we, re, ar); @@ -488,6 +742,7 @@ TESTS += [ Test("sp_arst_n_init_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), ] +# Synchronous read port with synchronous reset (reset priority over enable) SP_SRST = """ module top(clk, addr, rd, wd, we, re, sr); @@ -515,6 +770,7 @@ end endmodule """ +# Synchronous read port with synchronous reet (enable priority over reset) SP_SRST_G = """ module top(clk, addr, rd, wd, we, re, sr); @@ -602,6 +858,180 @@ TESTS += [ Test("sp_srst_gv_init_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), ] +# Byte enables, wrbe_separate +SYNC_ENABLE = """ +module top(clk, rwa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) begin + if (we) + mem[rwa] <= wd; + else + rd <= mem[rwa]; +end + +endmodule +""" + +for (abits, dbits, sep, defs, cells) in [ + (4, 4, False, ["NO_BYTE"], {"RAM_WREN": 1}), + (5, 4, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (6, 4, False, ["NO_BYTE"], {"RAM_WREN": 4}), + # (4, 4, True, ["NO_BYTE"], {"RAM_WREN": 1}), # should throw an error + (3, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), # needs two write ports + (4, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (4, 4, False, ["W4_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W4_B4"], {"RAM_WREN": 2}), + (4, 8, False, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, False, ["W8_B8"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B8"], {"RAM_WREN": 1}), + +]: + name = f"wren_a{abits}d{dbits}_{defs[0]}" + if (sep): + defs.append("WRBE_SEPARATE") + name += "_separate" + + TESTS.append(Test( + name, SYNC_ENABLE.format(abits=abits, dbits=dbits), + ["wren"], defs, cells + )) + +# Write port with byte enables +ENABLES = """ +module top(clk, we, be, rwa, wd, rd); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam WORDS = {words}; + +input wire clk; +input wire we; +input wire [WORDS-1:0] be; +input wire [ABITS-1:0] rwa; +input wire [(WBITS*WORDS)-1:0] wd; +output reg [(WBITS*WORDS)-1:0] rd; + +reg [(WBITS*WORDS)-1:0] mem [0:2**ABITS-1]; + +integer i; +always @(posedge clk) + for (i=0; i Date: Mon, 11 Jul 2022 12:31:38 +1200 Subject: [PATCH 6/9] Fix for sync_ram_sdp not being final module Explicitly declare -top in synth_intel_alm. --- tests/arch/intel_alm/blockram.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/arch/intel_alm/blockram.ys b/tests/arch/intel_alm/blockram.ys index 3b61b9339..21b5ecbfb 100644 --- a/tests/arch/intel_alm/blockram.ys +++ b/tests/arch/intel_alm/blockram.ys @@ -1,6 +1,6 @@ read_verilog ../common/blockram.v chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp -synth_intel_alm -family cyclonev -noiopad -noclkbuf +synth_intel_alm -top sync_ram_sdp -family cyclonev -noiopad -noclkbuf cd sync_ram_sdp select -assert-count 1 t:MISTRAL_NOT select -assert-count 1 t:MISTRAL_M10K From 51c2d476c2209b3dad9e0a0199648274b5c3ea82 Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Mon, 25 Jul 2022 10:10:21 +1200 Subject: [PATCH 7/9] Removing extra `default_nettype` lines --- tests/arch/common/blockram.v | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/arch/common/blockram.v b/tests/arch/common/blockram.v index 6b557fdca..c06ac96d5 100644 --- a/tests/arch/common/blockram.v +++ b/tests/arch/common/blockram.v @@ -22,7 +22,6 @@ module sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) endmodule // sync_ram_sp -`default_nettype none module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) (input wire clk, write_enable, input wire [DATA_WIDTH-1:0] data_in, @@ -46,7 +45,6 @@ module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) endmodule // sync_ram_sdp -`default_nettype none module sync_ram_tdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) (input wire clk_a, clk_b, input wire write_enable_a, write_enable_b, From 445a801a8587d75d3f0767cf9ba15776f50c5287 Mon Sep 17 00:00:00 2001 From: KrystalDelusion Date: Mon, 25 Jul 2022 10:12:30 +1200 Subject: [PATCH 8/9] bug3205.ys removed Made redundant by TDP test(s) in memories.ys --- tests/arch/ecp5/bug3205.ys | 57 -------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 tests/arch/ecp5/bug3205.ys diff --git a/tests/arch/ecp5/bug3205.ys b/tests/arch/ecp5/bug3205.ys deleted file mode 100644 index f2e936530..000000000 --- a/tests/arch/ecp5/bug3205.ys +++ /dev/null @@ -1,57 +0,0 @@ -read_verilog < Date: Mon, 25 Jul 2022 10:21:00 +1200 Subject: [PATCH 9/9] Genericising bug1836.ys --- tests/arch/ecp5/bug1836.ys | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/tests/arch/ecp5/bug1836.ys b/tests/arch/ecp5/bug1836.ys index d8533441e..15cdf4228 100644 --- a/tests/arch/ecp5/bug1836.ys +++ b/tests/arch/ecp5/bug1836.ys @@ -1,31 +1,23 @@ read_verilog <