Get current process id in SystemVerilog - system-verilog

To get process_id in Java, we use ProcessHandle.current().pid();,. Jow we can get current-process-id in Systemverilog?

Use the builtin process class
begin
process pid;
pid = process::self();
...
end
See section 9.7 Fine-grain process control in the IEEE 1800-2017 SystemVerilog LRM

SystemVerilog does not have any facility to get 'pid' of its process. It provides an object to do limited process control in a system-independent way. You can check lrm 9.7 for available controls.
However, it is possible to get pid using DPI or PLI functions, using 'c' calls. But implementation could be system and simulator dependent.
For example, the following works with VCS on linux:
module pid();
import "DPI-C" function int getpid();
initial begin
$display("%d", getpid());
end
endmodule // pid
In the above getpid() is a standard libc function which is callable from the simulator. It also seems to work with vcs, mentor, and cadence in EDA playground, but fails with aldec.
Since the function is globally defined, there is no need to define a dpi function body at least for the three simulators. However, you might need to define a different dpi function with a 'c' body to make it more portable.

Related

Is it allowed to use #1step as a procedural delay?

I am not sure if the LRM is clear about the #1step usage, but I have a case of creating a smallest possible delay a simulator could detect. So, I have written the following code:
virtual task drive_signal();
// Initialise mysignal to a value of '1'.
m_vif.mysignal= 1;
#1step; // Advance with 1 time step
m_vif.mysignal= 0;
#m_cfg.configured_delay; //Delay by configured value
m_vif.mysignal= 1;
endtask
Is this a valid way to do so?
I did however use #0 instead of #1step but it did not create any runtime delay.
This is currently an open issue in the IEEE 1800-2017 SystemVerilog LRM, but the intent was not to allow it.
The use of simple delays like #0 or #1 is a bad practice as they increase the potential for race conditions. Since you tagged this question with UVM, the use of any delays in a driver is highly discouraged and instead you should use synchronous clock edge in an interface or top-level testbench.

Can someone explain the control flow of modules in System Verilog

I know how to link modules but could someone explain the flow of calling the modules to be used when I want it to be used.
Like have a state machine and depending on the state I can call a module to activate, or like if I need to repeat a process how to go back to a module earlier in a state machine.
again I get the instantiating part like this
wire clk;
wire sig;
wire out;
A a(clk, sig, topout);
B b(clk, sig);
endmodule
but can someone explain how to call modules and how the control flow works in general for them?
(I am new to HDLs so I appreciate any help)
Verilog is a language specifically developed to simulate behavior of hardware. Hardware is a set of transistors and other elements which always statically presented and function in parallel. Functioning of such elements could be enabled or disabled, but the hardware is still present.
Verilog is similar to the hardware in the sense that all its elements are always present, intended for parallel functioning.
The basic functional elements of Verilog are gates, primitives and procedural blocks (i.e., always blocks). Those blocks are connected by wires.
All those elements are then grouped in modules. Modules are used to create logical partitioning of the hardware mode. They cannot be 'called'. They can be instantiated in a hierarchical manner to describe a logical structure of the model. They cannot be instantiated conditionally since they represent pieces of hardware. Different module instances are connected via wires to express hierarchical connectivity between lower-level elements.
There is one exception however, the contents of an always block is pure software. It describes an algorithmic behavior of it and as such, software flow constructs are allowed inside always block (specific considerations must be used to make it synthesizable).
As it comes to simulation, Verilog implements an event-driven simulation mode which is intended to mimic parallel execution of hardware. In other words, a Verilog low level primitive (gate or always block) is executed only if at least one of its inputs changes.
The only flow control which is usually used in such models is a sequence of input events and clocks. The latter are used to synchronize results of multiple parallel operations and to organize pipes or other sequential functions.
As I mentioned before, hardware elements can be enabled/disabled by different methods, so the only further control you can use by implementing such methods in your hardware description. For example, all hardware inside a particular module can be turned off by disabling clock signal which the module uses. There could be specific enable/disable signals on wires or in registers, and so on.
Now to your question: your code defines hierarchical instantiation of a couple of modules.
module top(out);
output wire out;
wire clk;
wire sig;
A a(clk, sig, out);
B b(clk, sig);
endmodule
Module 'top' (missing in your example) contains instances of two other modules, A and B. A and B are module definitions. They are instantiated as corresponding instances 'a' and 'b'. The instances are connected by signals 'clk', which is probably a clock signal, some signal 'sig' which is probably an output of one of the modules and input in another. 'out' is output of module top, which is probably connected to another module or an element in a higher level of hierarchy, not shown here.
The flow control in some sense is defined by the input/output relation between modules 'A' and 'B'. For example:
module A(input clk, input sig, output out);
assign out = sig;
...
endmodule
module B(input clk, output sig);
always#(posedge clk) sig <= some-new-value;
...
endmodule
However, in general it is defined by the input/output relation of the internal elements inside module (always blocks in the above example). input/output at the module port level is mostly used for semantic checking.
In the event-driven simulation it does not matter hardware of which module is executed first. However as soon as the value of the 'sig' changes in always#(posedge clk) of module 'B', simulation will cause hardware in module 'A' (the assign statement to be evaluated (or re-evaluated). This is the only way you can express a sequence in the flow at this level. Same as in hardware.
If you are like me you are looking at Verilog with the background of a software programmer. Confident in the idea that a program executes linearly. You think of ordered execution. Line 1 before line 2...
Verilog at its heart wants to execute all the lines simultaneously. All the time.
This is a very parallel way to program and until you get it, you will struggle to think the right way about it. It is not how normal software works. (I recall it took me weeks to get my head around it.)
You can prefix blocks of simultaneous execution with conditions, which are saying execute the lines in this block when the condition is true. All the time the condition is true. One class of such conditions is the rising edge of a clock: always #(posedge clk). Using this leads to a block of code that execute once every time the clk ticks (up).
Modules are not like subroutines. They are more like C macros - they effectively inline blocks of code where you place them. These blocks of code execute all the time any conditions that apply to them are true. Typically you conditionalize the internals of a module on the state of the module arguments (or internal register state). It is the connectivity of the modules through the shared arguments that ensures the logic of a system works together.

