Jean
Jean

Reputation: 22725

How do I read an environment variable in Verilog/System Verilog?

How do I read an environment variable in Verilog ? (Running on a VCS simulator)

I am trying to accomplish

File=$fopen("$PATH/FileName","r");

$PATH is an environment variable.

Upvotes: 11

Views: 31016

Answers (4)

AnuragChauhan
AnuragChauhan

Reputation: 163

Here I can see all answers, either they are using some DPI Or need some command line arguments. So I am sharing my answer with only SystemVerilog syntax. Answer is not specific to any simulator. But surely it is for Linux environment; for other OS we need to change $system commands.

We need to set this "logPath" system variable using some pre processing script or by simulation script before we start our simulation.

 string myPath;

 initial begin
     //Writing System Variable To A File
     $system("echo ${logPath} > logPath.txt");

     //Opening that file and reading to a string variable
     fh = $fopen ("./logPath.txt", "r");
     void'($fscanf(fh,"%s",myPath));

     //Appending File Name To That Path
     myPath = {myPath,"/note.txt"};

     //Closed and remove this temporary file
     $fclose(fh);
     $system("rm -rf logPath.txt");
      
     //Open a file at the path that you have extracted from System Variable
     //Do whatever you want now 
     fh = $fopen (myPath, "w");
     
     repeat(10) begin
         $fdisplay (fh, "%t %M: Write Line Number =|%0d| ", $time, i);
         i++;
     end

     $fclose(fh);
  end

Upvotes: 0

jclin
jclin

Reputation: 2579

You can simply use SystemVerilog DPI for getting environment. And because getenv is a standard C library for every POSIX platform, so you do not need to implement your own getenv() equivalent function for the function definition again.

Example code in SV.

import "DPI-C" function string getenv(input string env_name);

module top;

  initial begin
    $write("env = %s\n", {getenv("HOME"), "/FileName"});
  end
endmodule

Running

ncverilog -sv dpi.v

or

vcs -sverilog dpi.v

It will show

env = /home/user/FileName

And one more issue in your original question, PATH is a environment for executable search path and concatenate with ":" character. I think it should be an example here, not really "PATH" environment. Otherwise, your fopen file name could be "/bin:/usr/bin:/usr/local/bin/FileName", which is wrong.

Upvotes: 19

shuckc
shuckc

Reputation: 2993

It is often simpler to use the Verilog preprocessor

File = $fopen(`PATH_FILENAME, "r");

Then invoke the simulator from your Makefile/shell script the specifying value to be substituted

$(SIM) -DPATH_FILENAME=\"$PATH/FileName\" blah.v ...

I use this with Icarus' iverilog often, vsim and friends probably support similar.

Quotes are escaped so that they are included in the substituted value, since the preprocessor will not substitute inside a literal value. For instance this combination does not work:

File = $fopen("`PATH_FILENAME", "r");

...

`$(SIM) -DPATH_FILENAME=$PATH/FileName blah.v ...`

Upvotes: 1

Andy
Andy

Reputation: 4866

You can use a simple PLI application to read an environment variable. Here's a sample, without any error checks:

#include <stdlib.h>
#include <string.h>

#include "vpi_user.h"

PLI_INT32 pli_getenv (PLI_BYTE8 * arg) {

    vpiHandle tf_obj = vpi_handle (vpiSysTfCall, NULL);
    vpiHandle arg_iter = vpi_iterate (vpiArgument, tf_obj);

    vpiHandle arg1, arg2;
    arg1 = vpi_scan (arg_iter);
    arg2 = vpi_scan (arg_iter);

    s_vpi_value vi, vo;
    vi.format = vpiStringVal;
    vpi_get_value (arg2, &vi);

    vo.format = vpiStringVal;
    vo.value.str = strdup (getenv (vi.value.str));
    vpi_put_value (arg1, &vo, NULL, vpiNoDelay);

    return 0;
}

The VCS documentation should explain how to link this into the simulator.

Upvotes: 2

Related Questions