I have an opentitan like processor which can be simulated with verilator.
For this, there is a top_verilator function like this:
module top_verilator(input logic clk_i, rst_ni);
...
system #(
.SRAMInitFile("/home/user/location/to/vmem")
) u_system (
.clk_i,
.rst_ni
);
endmodule
what i want to do is read the vmem location out of a enviornment variable as multiple people work on the project.
what i tried to do is import getenv like this
import "DPI-C" function string getenv(input string env_name);
as shown here How do I read an environment variable in Verilog/System Verilog?. However, this does not function with recent systemverilog versions, as this gives the error
Constant function may not be DPI import (IEEE 1800-2023 13.4.3)
as described here https://github.com/verilator/verilator/issues/3103. Is there another way to do this?
Parameters need to be determined by the elaboration stage of the compile. DPI's are executed during simulation. So it makes sense a parameter cannot be assigned by a DPI.
If SRAMInitFile
needs to be a parameters, then a workaround would be to assign it with a macro during compile. Depending on the simulator, either
-define VMEM_PATH=${VMEM_PATH}
or +define+VMEM_PATH=${VMEM_PATH}
or -DVMEM_PATH=${VMEM_PATH}
should work as a option during compile (check your simulator manual).
Then your code would look like:
`ifndef VMEM_PATH
// Default path if macro is not defined from compile command line
`define VMEM_PATH /home/user/location/to/vmem
`endif
// Macro to convert input to string
`define STR(S) `"S`"
module top_verilator(input logic clk_i, rst_ni);
...
system #(
.SRAMInitFile(`STR(`VMEM_PATH))
) u_system (
.clk_i,
.rst_ni
);
endmodule
Alternatively, if you can have your testbench backdoor load the values to the memory, then you could to use the getenv()
DPI (assuming you don't need a synthesizable test-bench). If this is an option, then code like this may help:
import "DPI-C" function string getenv(input string env_name);
...
function void load_mem();
string vmem_path = getenv("VMEM_PATH");
$readmemh(vmem_path , tb.dut.top_verilator.system.mem );
endfunction