verilator / verilator

Verilator open-source SystemVerilog simulator and lint system
https://verilator.org
GNU Lesser General Public License v3.0
2.2k stars 536 forks source link

$fopen() & friends don't work as expected... #21

Closed veripoolbot closed 15 years ago

veripoolbot commented 15 years ago

Author Name: Holger Wächtler Original Redmine Issue: 21 from https://www.veripool.org Original Date: 2008-07-14 Original Assignee: Wilson Snyder (@wsnyder)


file test.vt:

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

file test.in:

1
2
3

Icarus Verilog output:

./test.vvp
count ==           x, infile -2147483645, outfile -2147483644
count ==           1, infile -2147483645, outfile -2147483644

test.out generated when simulating using Icarus Verilog:

1. a
           1

Verilator creates empty output file and this command line output:

./test.verilated 
count ==           0, infile           0, outfile           0
count ==           0, infile           0, outfile           0
veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Wilson Snyder (@wsnyder) Original Date: 2008-07-14T18:03:55Z


Works for me. Perhaps try

`verilator_file_descriptor infile, outfile;

instead of a integer.

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Holger Wächtler Original Date: 2008-07-14T19:10:41Z


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
veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Holger Wächtler Original Date: 2008-07-14T19:11:51Z


btw, I forgot to submit verilator_main.cpp:

#include "simulation.h"
#include "verilated.h"

int main (int argc, char **argv, char **env)
{
         simulation *sim = new simulation;
         while (!Verilated::gotFinish())
                 sim->eval();
         exit(0);
}
veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Wilson Snyder (@wsnyder) Original Date: 2008-07-14T20:04:37Z


You also need `include "verilated.h"

Verilator doesn't use MCD instead C file descriptors which in C under -m64 are 64 bits. See the docs.

This may not be the problem though...

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Holger Wächtler Original Date: 2008-07-14T20:27:13Z


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?

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Wilson Snyder (@wsnyder) Original Date: 2008-07-14T20:43:13Z


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?

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Holger Wächtler Original Date: 2008-07-14T20:51:57Z


yes, it works, just... as said before. I'll take a look into the MCD issue next days... will you leave the ticket open, or shall I open a new one?

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Wilson Snyder (@wsnyder) Original Date: 2008-07-14T21:16:37Z


There is still a fix here... I updated HEAD to warn if the $fopen etc descriptor isn't 64 bits so these errors can be caught.

For MCD support please file another bug, thanks.

veripoolbot commented 15 years ago

Original Redmine Comment Author Name: Holger Wächtler Original Date: 2008-07-15T10:27:30Z


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 vpimcd*() 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.