Importing C functions in System Verilog with file-type Argument

5.3k views Asked by At

I am trying to import a C function into a System verilog test bench. The code for the C function is as shown below. I want to pass files as arguments. The function basically reads from one file and writes to another.

    int readmem(int z, FILE *file1, FILE *file2) {
        char data;
        int x;
        int i;
        for(i = 0; i<z;i ++) {
        data = fgetc(file1);
        x = data;
        fputc(x,file2);
        }
        return 0;
    }

Kindly advise me on how I could call this function in a System verilog test bench.

2

There are 2 answers

0
dwikle On

You cannot pass file descriptors between SystemVerilog and C via the DPI, so I don't think it's possible to import the function directly as-is.

If all you really need to do is get the functionality in SystemVerilog, it will be easier to just port it to SystemVerilog rather than trying to import it via the DPI.

Something like this should work (not tested!):

function int readmem(int z, int file1, int file2);
  reg[8:0] data;
  for (int i = 0; i < z; i++) begin
    data = $fgetc(file1);    // Really should break out of the loop if data == EOF ('h1FF)
    $fwrite(file2, "%c", data[7:0]);
  end
  return 0;
endfunction

Then from somewhere else:

int file1 = $fopen("input_file", "r");
int file2 = $fopen("output_file", "w");

readmem(10, file1, file2)

The reason data is declared as 9 bits is to capture an EOF if the end of file is reached. Your original function could run past the end of file1 since you are not checking for EOF.

3
Greg On

SystemVerilog includes DPI (Direct Programming Interface) which lets your SystemVerilog call C functions and can even let your C call SystemVerilog tasks/functions. Check out IEEE std 1800-2009 Section 35 and Annex H & I. There are limitations with data types so check out Annex H.7.4 that for basic SV/C type mapping.

To call C functions in SystemVerilog, simply import it into the desired scope (e.g. module or package)

import "DPI-C" context function C_function_name(/* args */);

To call SystemVerilog from C requires one extra step.

In SV :

export "DPI-C" function SV_function_name; /*no args */

In C :

extern return_type SV_function_name( /* args */);

Depending on your simulator you may need to compile the C code first and reference the object file, or just include the source file in your file list. You make need to add options to your simulator to, so check the manual.

Here are some resources that can help you get started:


Revision: Use a translate wrapper since FILE does does not translate across DPI. C's const char* maps to SystemVerilog's string.

C:

#include <stdlib.h>
#include <stdio.h>
// include for DPI
#include "svdpi.h"
// wrapper
int C2SV_readmem(int z, const char *filename1, const char *filename2) {
    FILE *file1;
    FILE *file2;
    int rtn;
    file1 = fopen(filename1, "r");
    file2 = fopen(filename2, "w");
    if (file1 == NULL) {
        printf("failed to open '%s' for read\n", filename1);
        return 1;
    }
    if (file2 == NULL) {
        printf("failed to open '%s' for write\n", filename2);
        return 1;
    }
    return readmem(z, file1, file2); // call original readmem function
}
/* ... */

SystemVerilog:

module test;
  import "DPI-C" context function int C2SV_readmem(input int z, input string filename1, input string filename2);
int value;
initial begin
  value = C2SV_readmem( 25, "FileIn.txt", "FileOut.txt");
end
endmodule