verilogsystem-verilogfopenmodelsim

$fopen returns the MCD, but the MCD does not work


I'm trying to open a file and write stuff, simple. My implementation is not so simple. I'm using Verilog/SystemVerilog and Modelsim on the Windows OS. My command line in Modelsim is:

set generics "-gLOG_FILENAME=log_file?.txt"
vsim -onfinish stop -noglitch -voptargs=+acc -t ns filetest {*}$generics

The question mark is to try and create a file open error.

My Verilog module is

`include        "./simulationDefs.v"

module filetest
#( // Parameter passed in via the vsim command line
parameter LOG_FILENAME
)();

integer log_handle;

initial
    begin
        $display("log_handle=%h", log_handle); // Print MCD
        `log_file_open(LOG_FILENAME, log_handle); // Open File
        $display("log_handle=%h", log_handle); // Print MCD again
        $fdisplay(log_handle, "Test"); // Try to write to file
    end
endmodule

And my file open macro is:

`define log_file_open(log_filename, log_handle) \
        $display("Attempting to open log file - filename=%s", log_filename); \
        log_handle = $fopen(log_filename, "a"); \
        if (log_handle) $display("Success, log file opened - log_handle=%h", log_handle); \
        else $display("****ERROR LOG FILE NOT OPENED**** filename=%s", log_filename);

And finally my sim output:

# Start time: 15:24:21 on Oct 10,2023
# Loading sv_std.std
# Loading work.filetest
# log_handle=xxxxxxxx
# Attempting to open log file - filename=log_file?.txt
# Success, log file opened - log_handle=80000003
# log_handle=80000003
# ** Warning: (vsim-3535) [FOFIA] - Failed to open file "log_file?.txt" for appending.
# 
# Invalid argument. (errno = EINVAL)    : ft.v(18)
#    Time: 0 ns  Iteration: 0  Instance: /filetest
# ** Error (suppressible): (vsim-PLI-3085) ft.v(18): $fdisplay : Argument 1 is an unknown file descriptor.
#    Time: 0 ns  Iteration: 0  Instance: /filetest

$fopen is getting a valid MCD (multichannel descriptor), but after the macro checks its validity, the simulator outputs a "Failed to open file" error, and the next attempt to write to that file fails due to unknown file descriptor. If I remove the ? so the filename is valid, it all works. What's going on here? Why do I get a valid MCD when in fact the file did not open?


Solution

  • You are trying to open a file in "append" mode, and apparently it succeeds on your file system. I can open a file with a question mark in its name on my linux OS.

    When it can do so, $fopen returns a non-zero file descriptor.

    Refer to IEEE Std 1800-2017, section 21.3.1 Opening and closing files:

    The function $fopen opens the file specified as the filename argument and returns either a 32-bit multichannel descriptor or a 32-bit file descriptor, determined by the absence or presence of the type argument.

    The file descriptor fd is a 32-bit packed array value. The MSB (bit 31) of a fd is reserved and shall always be set

    Since you use the 2-argument form of $fopen, it returns a file descriptor, which is a number whose MSB is always set. This is why your if (log_handle) check is true.

    Note that the way you call $fopen, it does not return a multichannel descriptor (MCD).

    I tried an experiment where I called $fopen with a "r" type (open for reading), and the file descriptor was 0.

    I don't understand why Modelsim returns a non-zero file descriptor (80000003), but then shows you that warning message. That could be a tool bug. You should contact the vendor.