Jan Bartels
Jan Bartels

Reputation: 348

How to set Environment Variables with SystemVerilog?

My current project sets an environment variable in a perl module and then later on makes a call from a SystemVerilog file to a function that uses that variable. The requirement is that whatever we added in the perl module is present in the environment variable on time of the call.

The problem however is that something between the perl module and systemverilog call meddles with my variable. I can't figure out what it is and fixing this issue is not pertinent to my project so I just want to set the variable to whatever the perl module sets it to and move on.

There's a handy getenv function in Perl and I am able to use getenv in SV as well. But there doesn't seem to be a setenv. What is the appropriate way to set an environment variable in SV?

Upvotes: 0

Views: 4075

Answers (3)

Amal
Amal

Reputation: 343

Setting environment variables from SV is not very useful unless you are running another executable from SV.

If you want to get environment variables, you can use Verilab's svlib functions:

function automatic string sys_getEnv(string envVar);
function automatic bit sys_hasEnv(string envVar);

Upvotes: 0

Jan Bartels
Jan Bartels

Reputation: 348

Mh... Turns out the answer is trivial but this is the only thread to this question so I'll leave it up in case someone else finds themselve in a similar situation:

SystemVerilog does not have a setenv( ) or getenv( ) function. They're actually implemented from C using the following construct:

module/program foo();

    import "DPI-C" function <return type> foonction(<function arguments>);

endmodule/program; 

Apparently in my case someone had done this for getenv( ) but never setenv ( ). Reason I didn't catch it was because my code in question was included the following way:

**foo.sv**
if(var.bit) begin
    call_function();
    use_environment_variable();
end

**bar.sv**
module bar();
    <do stuff>
    `include foo.sv <-- foo code is copied in after calculations have occured.
endmodule

Trying to import DPI-C in foo.sv will trigger an error because the import will arrive after calculations have taken place. To solve this we need to import in bar.sv like so:

module bar();
   import "DPI-C" function int setenv(string name, string value, int override);
   <do stuff>
   `include foo.sv
endmodule

Upvotes: 0

Jonathan Bromley
Jonathan Bromley

Reputation: 358

Is the perl code invoked from within SystemVerilog using a $system() call? If so, environment changes made by the perl code will definitely NOT propagate back to the SV world, because those changes are made only in the $system() subprocess's environment.

The setenv() system call works for me via SystemVerilog DPI-C in all the tools I use (recent Fedora OS, recent versions of Mentor/Cadence/Synopsys simulators), but there may be some older *nix systems on which it's not available. I used the prototype as given in "man 3 setenv". Looking at discussions on other StackOverflow forums, it seems that using putenv() is not a great idea, especially from the DPI where you have no idea what will happen to the memory used for the DPI string argument. setenv() makes a copy of its argument strings, and should not be at risk from that problem.

It seems to me that if your tool flow isn't correctly propagating environment variables in the way you intend, then you have bigger problems than how to mess with the env from SystemVerilog. I specifically chose NOT to add environment-modifying functions to the svlib utility library, precisely because using the environment is a very bad way to communicate information within a SV simulation. I guess it would make sense if you need to set up an environment for some external program that you would then invoke using a SV $system() call.

Upvotes: 1

Related Questions