SystemVerilog $fdisplay 不会打印看起来像格式说明符的字符串

SystemVerilog $fdisplay won't print strings that appear like format specifiers

我维护一个 SystemVerilog 库,在使用此代码的 3 年中从未遇到过这个问题。 我只能假设用户 compiling/running 使用某些特殊版本的 VCS。

Compiler version L-2016.06-SP2-7_Full64; Runtime version L-2016.06-SP2-7_Full64
----------------------------------------------------------------
OVM-2.1.2

以及准确的错误:

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.

是否有某种方法可以强制 $fdisplay 在某些格式说明符未“填写”的情况下进行打印? 或者有什么方法可以让 VCS 忽略这些问题?

目前我唯一的调试方法是尝试添加一个 $display 相同的字符串,看看我是否注意到了什么。

这是为 UVM 编写的一段非常相似 的代码...错误的实际代码对内部开发的 OVM RAL 层执行相同的操作。在接近尾声时调用 $fdisplay 是等效的错误行:

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

我最后只是更改了最后的 fdisplay 行:

$fdisplay(fd, current_line);

$fdisplay(fd, "%s", current_line);