I am working, with Hans, on integrating a C++ model using UVM Connect into a SystemVerilog simulation. The model requires some static configuration at start of simulation. I decided to pass SV simulation command-line arguments (+plusargs), and send them over to SystemC.
Going over the documentation, command API chapter and the config db seemed what I need. I tried sending over a string list to the other side using UVMC_set_config_int (for length of the list), and multiple UVMC_set_config_string for each element of the list.
First I noticed, documentation mentions uvmc_cmd_init()
which does not really exist! I switched that to uvmc_init()
and things started working.
Second, I am not sure if I am using things as they should not be used that way or not. Documentation mentions that command API is intended to control the SV side from SC side. My use case is sending config data from SV to SC. The documentation does not mention UVMC_* (uppercase functions). I used the upper case ones on the SV side and lowercase ones (uvmc_*) on SC side.
I observed a few issues and I wonder what I am doing wrong.
I tried UVMC_set_config_int/UVMC_get_config_int on SV side, but the get function fails and returns 0. I also used UVM_CONFIG_DB_TRACE
and UVMC_COMMAND_TRACE
to debug and for this code:
string args[] = {"--arg1", "--arg2", "--arg3"};
bit b;
longint unsigned argc = args.size();
UVMC_set_config_int("", "TEST", "argc", argc);
b = UVMC_get_config_int("", "TEST", "argc", argc);
$display($sformatf("argc: %0d --> (%0d)", argc, b));
I see:
UVM_INFO uvmc_commands.sv(638) @ 0: reporter [TRACE/UVMC_CMD/SET_CFG_INT] contxt='' inst_name='TEST' field_name='argc' value=3
UVM_INFO uvmc_commands.sv(781) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_INT] contxt= inst_name=TEST field_name=argc
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.argc' (type logic signed[4095:0]) read by = null (failed lookup)
argc: 0 --> (0)
Then I send the string elements:
$display("args:");
for (int i = 0; i < args.size(); i++) begin
bit b;
string field;
string str;
$display(" [%0d]: %s", i, args[i]);
field = $sformatf("args_%0d", i);
UVMC_set_config_string("", "TEST", field, args[i]);
b = UVMC_get_config_string("", "TEST", field, str);
$display("--> %s - arg[%0d]: '%s' --> %0d", field, i, str, b);
end
And I see:
args:
[0]: --arg1
UVM_INFO uvmc_commands.sv(680) @ 0: reporter [TRACE/UVMC_CMD/SET_CFG_STR] contxt='' inst_name='TEST' field_name='args_0' value='49672931665713'
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_0
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_0' (type string) read by = null (failed lookup)
--> args_0 - arg[0]: '' --> 0
[1]: --arg2
UVM_INFO uvmc_commands.sv(680) @ 0: reporter [TRACE/UVMC_CMD/SET_CFG_STR] contxt='' inst_name='TEST' field_name='args_1' value='49672931665714'
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_1
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_1' (type string) read by = null (failed lookup)
--> args_1 - arg[1]: '' --> 0
[2]: --arg3
UVM_INFO uvmc_commands.sv(680) @ 0: reporter [TRACE/UVMC_CMD/SET_CFG_STR] contxt='' inst_name='TEST' field_name='args_2' value='49672931665715'
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_2
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_2' (type string) read by = null (failed lookup)
--> args_2 - arg[2]: '' --> 0
For some reason, I see another set of reads (get)! The argc
is correct, and I see multiple TEST.args_2
reads!
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'TEST.argc' (type logic signed[4095:0]) set by = (logic signed[4095:0]) 3
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'TEST.args_2' (type string) set by = (string) "--arg3"
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'TEST.args_2' (type string) set by = (string) "--arg3"
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/SET] Configuration 'TEST.args_2' (type string) set by = (string) "--arg3"
Interestingly, on the SV side, when I readback (get) what was written (set) into the config db using UVMC_*, I see failed lookup
!
On the SC side I have:
std::cout << std::string(120, '-') << std::endl;
if ( uvmc_get_config_int("", "TEST", "argc", argc) )
std::cout << "SC : argc: " << argc << std::endl;
else
UVMC_ERROR("GET_CFG_INT_FAIL", "get_config_int failed", name());
args = std::vector<std::string>(argc);
for ( size_t i = 0; i < argc; i++ )
{
std::string field = "args_" + std::to_string(i);
uvmc_get_config_string("", "TEST", field.c_str(), args[i]);
std::cout << "SC : args[" << i << "]: " << args[i] << std::endl;
}
I see:
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.argc' (type logic signed[4095:0]) read by = (logic signed[4095:0]) 3
SC : argc: 3
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_0
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_0' (type string) read by = null (failed lookup)
SC : args[0]: ''
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_1
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_1' (type string) read by = null (failed lookup)
SC : args[1]: ''
UVM_INFO uvmc_commands.sv(819) @ 0: reporter [TRACE/UVMC_CMD/GET_CFG_STR] contxt= inst_name=TEST field_name=args_2
UVM_INFO uvm_resource_db.svh(121) @ 0: reporter [CFGDB/GET] Configuration 'TEST.args_2' (type string) read by = (string) "--arg3"
SC : args[2]: '--arg3'
Again, argc
value is correct, even though the get
on SV side fails.
The TEST.args_0
and TEST.args_1
fail and the last TEST.args_2
has correct value.
It is not clear if my use case is not correct and this mode of operation was never designed to work this way or something else.
Or maybe I should use generic payload instead of config db for this case as well.
I can pack up a small testcase if that helps. Any help or guidance is appreciated for this static configuration setup.
Cheers,
– Amal