How to change verbosity of uvm components after certain condition

I am trying to change the UVM verbosity of the simulation after satisfying certain conditions. Verbosity options of different components are passing through the command line as +uvm_set_verbosity. Once the conditions are satisfied, then the simulations should run with the the command line +uvm_set_verbosity option. Till then simulation runs with low verbosity for all components.
Looking through the UVM library code, it appears that there is a function called m_set_cl_msg_args(). This function calls three other functions that appear to consume the command line arguments like: +uvm_set_verbosity, +uvm_set_action, +uvm_set_severity.
So what I did was get the uvm_root instance from the uvm_coreservice singleton, and then use the get_children() function from uvm_component class to recursively get a queue of all of the uvm_components in the simulation. Then call the m_set_cl_msg_args() function on all of the components.
My code looks like:
begin
uvm_root r;
uvm_coreservice_t cs_t;
uvm_component array_uvm[$];
cs_t = uvm_coreservice_t::get();
r = cs_t.get_root();
r.get_children(array_uvm);
foreach(array_uvm[i])
array_uvm[i].m_set_cl_msg_args();
end
Even though this code compiles properly, But this is not changing verbosity. Any idea ?
Moreover I am able to print all the components in array_uvm. So I am guessing
array_uvm[i].m_set_cl_msg_args();
this as a wrong call.
Anyone have any other suggestion to change verbosity during run time.
You should never use functions in the UVM that are not documented in the language reference manual. They can (and do) change in any revision. I'm guessing +uvm_set_verbosity only works at time 0 by default.
There is already a function to do what you want
umm_top.set_report_verbosity_level_hier()
I suggest using +UVM_VERBOSITY=UVM_LOW to start your test, and then define your own switch for activating the conditional setting.
If you want a specific component, use component_h.set_report_verbosity_level() (add the _hier to set all its children)
You can use the UVM's command line processor get_arg_values() method to specify the name of the component(s) you want to set, and then use umm_top.find() to get a handle to the component.

Understanding higher level call to systemcalls

