mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 19:52:31 +00:00 
			
		
		
		
	`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.
		
			
				
	
	
		
			121 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 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()
 |