Note that Synopsys' VCS 6.1, NC-Verilog 3.3, and MTI's ModelSim 5.5 offer native support for the IEEE-1364 2001 standard. Verilog-XL does not support these tasks except through this PLI application.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The Verilog language has a rich set of system functions to write files ($fdisplay, $fwrite, etc.) but only reads files with a single, fixed format ($readmem). In the past if you wanted to read a file that was not in $readmem format, you would have to learn the Programming Language Interface (PLI) and the C language, write C code to read the file and pass values into Verilog, then debug the combined C and Verilog code. In addition, the Verilog is limited to 32 open files at a time.
However, using the new file I/O system functions you can perform your file I/O directly from Verilog. You can write Verilog HDL to:
In V2K, there is a single $fopen for both multi-channel descriptors
(MCD) and file descriptors (FD). Whether an FD or MCD is produced
is indicated by the presence of a mode string added to $fopen in V2K:
file = $fopen("filename", "w");
// FD
file = $fopen("filename");
// MCD
Fileio supports the V2K $fopen format under a package compilation switch but that then blocks any use of MCDs since it hides the builtin $fopen.
In V2K, there is a single $fclose for both MCDs and FDs. It does not return a status. Errors can be determined by using $ferror.
Fileio supports the V2K $fclose format under a package compilation switch but that then blocks any use of MCDs since it hides the builtin $fclose.
V2K does not support a maximum count "n" of characters to read. Input in V2K always terminates at end of line and then string assignment to the target is done.
Fileio's $gets is not directly supported in Verilog 2001. The
operation can be done by using:
$fgets(string, 'h8000_0000);
that makes use of the reserved FD for stdin.
integer file; file = $fopenr("filename"); file = $fopenw("filename"); file = $fopena("filename");The function $fopenr opens an existing file for reading. $fopenw opens a new file for writing, and $fopena opens a new file for writing where any data will be appended to the end of the file. The file name can be either a quoted string or a reg holding the file name. If the file was successfully opened, it returns an integer containing the file number (1..MAX_FILES) or NULL (0) if there was an error. Note that these functions are not the same as the built-in system function $fopen which opens a file for writing by $fdisplay. The files are opened in C with 'rb', 'wb', and 'ab' which allows reading and writing binary data on the PC. The 'b' is ignored on Unix.
integer file, r; r = $fcloser(file); r = $fclosew(file);The function $fcloser closes a file for input. $fclosew closes a file for output. It returns EOF if there was an error, otherwise 0. Note that these are not the same as $fclose which closes files for writing.
integer file; reg eof; eof = $feof(file);The function $feof tests for end of file. If an end-of-file has been reached while reading from the file, a non-zero value is returned; otherwise, a 0 is returned.
The function $ferror returns the error status of a file. If an error has occurred while reading from a file, $ferror returns a non-zero value, else 0. The error value is returned once, then reset to 0.
integer file, char; char = $fgetc(file); char = $getc();The function $fgetc reads a single character from the specified file and returns it. If the end-of-file is reached, $fgetc returns EOF. You should use a 32-bit register to hold the result from $fgetc to tell the difference between the character with the value 255 and EOF. $getc reads from stdin.
integer file; reg [7:0] char, r; r = $ungetc(char, file);The function $ungetc pushes the character back into the file stream. That character will be the next read by $fgetc. It returns the character if it was successfully pushed back or EOF if it fails.
Note that since there is no $ungetc for stdin in C, there will not be one in the file I/O package.
integer stream, r, char; r = $fputc(stream, char);The function $fputc writes a single character to the specified file. It returns EOF if there was an error, 0 otherwise.
integer file, n, r; reg [n*8-1:0] string; r = $fgets(string, n, file); r = $gets(string);The function $fgets reads a string from the file. Characters are read from the file into string until a newline is seen, end-of-file is reached, or n-1 characters have been read. If the end-of-file is encountered, $fgets returns a 0 and string is unchanged; otherwise, $fgets returns a 1. $gets reads from stdin.
The function $fgets has a string size limit of 1024 bytes. You can increase this by changing the constant MAX_STRING_SIZE.
The function $gets is no longer supported by default in fileio v3.4. If you want to use it, you must compile fileio.c with -DGETS. This is because some C compilers will give an error message when compiling fileio.c:
fileio.o: In function `fileio_gets_call`: fileio.o: the gets function is dangerous and should not be usedYou can either ignore this message, or stop using -DGETS to remove the gets function call from fileio.c.
integer file, count; count = $fscanf(file, format, args); count = $sscanf(string, format, args); count = $scanf(format, args);The function $fscanf parses formatted text from the file according to the format and writes the results to args. $sscanf parses formatted text from a string. $scanf parses formated text from stdin. See a C reference manual for detailed information on fscanf, plus examples later in this note.
The format can be either a string constant or a reg. It can contain:
Formatting & padding is closer to Verilog than C. For example, %x of 16'h24 is '0024', not '24', and %0x returns '24', not '0024'.
$fscanf, $sscanf, and $scanf return the number of successful assignments performed. If you do not want a return value from these routines, compile fileio.c (and veriuser.c for Cadence users) with -Dscanf_task. VCS users should switch from fileio.tab to fileio_task.tab
integer file, position; position = $ftell(file);The function $ftell returns the position in the file for use by $fseek. If there is an error, it returns a -1.
`define SEEK_SET 0 `define SEEK_CUR 1 `define SEEK_END 2 integer file, offset, position, r; r = $fseek(file, 0, `SEEK_SET); /* Beginning */ r = $fseek(file, 0, `SEEK_CUR); /* No effect */ r = $fseek(file, 0, `SEEK_END); /* End of file */ r = $fseek(file, position, `SEEK_SET); /* Previous loc */The function $fseek allows random access in a file. You can position at the beginning or end of a file, or use the position returned from $ftell.
integer r, file, start, count; reg [15:0] mem[0:10], r16; r = $fread(file, mem[0], start, count); r = $fread(file, r16);The function $fread reads a binary file into a Verilog memory. The first argument is either a register or a memory name, which must have a subscript, though the value of the subscript is ignored. start and count are optional.
By default $fread will store data in the first data location through the final location. For the memory up[10:20], the first location loaded would be up[10], then up[11]. For down[20:10], the first location would be down[10], then down[11].
start and count are ignored if $fread storing data in a reg instead of a memory. No warning is printed if the file contains more data than will fit in the memory.
start is the word offset from the lowest element in the memory. For start = 2 and the memory up[10:20], the first data would be loaded at up[12]. For the memory down[20:10] , the first location loaded would be down[12], then down[13].
$fread returns the number of elements read from the file, If $fread terminates early because of an error, it will return the number of elements successfully read. $feof can be used to determine whether the end-of-file was reached during $fread.
The data in the file is broken into bytes according to the width of the memory. An 8-bit wide memory takes one byte per location, while a 9-bit wide memory takes 2 bytes. Care should be taken when using memories with widths not evenly divisible by 8 as there may be gaps in the data in the memory vs. data in the file.
The $fread system task only works with NC-Verilog if you use the -MEMPACK switch as in:
ncverilog +ncvlogargs+-NOMEMPACK foo.v
integer file, r, a, b; reg [80*8:1] string; file = $fopenw("output.log"); r = $sformat(string, "Formatted %d %x", a, b); r = $sprintf(string, "Formatted %d %x", a, b); r = $fprintf(file, "Formatted %d %x", a, b);The functions $sformat and $sprintf writes a formatted string into a Verilog register. The two functions are identical. $fprintf writes a formatted string to a file. It has most, but not the formatting capabilites of C stdio package. The first argument is a register to receive the formatted data, and the second is a format string. Additional arguments may be included.
The supported formats include b, c, d, e, f, g, h, m, o, r, s, and x. %t for printing formatted time is NOT supported yet.
integer file, r; file = $fopenw("output.log"); r = $fflush(file);The function $fflush(stream) causes any buffered data waiting to be written for the named stream to be written to that file. If the stream is 0, all files open for writing are flushed.
while (c=fgetc(stream) != EOF) { <process input> }turns into the Verilog code:
c = $fgetc(file); while (c !== `EOF) begin <process input> c = $fgetc(file); end
The maximum number of files (MAX_FILES) is set in the C code to 12. The maximum string size is 1000 characters. There is no known limit to the number of conversion operators in $fscanf or $sscanf.
This is the pattern file - read_pattern.pat , included in the examples directory:
// This is a pattern file // time bin dec hex 10: 001 1 1 20.0: 010 20 020 50.02: 111 5 FFF 62.345: 100 4 DEADBEEF 75.789: XXX 2 ZzZzZzZzNote that the binary and hexadecimal values have X and Z values, but these are not allowed in the decimal values. You can use white space when formatting your file to make it more readable. Lastly, any line beginning with a / is treated as a comment.
The module read_pattern.v reads the time for the next pattern from an ASCII file. It then waits until the absolute time specified in the input file, and reads the new values for the input signals (bin, dec, hex). The time in the file is a real value and, when used in a delay, is rounded according to the timescale directive. Thus the time 75.789 is rounded to 75.79 ns.
`timescale 1ns / 10 ps `define EOF 32'hFFFF_FFFF `define NULL 0 `define MAX_LINE_LENGTH 1000 module read_pattern; integer file, c, r; reg [3:0] bin; reg [31:0] dec, hex; real real_time; reg [8*`MAX_LINE_LENGTH:0] line; /* Line of text read from file */ initial begin : file_block $timeformat(-9, 3, "ns", 6); $display("time bin decimal hex"); file = $fopenr("read_pattern.pat"); if (file == `NULL) // If error opening file disable file_block; // Just quit c = $fgetc(file); while (c != `EOF) begin /* Check the first character for comment */ if (c == "/") r = $fgets(line, `MAX_LINE_LENGTH, file); else begin // Push the character back to the file then read the next time r = $ungetc(c, file); r = $fscanf(file," %f:\n", real_time); // Wait until the absolute time in the file, then read stimulus if ($realtime > real_time) $display("Error - absolute time in file is out of order - %t", real_time); else #(real_time - $realtime) r = $fscanf(file," %b %d %h\n",bin,dec,hex); end // if c else c = $fgetc(file); end // while not EOF r = $fcloser(file); end // initial // Display changes to the signals always @(bin or dec or hex) $display("%t %b %d %h", $realtime, bin, dec, hex); endmodule // read_pattern
`define EOF 32'hFFFF_FFFF `define NULL 0 `define MAX_LINE_LENGTH 1000 module compare; integer file, r; reg a, b, expect, clock; wire out; reg [`MAX_LINE_LENGTH*8:1]; parameter cycle = 20; initial begin : file_block $display("Time Stim Expect Output"); clock = 0; file = $fopenr("compare.pat"); if (file == `NULL) disable file_block; r = $fgets(line, MAX_LINE_LENGTH, file); // Skip comments r = $fgets(line, MAX_LINE_LENGTH, file); while (!$feof(file)) begin // Wait until rising clock, read stimulus @(posedge clock) r = $fscanf(file, " %b %b %b\n", a, b, expect); // Wait just before the end of cycle to do compare #(cycle - 1) $display("%d %b %b %b %b", $stime, a, b, expect, out); $strobe_compare(expect, out); end // while not EOF r = $fcloser(file); $stop; end // initial always #(cycle / 2) clock = !clock; // Clock generator and #4 (out, a, b); // Circuit under test endmodule // compare
`define EOF 32'hFFFF_FFFF `define NULL 0 module script; integer file, r; reg [80*8:1] command; reg [31:0] addr, data; initial begin : file_block clock = 0; file = $fopenr("script.txt"); if (file == `NULL) disable file_block; while (!$feof(file)) begin r = $fscanf(file, " %s %h %h \n", command, addr, data); case (command) "read": $display("READ mem[%h], expect = %h", addr, data); "write": $display("WRITE mem[%h] = %h", addr, data); default: $display("Unknown command '%0s'", command); endcase end // while not EOF r = $fcloser(file); end // initial endmodule // scriptThe file script.txt is the script read by the above model:
read 9 0 write 300a feedface read 2FF xxxxxxxx bad
This is the file load_mem.v
`define EOF 32'HFFFF_FFFF `define MEM_SIZE 200_000 module load_mem; integer file, i; reg [7:0] mem[0:`MEM_SIZE]; reg [80*8:1] file_name; initial begin file_name = "data.bin"; file = $fopenr(file_name); i = $fread(file, mem[0]); $display("Loaded %0d entries \n", i); i = $fcloser(file); $stop; end endmodule // load_memThe file data.bin contains the 200 binary values 0 to 199. You can look at the program data.c which generated the file. To dump out the binary file in Unix use the command od data.bin
On the DEC/Alpha use:
cc -c fileio.c -I$VCS_HOME/`vcs -platform`/lib -taso -xtaso_short
On Windows, use the Microsoft C++ compiler included with VCS:
cl -c -Zp4 fileio.c
The -Zp4 switch tells the compiler to use longword alignment. Note that the compiler produces fileio.obj, not fileio.o. In the example below, if you compile on Windows, change the file extension.
Note that the system variable "include" must contain a reference
to the VCS include files, such as:
c:\vcs422\Windows_NT\lib
% vcs load_mem.v fileio.o -P fileio.tab -R Chronologic VCS (TM) Version 5.1 -- Tue Jan 11 09:00:41 2000 Copyright (c) 1991-2000 by Synopsys Inc. ALL RIGHTS RESERVED This program is proprietary and confidential information of Synopsys Inc. and may be used and disclosed only as authorized in a license agreement controlling such use and disclosure. Compiling load_mem.v Top Level Modules: load_mem ( cd csrc ; make -f Makefile DEFAULT_RUNTIME=TRUE product ) ../simv up to date Chronologic VCS simulator copyright 1991-2000 Contains Synopsys proprietary information. Compiler version 5.1; Runtime version 5.1; Jan 11 09:00 2000 Loaded 200 entries $stop at time 0 Scope: load_mem File: load_mem.v Line: 13 cli_0 >
Note: this information is based on an older version of Verilog-XL. Send me an update if you have one.
To use the file I/O system functions with Verilog-XL, you will need to:
Running vconfig |
|
Prompt issued from vconfig : |
You type: |
Please enter the name of the output script | cr_vlog |
Please choose a target | 1 Stand Alone |
Please choose how to link in PLI application | 4 Static with user PLI application |
What do you want to name the Verilog-XL target? | verilog_fileio |
Do you want to compile for the SimVision environment? | n |
Do you want to include GR_WAVES | n |
Do you want to include the Simulation History Manager | n |
The LAI interface in no longer supported | n |
Do you want to include the LMSI HARDWARE MODELER interface software in this executable? | return |
Do you want to include the Verilog Mixed-Signal interface software in this executable? | return |
Do you want to include the Standard Delay File Annotator in this executable? | return |
The user template file 'veriuser.c' must always be included in the link statement. What is the path name of this file? | ./veriuser.c |
Please list any other user files to be linked with this Verilog-XL ... terminating with a single '.' | ./fileio.c
. (period) |
cc -Dverilogxl -o verilog_read $1 $2 -g \ ... fileio.c \ ...
% ./verilog_read load_mem.v VERILOG-XL 2.1.12 Jun 21, 1995 14:55:32 Copyright (c) 2000 Cadence Design Systems, Inc. All Rights Reserved. . . . <<< Routines for file read linked in >> Compiling source file "load_mem.v" Highest level modules: load_mem Loaded 200 entries L13 "load_mem.v": $stop at simulation time 0 Type ? for help C1>
Create fileio.so, the shareable object:
make MTI=1 fileio.soor:
gcc -c -g fileio.c -DMTI -I$MTI_PATH/include ld -G -Bdynamic -o fileio.so fileio.oCompile and run your design with:
rm -rf work vlib work vlog test1.v # Your Verilog code here vsim -c test1 -pli fileio.so -do "run -all"You might have to set the environment variable LD_LIBRARY_PATH to point to the directory where fileio.so resides.
NC-Verilog does not support the tf_nodeinfo PLI call which is used in several places by fileio.c. If you want to use these system functions with NC-Verilog, compile fileio.c with the -DNCVerilog switch. This will disable the $fread routine, and passing some strings using a register, such as the format string to $fscanf.
If you have any information on linking with NC-Verilog, please pass it on to me!
You can use makefile_fileio_ncv to compile and link with NC-Verilog. I make no promises!