I maintain a SystemVerilog library and have never had this issue in 3 years of using this code. I can only assume the user is compiling/running with some special version of VCS.
Compiler version L-2016.06-SP2-7_Full64; Runtime version L-2016.06-SP2-7_Full64
----------------------------------------------------------------
OVM-2.1.2
and the exact error:
Error-[STASKE_NEAFFS] Insufficient number of arguments
my_model/my_source_file.sv, 659
Number of arguments (2) passed to substitute format specifiers in the string
are less than the number of format specifiers.
Please check the call stack shown above and pass number of arguments equal
to number of format specifiers.
is there some way to force $fdisplay to print even if some format specifiers are not "filled in"?
Or some way to tell VCS to ignore these sort of issues?
Currently my only approach to debugging is to try adding a $display of the same string, to see if I noticed anything.
Here's a very similar piece of code that is written for UVM... the actual code that's erroring does the same for an internally-developed OVM RAL layer. The call to $fdisplay near the very end is the equivalent line that's erroring:
task save_uvm_accesses();
uvm_reg_block model_reg_blocks[$];
uvm_reg regs_of_block[$];
uvm_reg_field fields_of_reg[$];
uvm_reg sub_block;
uvm_reg_file uvm_file;
uvm_reg_backdoor backdoor_access;
uvm_reg_frontdoor front_access;
int fd;
string output_file_name = "UVM_info.csv";
string current_line="";
string frontdoors = "";
string fieldnames = "";
reg_model.get_blocks(model_reg_blocks);
fd = $fopen({output_file_name}, "w");
$fdisplay(fd,"reg_name,reg_full_name,unique_file_name,reg_file,backdoor_access,front_access,access methods,fieldnames");
$display("**************** UVM dump regs *******************");
// go through each sub-block
foreach (model_reg_blocks[sub_block]) begin
// go through each reg in sub-block
regs_of_block = {};
model_reg_blocks[sub_block].get_registers(regs_of_block);
foreach (regs_of_block[rreg]) begin
uvm_reg_map reg_map[$];
frontdoors = "\"";
fieldnames = "\"";
fields_of_reg = {};
current_line ="";
uvm_file = regs_of_block[rreg].get_regfile();
regs_of_block[rreg].get_maps(reg_map);
//backdoor_access = regs_of_block[rreg].get_backdoor(1);
backdoor_access = model_reg_blocks[sub_block].get_backdoor(1);
// enumerate any available frontdoor accesses
foreach (reg_map[map]) begin
front_access = regs_of_block[rreg].get_frontdoor(reg_map[map]);
if(front_access != null)
frontdoors = {frontdoors, $sformatf("%s,", front_access.get_name())};
end
frontdoors = {frontdoors, "\""};
regs_of_block[rreg].get_fields(fields_of_reg);
foreach (fields_of_reg[current_fieldname]) begin
fieldnames = {fieldnames, $sformatf("%s, ", fields_of_reg[current_fieldname].get_name())};
end
fieldnames = {fieldnames, "\""};
// current_line = {current_line, $sformatf("%s,", rreg}; r
current_line = {current_line, $sformatf("%s,", regs_of_block[rreg].get_name())};
current_line = {current_line, $sformatf("%s,", regs_of_block[rreg].get_full_name())};
current_line = {current_line, $sformatf("%s,", model_reg_blocks[sub_block].get_name())};
if(uvm_file == null)
current_line = {current_line, "null,"};
else
current_line = {current_line, $sformatf("%s,", uvm_file.get_name())};
if(backdoor_access == null)
current_line = {current_line, "null,"};
else
current_line = {current_line, $sformatf("%s,", backdoor_access.get_name())};
current_line = {current_line, $sformatf("%s,", frontdoors)};
current_line = {current_line,"backdoor,"};
current_line = {current_line, fieldnames};
$fdisplay(fd, current_line);
end
end
$fclose(fd);
endtask: save_uvm_accesses
I ended up just changing the final fdisplay line from:
$fdisplay(fd, current_line);to
$fdisplay(fd, "%s", current_line);