[prim] Make ROM_INIT_FILE a parameter
Instead of having a global define ROM_INIT_FILE, which contains a path
to a VMEM file with the boot ROM contents, use a parameter passed
through the hierarchy. This enables multiple instantiations of the ROM,
and avoids naming clashes between the ROM_INIT_FILE/SRAM_INIT_FILE
define, which can be used only once in the whole toplevel design.
This requires changes in various places to properly pass through the
parameter.
Instead of updating the prim_xilinx_rom variant, remove it. This
primitive is identical to the generic one, with the addition of
generating an empty ROM if no ROM initialization file is present during
the synthesis run. We capture this problem now in a more user-friendly
way with a TCL script after synthesis; removing this primitive here
avoids updating it first to the new way of passing in the init file.
The Arty S7 changes were done blindly, I don't have that board. I also
note that the board was very likely broken before, as the ROM init file
name was not called SRAM_INIT_FILE for a long time.
Fixes #2225
Signed-off-by: Philipp Wagner <phw@lowrisc.org>
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 1cb5092..5255c5e 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -269,7 +269,7 @@
run --target=synth --setup --build \
--build-root="$OBJ_DIR/hw" \
lowrisc:systems:top_earlgrey_nexysvideo \
- --ROM_INIT_FILE="$BOOTROM_VMEM"
+ --BootRomInitFile="$BOOTROM_VMEM"
cp "$OBJ_DIR/hw/synth-vivado/lowrisc_systems_top_earlgrey_nexysvideo_0.1.bit" \
"$BIN_DIR/hw/top_earlgrey"
diff --git a/hw/ip/prim/rtl/prim_util_memload.sv b/hw/ip/prim/rtl/prim_util_memload.sv
index d5ebf3f..db77102 100644
--- a/hw/ip/prim/rtl/prim_util_memload.sv
+++ b/hw/ip/prim/rtl/prim_util_memload.sv
@@ -12,7 +12,10 @@
* - A memory array named `mem`.
* - A parameter `Width` giving the memory width (word size) in bit.
* - A parameter `Depth` giving the memory depth in words.
+ * - A parameter `MemInitFile` with a file path of a VMEM file to be loaded into
+* the memory if not empty.
*/
+
`ifdef VERILATOR
// Task for loading 'mem' with SystemVerilog system task $readmemh()
export "DPI-C" task simutil_verilator_memload;
@@ -50,10 +53,9 @@
end
`endif
-`ifdef SRAM_INIT_FILE
- localparam MEM_FILE = `PRIM_STRINGIFY(`SRAM_INIT_FILE);
- initial begin
- $display("Initializing memory from %s", MEM_FILE);
- $readmemh(MEM_FILE, mem);
+initial begin
+ if (MemInitFile != "") begin : gen_meminit
+ $display("Initializing memory %m from file '%s'.", MemInitFile);
+ $readmemh(MemInitFile, mem);
end
-`endif
+end
diff --git a/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv b/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
index 4c8085f..e81bf84 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
@@ -10,6 +10,8 @@
parameter int Width = 32, // bit
parameter int Depth = 128,
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
+ parameter MemInitFile = "", // VMEM file to initialize the memory with
+
localparam int Aw = $clog2(Depth) // derived parameter
) (
input logic clk_i,
diff --git a/hw/ip/prim_generic/rtl/prim_generic_ram_2p.sv b/hw/ip/prim_generic/rtl/prim_generic_ram_2p.sv
index 36a90d4..2666879 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_ram_2p.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_ram_2p.sv
@@ -7,11 +7,12 @@
// Implementing ECC should be done inside wrapper not this model.
module prim_generic_ram_2p #(
- parameter int Width = 32, // bit
- parameter int Depth = 128,
+ parameter int Width = 32, // bit
+ parameter int Depth = 128,
parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
+ parameter MemInitFile = "", // VMEM file to initialize the memory with
- localparam int Aw = $clog2(Depth) // derived parameter
+ localparam int Aw = $clog2(Depth) // derived parameter
) (
input clk_a_i,
input clk_b_i,
diff --git a/hw/ip/prim_generic/rtl/prim_generic_rom.sv b/hw/ip/prim_generic/rtl/prim_generic_rom.sv
index 3bd1c2a..9bfe88b 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_rom.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_rom.sv
@@ -5,9 +5,11 @@
`include "prim_assert.sv"
module prim_generic_rom #(
- parameter int Width = 32,
- parameter int Depth = 2048, // 8kB default
- localparam int Aw = $clog2(Depth)
+ parameter int Width = 32,
+ parameter int Depth = 2048, // 8kB default
+ parameter MemInitFile = "", // VMEM file to initialize the memory with
+
+ localparam int Aw = $clog2(Depth)
) (
input clk_i,
input rst_ni,
diff --git a/hw/ip/prim_xilinx/lint/prim_xilinx_rom.vlt b/hw/ip/prim_xilinx/lint/prim_xilinx_rom.vlt
deleted file mode 100644
index 544a7b7..0000000
--- a/hw/ip/prim_xilinx/lint/prim_xilinx_rom.vlt
+++ /dev/null
@@ -1,4 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
diff --git a/hw/ip/prim_xilinx/lint/prim_xilinx_rom.waiver b/hw/ip/prim_xilinx/lint/prim_xilinx_rom.waiver
deleted file mode 100644
index af90009..0000000
--- a/hw/ip/prim_xilinx/lint/prim_xilinx_rom.waiver
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-#
diff --git a/hw/ip/prim_xilinx/prim_xilinx_rom.core b/hw/ip/prim_xilinx/prim_xilinx_rom.core
deleted file mode 100644
index 9e4a053..0000000
--- a/hw/ip/prim_xilinx/prim_xilinx_rom.core
+++ /dev/null
@@ -1,44 +0,0 @@
-CAPI=2:
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-
-name: "lowrisc:prim_xilinx:rom"
-description: "Xilinx implementation of a Read-Only Memory (ROM) primitive"
-filesets:
- files_rtl:
- depend:
- - lowrisc:prim:all
- files:
- - rtl/prim_xilinx_rom.sv
- file_type: systemVerilogSource
-
- files_verilator_waiver:
- depend:
- # common waivers
- - lowrisc:lint:common
- files:
- - lint/prim_xilinx_rom.vlt
- file_type: vlt
-
- files_ascentlint_waiver:
- depend:
- # common waivers
- - lowrisc:lint:common
- files:
- - lint/prim_xilinx_rom.waiver
- file_type: waiver
-
- files_veriblelint_waiver:
- depend:
- # common waivers
- - lowrisc:lint:common
- - lowrisc:lint:comportable
-
-targets:
- default:
- filesets:
- - tool_verilator ? (files_verilator_waiver)
- - tool_ascentlint ? (files_ascentlint_waiver)
- - tool_veriblelint ? (files_veriblelint_waiver)
- - files_rtl
diff --git a/hw/ip/prim_xilinx/rtl/prim_xilinx_rom.sv b/hw/ip/prim_xilinx/rtl/prim_xilinx_rom.sv
deleted file mode 100644
index 5703270..0000000
--- a/hw/ip/prim_xilinx/rtl/prim_xilinx_rom.sv
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-/**
- * Implementation of a Read-Only Memory (ROM) primitive for Xilinx FPGAs
- *
- * This implementation of a ROM primitive is coded as outlined in UG 901 to
- * enable Xilinx Vivado infer Block RAM (BRAM) or LUT RAM from it. No mapping
- * target is forced; depending on the Width, Depth and other factors Vivado
- * chooses a mapping target.
- *
- * It is possible to force the mapping to BRAM or distributed RAM by using the
- * ROM_STYLE directive in an XDC file.
- */
-
-`include "prim_assert.sv"
-
-module prim_xilinx_rom #(
- parameter int Width = 32,
- parameter int Depth = 2048, // 8kB default
- parameter int Aw = $clog2(Depth)
-) (
- input clk_i,
- input [Aw-1:0] addr_i,
- input cs_i,
- output logic [Width-1:0] dout_o,
- output logic dvalid_o
-
-);
-
- `ifdef ROM_INIT_FILE
- // Only create an actual ROM block if ROM data is specified
- //
- // Xilinx Vivado infers a BRAM or LUTRAM from the ROM code below only if mem
- // is actually being written to through $readmemh(). If no ROM_INIT_FILE is
- // given and hence the mem initialization is missing, registers are inferred
- // instead. This severely degrades the synthesis quality for no good reason.
- logic [Width-1:0] mem [Depth];
-
- localparam MEM_FILE = `PRIM_STRINGIFY(`ROM_INIT_FILE);
- initial
- begin
- $display("Initializing ROM from %s", MEM_FILE);
- $readmemh(MEM_FILE, mem);
- end
-
- always_ff @(posedge clk_i) begin
- if (cs_i) begin
- dout_o <= mem[addr_i];
- end
- end
- `else
- // ROM is not initialized
- always_ff @(posedge clk_i) begin
- dout_o <= '0;
- end
- `endif
-
- always_ff @(posedge clk_i) begin
- dvalid_o <= cs_i;
- end
-
-
- ////////////////
- // ASSERTIONS //
- ////////////////
-
- // Control Signals should never be X
- `ASSERT(noXOnCsI, !$isunknown(cs_i), clk_i, '0)
-
-endmodule
diff --git a/hw/top_earlgrey/data/top_earlgrey.sv.tpl b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
index c8021c9..046b80a 100644
--- a/hw/top_earlgrey/data/top_earlgrey.sv.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
@@ -30,7 +30,8 @@
dm_rst = top["reset_paths"]["lc"]
%>\
module top_${top["name"]} #(
- parameter bit IbexPipeLine = 0
+ parameter bit IbexPipeLine = 0,
+ parameter BootRomInitFile = ""
) (
// Clock and Reset
input clk_i,
@@ -421,7 +422,8 @@
## TODO: Replace emulated ROM to real ROM in ASIC SoC
prim_rom #(
.Width(${data_width}),
- .Depth(${rom_depth})
+ .Depth(${rom_depth}),
+ .MemInitFile(BootRomInitFile)
) u_rom_${m["name"]} (
% for key in clocks:
.${key} (${clocks[key]}),
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 7abb4d8..ff6e4dc 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -3,7 +3,8 @@
// SPDX-License-Identifier: Apache-2.0
module top_earlgrey #(
- parameter bit IbexPipeLine = 0
+ parameter bit IbexPipeLine = 0,
+ parameter BootRomInitFile = ""
) (
// Clock and Reset
input clk_i,
@@ -373,7 +374,8 @@
prim_rom #(
.Width(32),
- .Depth(4096)
+ .Depth(4096),
+ .MemInitFile(BootRomInitFile)
) u_rom_rom (
.clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_sys_n),
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv b/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
index 16ab392..fc3a897 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
@@ -2,7 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-module top_earlgrey_artys7 (
+module top_earlgrey_artys7 #(
+ // Path to a VMEM file containing the contents of the boot ROM, which will be
+ // baked into the FPGA bitstream.
+ parameter BootRomInitFile = "boot_rom_fpga_artys7.32.vmem"
+) (
// Clock and Reset
inout IO_CLK,
inout IO_RST_N,
@@ -161,7 +165,8 @@
//////////////////////
top_earlgrey #(
- .IbexPipeLine(1)
+ .IbexPipeLine(1),
+ .BootRomInitFile(BootRomInitFile)
) top_earlgrey (
// Clocks, resets
.clk_i ( clk ),
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv b/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
index ff3ddec..3bc70e0 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
@@ -2,7 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-module top_earlgrey_nexysvideo (
+module top_earlgrey_nexysvideo #(
+ // Path to a VMEM file containing the contents of the boot ROM, which will be
+ // baked into the FPGA bitstream.
+ parameter BootRomInitFile = "boot_rom_fpga_nexysvideo.32.vmem"
+) (
// Clock and Reset
inout IO_CLK,
inout IO_RST_N,
@@ -202,7 +206,8 @@
//////////////////////
top_earlgrey #(
- .IbexPipeLine(1)
+ .IbexPipeLine(1),
+ .BootRomInitFile(BootRomInitFile)
) top_earlgrey (
// Clocks, resets
.clk_i ( clk ),
diff --git a/hw/top_earlgrey/top_earlgrey_artys7-50.core b/hw/top_earlgrey/top_earlgrey_artys7-50.core
index 71e258a..5f2b188 100644
--- a/hw/top_earlgrey/top_earlgrey_artys7-50.core
+++ b/hw/top_earlgrey/top_earlgrey_artys7-50.core
@@ -21,15 +21,15 @@
parameters:
# XXX: This parameter needs to be absolute, or relative to the *.runs/synth_1
# directory. It's best to pass it as absolute path when invoking fusesoc, e.g.
- # --SRAM_INIT_FILE=$PWD/sw/device/examples/hello_world/hello_world.vmem
+ # --BootRomInitFile=$PWD/build-bin/sw/device/boot_rom/boot_rom_fpga_nexysvideo.32.vmem
# XXX: The VMEM file should be added to the sources of the Vivado project to
# make the Vivado dependency tracking work. However this requires changes to
# fusesoc first.
- SRAM_INIT_FILE:
+ BootRomInitFile:
datatype: str
- description: SRAM initialization file in vmem hex format
+ description: Boot ROM initialization file in 32 bit vmem hex format
default: "../../../../../build-bin/sw/device/boot_rom/boot_rom_fpga_nexysvideo.32.vmem"
- paramtype: vlogdefine
+ paramtype: vlogparam
# For value definition, please see ip/prim/rtl/prim_pkg.sv
PRIM_DEFAULT_IMPL:
datatype: str
@@ -44,7 +44,7 @@
- files_constraints
toplevel: top_earlgrey_artys7
parameters:
- - SRAM_INIT_FILE
+ - BootRomInitFile
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
tools:
vivado:
diff --git a/hw/top_earlgrey/top_earlgrey_nexysvideo.core b/hw/top_earlgrey/top_earlgrey_nexysvideo.core
index 84460ea..8d6cf89 100644
--- a/hw/top_earlgrey/top_earlgrey_nexysvideo.core
+++ b/hw/top_earlgrey/top_earlgrey_nexysvideo.core
@@ -30,15 +30,15 @@
parameters:
# XXX: This parameter needs to be absolute, or relative to the *.runs/synth_1
# directory. It's best to pass it as absolute path when invoking fusesoc, e.g.
- # --ROM_INIT_FILE=$PWD/build-bin/sw/device/boot_rom/boot_rom_fpga_nexysvideo.vmem
+ # --BootRomInitFile=$PWD/build-bin/sw/device/boot_rom/boot_rom_fpga_nexysvideo.32.vmem
# XXX: The VMEM file should be added to the sources of the Vivado project to
# make the Vivado dependency tracking work. However this requires changes to
# fusesoc first.
- ROM_INIT_FILE:
+ BootRomInitFile:
datatype: str
- description: ROM initialization file in vmem hex format
+ description: Boot ROM initialization file in 32 bit vmem hex format
default: "../../../../../build-bin/sw/device/boot_rom/boot_rom_fpga_nexysvideo.32.vmem"
- paramtype: vlogdefine
+ paramtype: vlogparam
# For value definition, please see ip/prim/rtl/prim_pkg.sv
PRIM_DEFAULT_IMPL:
datatype: str
@@ -59,7 +59,7 @@
- files_tcl
toplevel: top_earlgrey_nexysvideo
parameters:
- - ROM_INIT_FILE
+ - BootRomInitFile
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
tools:
vivado: