From 805f110aefac1eca6bf860b4997c8b07efd4112a Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 18 Oct 2025 17:38:01 +1300 Subject: [PATCH] analogdevices: Extra tests `mem_gen.py` based on quicklogic tests. Remove BUFG from `lutram.ys`. Extra `sync_ram_sp` models in `arch/common/blockram.v`. Add analogdevices to main makefile tests. Not all the other tests are passing, but that's fine for now. --- Makefile | 1 + tests/arch/analogdevices/.gitignore | 1 + tests/arch/analogdevices/lutram.ys | 18 ++-- tests/arch/analogdevices/mem_gen.py | 121 +++++++++++++++++++++++++++ tests/arch/analogdevices/run-test.sh | 3 +- tests/arch/common/blockram.v | 80 ++++++++++++++++++ 6 files changed, 211 insertions(+), 13 deletions(-) create mode 100644 tests/arch/analogdevices/.gitignore create mode 100644 tests/arch/analogdevices/mem_gen.py diff --git a/Makefile b/Makefile index 934bd6586..86c98459c 100644 --- a/Makefile +++ b/Makefile @@ -879,6 +879,7 @@ endif # Tests that generate .mk with tests/gen-tests-makefile.sh MK_TEST_DIRS = +MK_TEST_DIRS += tests/arch/analogdevices MK_TEST_DIRS += tests/arch/anlogic MK_TEST_DIRS += tests/arch/ecp5 MK_TEST_DIRS += tests/arch/efinix diff --git a/tests/arch/analogdevices/.gitignore b/tests/arch/analogdevices/.gitignore new file mode 100644 index 000000000..fb232f235 --- /dev/null +++ b/tests/arch/analogdevices/.gitignore @@ -0,0 +1 @@ +t_*.ys diff --git a/tests/arch/analogdevices/lutram.ys b/tests/arch/analogdevices/lutram.ys index d3a088bdb..35fc09c86 100644 --- a/tests/arch/analogdevices/lutram.ys +++ b/tests/arch/analogdevices/lutram.ys @@ -12,10 +12,9 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 1 t:BUFG select -assert-count 8 t:FFRE select -assert-count 8 t:RAMS32X1 -select -assert-none t:BUFG t:FFRE t:RAMS32X1 %% t:* %D +select -assert-none t:FFRE t:RAMS32X1 %% t:* %D design -reset @@ -33,10 +32,9 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r dump -select -assert-count 1 t:BUFG select -assert-count 8 t:FFRE select -assert-count 8 t:RAMS64X1 -select -assert-none t:BUFG t:FFRE t:RAMS64X1 %% t:* %D +select -assert-none t:FFRE t:RAMS64X1 %% t:* %D design -reset @@ -53,10 +51,9 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w3r -select -assert-count 1 t:BUFG select -assert-count 24 t:FFRE select -assert-count 16 t:RAMD32X1 -select -assert-none t:BUFG t:FFRE t:RAMD32X1 %% t:* %D +select -assert-none t:FFRE t:RAMD32X1 %% t:* %D design -reset @@ -73,10 +70,9 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w3r -select -assert-count 1 t:BUFG select -assert-count 24 t:FFRE select -assert-count 16 t:RAMD64X1 -select -assert-none t:BUFG t:FFRE t:RAMD64X1 %% t:* %D +select -assert-none t:FFRE t:RAMD64X1 %% t:* %D design -reset @@ -93,10 +89,9 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 1 t:BUFG select -assert-count 6 t:FFRE select -assert-count 6 t:RAMS32X1 -select -assert-none t:BUFG t:FFRE t:RAMS32X1 %% t:* %D +select -assert-none t:FFRE t:RAMS32X1 %% t:* %D design -reset @@ -113,7 +108,6 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 1 t:BUFG select -assert-count 6 t:FFRE select -assert-count 6 t:RAMS64X1 -select -assert-none t:BUFG t:FFRE t:RAMS64X1 %% t:* %D +select -assert-none t:FFRE t:RAMS64X1 %% t:* %D diff --git a/tests/arch/analogdevices/mem_gen.py b/tests/arch/analogdevices/mem_gen.py new file mode 100644 index 000000000..b8037b918 --- /dev/null +++ b/tests/arch/analogdevices/mem_gen.py @@ -0,0 +1,121 @@ +from __future__ import annotations + +from dataclasses import dataclass + + +blockram_template = """# ====================================== +log ** GENERATING TEST {top} WITH PARAMS{param_str} +design -reset; read_verilog -defer ../common/blockram.v +chparam{param_str} {top} +hierarchy -top {top} +echo on +debug synth_analogdevices -tech {tech} -top {top} {opts} -run :map_ffram +stat; echo off +""" +inference_tests: "list[tuple[str, list[tuple[str, int]], str, list[str], list[str]]]" = [ + # RBRAM2 has TDP and SDP for 8192x5bit, 4096x9bit, and 2048x40bit + ("t16ffc", [("ADDRESS_WIDTH", 13), ("DATA_WIDTH", 5)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t16ffc", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 9)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t16ffc", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 40)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + # LUTRAM is generally cheaper than BRAM for undersized (SDP) memories + ("t16ffc", [("ADDRESS_WIDTH", 6), ("DATA_WIDTH", 1)], "sync_ram_sdp", ["-assert-count 1 t:RAMD64X1"], []), + ("t16ffc", [("ADDRESS_WIDTH", 6), ("DATA_WIDTH", 8)], "sync_ram_sdp", ["-assert-count 8 t:RAMD64X1"], []), + ("t16ffc", [("ADDRESS_WIDTH", 10), ("DATA_WIDTH", 8)], "sync_ram_sdp", ["-assert-count 128 t:RAMD64X1"], []), + ("t16ffc", [("ADDRESS_WIDTH", 10), ("DATA_WIDTH", 16)], "sync_ram_sdp", ["-assert-count 256 t:RAMD64X1"], []), + # RBRAM is half the depth of RBRAM2, and doesn't have TDP, also LUTRAM is cheaper, so we need to specify not to use it + ("t40lp", [("ADDRESS_WIDTH", 13), ("DATA_WIDTH", 5)], "sync_ram_sdp", ["-assert-count 2 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 5)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 9)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 10), ("DATA_WIDTH", 40)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + # 2048x32 and 2048x36bit are also valid + ("t16ffc", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 32)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t16ffc", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 36)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t40lp", [("ADDRESS_WIDTH", 10), ("DATA_WIDTH", 32)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 10), ("DATA_WIDTH", 36)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + + # 4096x16/18bit can be mapped to a single 2048x32/36bit + ("t16ffc", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 16)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t16ffc", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 18)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t40lp", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 16)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 18)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + # same for 8192x8/9bit + ("t16ffc", [("ADDRESS_WIDTH", 13), ("DATA_WIDTH", 8)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t16ffc", [("ADDRESS_WIDTH", 13), ("DATA_WIDTH", 9)], "sync_ram_*dp", ["-assert-count 1 t:RBRAM2"], []), + ("t40lp", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 8)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + ("t40lp", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 9)], "sync_ram_sdp", ["-assert-count 1 t:RBRAM"], ["-nolutram"]), + # but 4096x20bit requires extra memories because 2048x40bit has 8bit byte enables (which doesn't divide 20bit evenly) + ("t16ffc", [("ADDRESS_WIDTH", 12), ("DATA_WIDTH", 20)], "sync_ram_sdp", ["-assert-count 2 t:RBRAM2"], []), + ("t40lp", [("ADDRESS_WIDTH", 11), ("DATA_WIDTH", 20)], "sync_ram_sdp", ["-assert-count 2 t:RBRAM"], ["-nolutram"]), +] + +@dataclass +class TestClass: + params: dict[str, int] + top: str + assertions: list[str] + test_steps: None | list[dict[str, int]] + opts: list[str] + tech: str = "t16ffc" + +sim_tests: list[TestClass] = [] + +for (tech, params, top, assertions, opts) in inference_tests: + sim_test = TestClass( + params=dict(params), + top=top, + assertions=assertions, + test_steps=None, + opts=opts, + tech=tech, + ) + sim_tests.append(sim_test) + +i = 0 +j = 0 +max_j = 16 +f = None +for sim_test in sim_tests: + # format params + param_str = "" + for (key, val) in sim_test.params.items(): + param_str += f" -set {key} {val}" + + # resolve top module wildcards + top_list = [sim_test.top] + if "*dp" in sim_test.top: + top_list += [ + sim_test.top.replace("*dp", dp_sub) for dp_sub in ["sdp", "tdp"] + ] + if "w*r" in sim_test.top: + top_list += [ + sim_test.top.replace("w*r", wr_sub) for wr_sub in ["wwr", "wrr"] + ] + if len(top_list) > 1: + top_list.pop(0) + + # iterate over string substitutions + for top in top_list: + # limit number of tests per file to allow parallel make + if not f: + fn = f"t_mem{i}.ys" + f = open(fn, mode="w") + j = 0 + + # output yosys script test file + print( + blockram_template.format(param_str=param_str, top=top, tech=sim_test.tech, opts=" ".join(sim_test.opts)), + file=f + ) + for assertion in sim_test.assertions: + print(f"log ** CHECKING CELL COUNTS FOR TEST {top} WITH PARAMS{param_str} ON TECH {sim_test.tech}", file=f) + print(f"select {assertion}", file=f) + print("", file=f) + + # increment test counter + j += 1 + if j >= max_j: + f = f.close() + i += 1 + +if f: + f.close() diff --git a/tests/arch/analogdevices/run-test.sh b/tests/arch/analogdevices/run-test.sh index 691b70966..9b5e2f7f4 100755 --- a/tests/arch/analogdevices/run-test.sh +++ b/tests/arch/analogdevices/run-test.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash set -eu +python3 mem_gen.py source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" +generate_mk --yosys-scripts --bash diff --git a/tests/arch/common/blockram.v b/tests/arch/common/blockram.v index 4a9d45a6b..4358a4655 100644 --- a/tests/arch/common/blockram.v +++ b/tests/arch/common/blockram.v @@ -22,6 +22,30 @@ module sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) endmodule // sync_ram_sp +module sync_ram_sp_nochange #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) + (input wire write_enable, clk, + input wire [DATA_WIDTH-1:0] data_in, + input wire [ADDRESS_WIDTH-1:0] address_in, + output wire [DATA_WIDTH-1:0] data_out); + + localparam WORD = (DATA_WIDTH-1); + localparam DEPTH = (2**ADDRESS_WIDTH-1); + + reg [WORD:0] data_out_r; + reg [WORD:0] memory [0:DEPTH]; + + always @(posedge clk) begin + if (write_enable) + memory[address_in] <= data_in; + else + data_out_r <= memory[address_in]; + end + + assign data_out = data_out_r; + +endmodule // sync_ram_sp_nochange + + module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10) (input wire clk, write_enable, input wire [DATA_WIDTH-1:0] data_in, @@ -112,6 +136,62 @@ module sync_ram_sdp_wrr #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10, SHIFT_VAL=1) endmodule // sync_ram_sdp_wrr +module double_sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10, USE_TDP=0) +( + input wire write_enable_a, clk_a, + input wire [DATA_WIDTH-1:0] data_in_a, + input wire [ADDRESS_WIDTH-1:0] address_in_a, + output wire [DATA_WIDTH-1:0] data_out_a, + + input wire write_enable_b, clk_b, + input wire [DATA_WIDTH-1:0] data_in_b, + input wire [ADDRESS_WIDTH-1:0] address_in_b, + output wire [DATA_WIDTH-1:0] data_out_b +); + + generate + if (USE_TDP) begin + + sync_ram_tdp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH+1) + ) ram ( + .clk_a(clk_a), .clk_b(clk_b), + .write_enable_a(write_enable_a), .write_enable_b(write_enable_b), + .write_data_a(data_in_a), .write_data_b(data_in_b), + .addr_a({1'b0, address_in_a}), .addr_b({1'b1, address_in_b}), + .read_data_a(data_out_a), .read_data_b(data_out_b) + ); + + end else begin + + sync_ram_sp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) a_ram ( + .write_enable(write_enable_a), + .clk(clk_a), + .data_in(data_in_a), + .address_in(address_in_a), + .data_out(data_out_a) + ); + + sync_ram_sp #( + .DATA_WIDTH(DATA_WIDTH), + .ADDRESS_WIDTH(ADDRESS_WIDTH) + ) b_ram ( + .write_enable(write_enable_b), + .clk(clk_b), + .data_in(data_in_b), + .address_in(address_in_b), + .data_out(data_out_b) + ); + end + endgenerate + +endmodule // double_sync_ram_sp + + module double_sync_ram_sdp #(parameter DATA_WIDTH_A=8, ADDRESS_WIDTH_A=10, DATA_WIDTH_B=8, ADDRESS_WIDTH_B=10) ( input wire write_enable_a, clk_a,