I am going through the book by Galvin on OS . There is a section at the end of chapter 2 where the author writes about "adding a system call " to the kernel.
He describes how using asmlinkage we can create a file containing a function and make it qualify as a system call . But in the next part about how to call the system call he writes the following :
" Unfortunately, these are low-level operations that cannot be performed using C language statements and instead require assembly instructions. Fortunately, Linux provides macros for instantiating wrapper functions that contain the appropriate assembly instructions. For instance, the following C program uses the _syscallO() macro to invoke the newly defined system call:
Basically , I want to understand how syscall() function generally works . Now , what I understand by Macros is a system for text substitution .
(Please correct me If I am wrong)
How does a macro call an assembly language instruction ?
Is it so that syscallO() when compiled is translated into the address(op code) of the instruction to execute a trap ?(But this somehow doesn't fit with concept or definition of macros that I have )
What exactly are the wrapper functions that are contained inside and are they also written in assembly language ?
Suppose , I want to create a function of my own which performs the system call then what are the things that I need to do . Do , I need to compile it to generate the machine code for performing Trap instructions ?
Man, you have to pay $156 dollars to by the thing, then you actually have to read it. You could probably get an VMS Internals and Data Structures book for under $30.
That said, let me try to translate that gibberish into English.
System calls do not use the same kind of linkage (i.e. method of passing parameters and calling functions) that other functions use.
Rather than executing a call instruction of some kind, to execute a system service, you trigger an exception (which in Intel is bizarrely called an interrupt).
The CPU expects the operating system to create a DISPATCH TABLE and store its location and size in a special hardware register(s). The dispatch table is an array of pointers to handlers for exceptions and interrupts.
Exceptions and interrupts have numbers so, when exception or interrupt number #1 occurs, the CPU invokes the 2d exception handler (not #0, but #1) in the dispatch table in kernel mode.
What exactly are the wrapper functions that are contained inside and are they also written in assembly language ?
The operating system devotes usually one (but sometimes more) exceptions to system services. You need to do some thing like this in assembly language to invoke a system service:
INT $80 ; Explicitly trigger exception 80h
Because you have to execute a specific instruction, this has to be one in assembly language. Maybe your C compiler can do assembly language in line to call system service like that. But even if it could, it would be a royal PITA to have to do it each time you wanted to call a system service.
Plus I have not filled in all the details here (only the actual call to the system service). Normally, when you call functions in C (or whatever), the arguments are pushed on the program stack. Because the stack usually changes when you enter kernel mode, arguments to system calls need to be stored in registers.
PLUS you need to identify what system service you want to execute. Usually, system services have numbers. The number of the system service is loaded into the first register (e.g., R0 or AX).
The full process when you need to invoke a system service is:
Save the registers you are going to overwrite on the stack.
Load the arguments you want to pass to the system service into hardware registers.
Load the number of the system service into the lowest register.
Trigger the exception to enter kernel mode.
Unload the arguments returned by the system service from registers
Possibly do some error checking
Restore the registers you saved before.
Instead of doing this each time you call a system service, operating systems provide wrapper functions for high level languages to use. You call the wrapper as you would normally call a function. The wrapper (in assembly language) does the steps above for you.
Because these wrappers are pretty much the same (usually the only difference is the result of different numbers of arguments), wrappers can be created using macros. Some assemblers have powerful macro facilities that allow a single macro to define all wrappers, even with different numbers of arguments.
Linux provides multiple _syscall C macros that create wrappers. There is one for each number of arguments. Note that these macros are just for operating system developers. Once the wrapper is there, everyone can use it.
How does a macro call an assembly language instruction ?
These _syscall macros have to generate in line assembly code.
Finally, note that these wrappers do not define the actual system service. That has to be set up in the dispatch table and the system service exception handler.

setting the Verbosity only for few /sequences/objects/interfaces in uvm?

How do I control the verbosity of certain components so that I can set a verbosity to only few of the components?
Lets say, for example in the verification of a particular feature, the test, few set of components/sequences/objects/interfaces etc are involved. I would like to set the verbosity of only these to be UVM_HIGH. I do not want to set the global severity to be set UVM_HIGH since lot of unrelated debug messages could come in which might increase the log size.
What would be a cleaner way of doing this? Its okay to use an additional commandline-plusarg for triggering this. Basically, the requirement would be that the test/components/sequences/objects/interfaces involved for a particular feature verification should take the global severity or the feature specific severity depending on which is higher.
Please note that one cannot use the built in report methods of uvm_component since, the uvm_info statements can be inside uvm_object extended classes as well as interfaces.
You can control the verbosity of a component from command line as a simulation argument. There are two choices:
+uvm_set_verbosity=<comp>,<id>,<verbosity>,<phase>
+uvm_set_verbosity=<comp>,<id>,<verbosity>,time,<phase> This one lets you specify the simulation time you want the applied verbosity to start
comp is the path of the component and wildcard * is supported. Example: uvm_test_top.env.agnt.*
id is the message identifier. you can apply to all messages within the component scope with by setting the id to _ALL_
verbosity is verbosity e.g. UVM_LOW, UVM_MEDIUM, UVM_HIGH, etc.
phase is phase you want the verbosity to be applied to.
For more detail i suggest reading:
The UVM reference manual section on Command Line Processor
UVM Message Display Commands Capabilities, Proper Usage and Guidelines by Clifford E. Cummings
You can use uvm_report_catcher for this. It works with uvm_object and interface. You can also use get_id(), get_message() etc. API for matching particular component/object and can only set verbosity of that component/object.
check my simple example on here on edaplaygroud
I tried different ways and also came up with this way.
Not sure how much it would be helpful for people.
simulate this with run time commands +user_verb=UVM_LOW +UVM_VERBOSITY=UVM_MEDIUM
class user_class extends uvm_object;
string report_id = "user_class";
string user_verb;
typedef uvm_enum_wrapper#(uvm_verbosity) uvm_verbosity_wrapper_e;
uvm_verbosity current_verb;
uvm_verbosity USER_VERBOSITY=UVM_HIGH;
function new (string name="my_class");
super.new(name);
report_id = name;
//void'($value$plusargs("user_verb=%s",user_verb));
//void'(uvm_verbosity_wrapper_e::from_name (user_verb,USER_VERBOSITY));
if ($test$plusargs("user_verb")) begin
current_verb=uvm_top.get_report_verbosity_level(UVM_INFO,"current_verb"); USER_VERBOSITY=uvm_top.get_report_verbosity_level(UVM_INFO,"user_verb");
end
$display("user_verb = %s",user_verb);
$display("current_verb = %s",current_verb);
endfunction : new
task display;
`uvm_info(report_id,"This is my message",USER_VERBOSITY)
endtask
endclass: user_class
module top;
string id;
string report_id = "top";
user_class m_user_class;
initial begin
m_user_class = new("m_user_class");
m_user_class.display;
`uvm_info(report_id,"This is my message",UVM_LOW)
end
endmodule: top
A working example can be found at edaplayground here