$fopen() & friends don't work as expected...
|Assignee:||Wilson Snyder||% Done:|
module testbench; integer infile, outfile, count, a; initial begin infile = $fopen("test.in", "r"); outfile = $fopen("test.out", "w"); $display("count == %d, infile %d, outfile %d", count, infile, outfile); count = $fscanf(infile, "%d\n", a); $display("count == %d, infile %d, outfile %d", count, infile, outfile); $fwrite(outfile, "# a\n"); $fwrite(outfile, "%d\n", a); $fclose(infile); $fclose(outfile); $finish; end endmodule
1 2 3Icarus Verilog output:
./test.vvp count == x, infile -2147483645, outfile -2147483644 count == 1, infile -2147483645, outfile -2147483644test.out generated when simulating using Icarus Verilog:
# a 1Verilator creates empty output file and this command line output:
./test.verilated count == 0, infile 0, outfile 0 count == 0, infile 0, outfile 0
#2 Updated by Holger WÃ¤chtler over 5 years ago
mmh,... why verilator_file_descriptor, why should this be verilator-specific? Using `verilator_file_descriptor yields:
%Error: test.vt:2: Define or directive not defined: `verilator_file_descriptor %Error: test.vt:2: syntax error, unexpected ',', expecting IDENTIFIER %Error: Cannot continue %Error: Command Failed verilator_bin --cc test.vt -Mdir .verilator_obj_dir/test --prefix simulation --exe verilator_main.cpp make: *** [test.verilated] Error 10
#5 Updated by Holger WÃ¤chtler over 5 years ago
mh, this would render the principal idea of using fwrite & friends for portable testcases ridiculous: if one has to touch&modify every testcase for verilator, then one could as well directly use C wrappers instead:
`define fopen(x) $c(...) etc...
Isn't a proper MCD implementation very straightforward? (e.g. maintain an array of refcounted open file descriptors/file name pairs, and verilog-MCDs could be simple indices into this array? Entries are only valid if refcount > 0, fopen increases refcount for already open file name, fclose decrements it).
Or do I miss something that would make this non-trivial?
#6 Updated by Wilson Snyder over 5 years ago
There are some implementation issues, but the main issue is I consider Verilator a synthesis subset simulator, and have no time to deal with Verilogisms (MCD) that simply obscure a nice C equivelent. However if you want to implement it, I'd accept it.
To the main issue, does that fix it nor not?
#9 Updated by Holger WÃ¤chtler over 5 years ago
I took a closer look on the Icarus mcd implementation.verilog/vvp/vpi_mcd.cc is pretty self-containing, applying these changes makes it compile stand-alone:
typedef unsigned int PLI_UINT32; typedef signed int PLI_INT32; //# include "vpi_priv.h"
It defines the following functions, which can be used instead of libc's fopen/fprintf/fclose/fflush:
extern "C" PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) extern "C" char *vpi_mcd_name(PLI_UINT32 mcd) extern "C" PLI_UINT32 vpi_mcd_open(char *name) extern "C" PLI_INT32 extern "C" PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, const char *fmt, ...) extern "C" PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) extern "C" PLI_INT32 vpi_fopen(const char*name, const char*mode) extern "C" FILE *vpi_get_file(PLI_INT32 fd)
Replacing the direct libc calls with vpi_mcd_*() should be sufficient -- and as side-effect a first minimal basis for the VPI core comes in for free. The file is GPL'd, so there should be no licensing issue.