output *E,TRNULLID: NULL pointer dereference. System verilog - system-verilog

class tx;
pkt p;
int j;
function new ( pkt p);
p = new();
j =10;
endfunction
task copy(pkt p);
this.p = new p;
endtask
endclass :tx
initial
begin
tx t1,t2;
pkt p;
t1 =new();
p = new();
p.i=256;
t2= new t1;
t2.j=20;
t2.copy(p);
$display(t1.j);
$display(t2.j);
$display(p.i);
$display(t1.p.i);
$display(t2.p.i);
t1.p.i=221;
$display(t1.p.i);
$display(t2.p.i);
end
endprogram
Why this code is not giving output. when i change t1 = new (p). it works fine
but give error for few lines
ncsim> run 10 20 256 ncsim: *E,TRNULLID: NULL pointer dereference.
While it doesn't print for
$display(t1.p.i);
$display(t2.p.i);

Null pointer errors occurs when trying to access a object that doesn't exist.
For the case of t1 = new(), there should be an warning in the compile/elaboration log. Something along the lines of missing input p. Changing t1 = new() to t1 = new(p) may appear to change resolve the error on that line, but t1.p is still null. This is because input variable has the same name of the as a member variable. When you newed the p inside tx's new it used the input variable because it was closer in scope. Since you assigned a new object to a input handle, the original handle is not pointing to the same object. It would be pointing the the same object if you used you defined the directionality as inout or ref instead as an inferred input. Still the member p would be null.
Solutions:
Change tx's function new ( pkt p); to function new ();. The input p doesn't appear to be doing anything so there is no reason to have it. p = new() will be assigned to tx's member variable since there is no name conflict.
Change p = new() to this.p = new() in tx's new method. This makes it explicit that the new will apply to the member variable, not the local.
Do both solutions 1 and 2.
If you need both ps and you do not want to do the above, then rename one and use accordingly.

Related

passing different type of argument to method in systemverilog

Trying to understand the concept of casting.
class base;
local string a;
function new();
a = "I am a";
endfunction
function void print();
$display(a);
endfunction
endclass
class ext extends base;
local string b;
function new();
b = "i am b";
endfunction
function void print();
$display(b);
endfunction
endclass
function void printer(base p);
ext e;
$cast(e, p);
e.print();
p.print();
endfunction
program P;
base b = new();
ext e = new();
initial begin
printer(b);
end
endprogram
After printer(b) executed then I get cast and Null pointer Error as the below.
I thought that printer(b) send base type so there is no casting to printer(base p) as a base argument. then $cast(e, p); down-casts from base to ext. Why does this casting invalid?
xcelium> run
$cast(e, p);
|
xmsim: *E,BCLCST (./testbench.sv,24|6): Invalid cast: a value with the class datatype '$unit_0x4ccdf83b::base' cannot be assigned to a class variable with the datatype '$unit_0x4ccdf83b::ext'.
xmsim: *E,TRNULLID: NULL pointer dereference.
File: ./testbench.sv, line = 17, pos = 13
Scope: worklib.$unit_0x4ccdf83b::ext::print
Time: 0 FS + 1
Verilog Stack Trace:
0: function worklib.$unit_0x4ccdf83b::ext::print at ./testbench.sv:17
1: function worklib.$unit_0x4ccdf83b::printer at ./testbench.sv:26
2: initial block in P at ./testbench.sv:36
./testbench.sv:17 $display(b);
xcelium> exit
If I ran printer(b); after printer(e); then there is no null pointer error but still Invalid case.
Why does casting invalid happen and Null point error?
In your program, you create two separate objects:
a base object containing a member a and a method base::print.
an extended object containing members a and b, and methods base::print and ext::print.
You are never allowed to make an assignment from a base object to to an extended class variable e.
Lets assume you did not declare b as a local variable. If SystemVerilog did allow assignments from base object to extended, and you tried to reference e.b, the member does not exist.
You are allowed to make assignments in the other direction--from extended object to base class variable. That is what happens when you call printer(e)
You need to test the result from $cast. It returns 0 if the cast fails to make the assent to e leaving it null.
function void printer(base p);
ext e;
if ($cast(e, p))
e.print();
p.print();
endfunction
module P;
base b = new();
ext e = new();
initial begin
printer(b);
printer(e);
end
endmodule
Note that this prints 3 lines (1 from printer(b) and 2 from printer(e))
# I am a
# i am b
# I am a

Unexpected behavior with force statement inside interface task

I am seeing side affect of other unrelated signals getting affected when I use force inside a task. In the example below, I try forcing 2 independent variables "a" and "b" inside the module "dut". To do this I use the helper task "force1" inside the interface 'intf'. However I find that changing 'b' also causes 'a' to change as shown in the output.
Test case on edaplayground. https://www.edaplayground.com/x/23LM
module dut(intf i1);
logic a;
logic b;
endmodule
interface intf;
task force1(bit sel, int value);
if(sel == 0) begin
$display("[%0t]:forcing a to %0d", $stime, value);
force dut1.a = value;
end
else begin
$display("[%0t]:forcing b to %0d", $stime, value);
force dut1.b = value;
end
endtask
endinterface
module test();
intf intf1();
dut dut1(intf1);
always#(dut1.a) begin
$display("[%0t]:Changing value of a=%0d", $stime, dut1.a);
end
always#(dut1.b) begin
$display("[%0t]:Changing value of b=%0d", $stime, dut1.b);
end
initial begin
intf1.force1(.sel(0), .value(1));// Change value of a to 1
#10;
intf1.force1(.sel(1), .value(0));// Change value of b to 0
#10;
$finish;
end
endmodule
[0]:forcing a to 1
[0]:Changing value of a=1
[10]:forcing b to 0
[10]:Changing value of a=0 ----------> WHY DID THIS CHANGE?
[10]:Changing value of b=0
I expected the output 'a' not to change to 0.
The problem is that value is a static variable. When you declare a task in Verilog, unless you specify the task to be automatic, all the variables in the task will be static, meaning each call to the task that modifies a variable does so for all calls to that task (its like creating a static local variable in C).
Its also important to note that force procedural assignments dont just resolve the RHS and set the LHS to that value, but instead forces the LHS to be set to the expression on the RHS. So, an assignment like force A = B; will make A equal to B at the time the force is applied as well as any time B might be updated after. Putting this together with information above (value is static), you arent setting dut1.a to be 1 with your force, but setting it to be value. Once value changes with your next call to your task, dut1.a also changes to match it.
Now, unfortunately, you cant just make the task automatic or just make value automatic to solve the problem since force requires a static expression (ie, an expression of only static variables or constants) to work. One solution is to create a static placeholder for the values you want that disconnects your force from your task input value; you can do that with an array:
task force1(bit sel, int value);
static int values[1 << $bits(sel)]; // <- Make sure no matter the width of sel, there are enough places in the array, could just be values[2]
values[sel] = value;
if(sel == 0) begin
$display("[%0t]:forcing a to %0d", $stime, value);
force dut1.a = values[0];
end
else begin
$display("[%0t]:forcing b to %0d", $stime, value);
force dut1.b = values[1];
end
endtask

Understanding function return values

I am trying to understand SystemVerilog function return values from the Language resource manual(Section 10.3.1), but I am having difficulties in grasping the following section. Can anyone help me interpret it? I tried looking in different sites but the information wasn't that deep.
In SystemVerilog, a function return can be a structure or union. In this case, a hierarchical name used inside the function and beginning with the function name is interpreted as a member of the return value. If the function name is used outside the function, the name indicates the scope of the whole function. If the function name is used within a hierarchical name, it also indicates the scope of the whole function.a = b + myfunc1(c, d); //call myfunc1 (defined above) as an expression
myprint(a); //call myprint (defined below) as a statement
function void myprint (int a);
...
endfunction
You can use two different ways to return a value from a function. For example as follows,
function int myfunc1(int c, d);
myfunc1 = c+d;
endfunction
and
function int myfunc1(int c, d);
return c+d;
endfunction
So when the function is declared as a structure or union type, the hierarchical name beginning with the function name also means the variable of the return value.
But the old LRM description is not right and precise now because the hierarchical name now could also be the function scope, not the return value. For example,
typedef struct { int c, d, n; } ST;
function ST myfunc1(int c, d);
static int x = 1;
myfunc1.c = c; // myfunc1 refers to the return structure
myfunc1.d = d; // myfunc1 refers to the return structure
myfunc1.n = c + d + // myfunc1 refers to the return structure
myfunc1.x; // myfunc1 refers to function scope
endfunction
Another interesting example of using hierarchical name containing the function name.
typedef struct { int c, d; } ST ;
module top;
function ST myfunc1(int c,d);
top.myfunc1.c = c;
myfunc1.c = 1;
myfunc1.d = d;
endfunction
ST x;
initial begin
x = myfunc1(3,2);
#1 $display("%d %d %d", x.c, x.d, top.myfunc1.c);
end
endmodule
The function call of x = myfunc1(3,2) constructs a call frame for myfunc1 and pass values for evaluation. The scopes of myfunc1 and top.myfunc1 are different. The hierarchical name beginning with myfunc1 refers to current call frame of the function, while top.myfunc1 refers to the scope of function declared inside the module top . So the message will be 1 2 3.
It looks like you are referencing a really old version of the LRM. Get the latest official version IEEE Std 1800-2012. You'll want to look at § 13.4.1 Return values and void functions. There is a line missing between quoted paragraph and quoted code:
Functions can be declared as type void, which do not have a return
value. Function calls may be used as expressions unless of type void,
which are statements:
The example code is not referring you your question hierarchical name access, it is an example of the void return type.
The example code below demonstrates hierarchical name access with a struct/union return types. Read about structs and unions in § 7.2 and § 7.3.
function struct { byte a,b; } struct_func (byte a,b);
byte c;
c = a ^ b;
struct_func.a = a; // <== hierarchical name used inside the function
struct_func.b = ~b;
endfunction
initial begin
// function name is used within a hierarchical name ( struct member )
$display("%h", struct_func(8'h42,8'hFE).b ); // returns 01
// function name is used within a hierarchical name ( function member )
$display("%h", struct_func.b ); // returns fe (last value of input b)
// function name is used within a hierarchical name ( function member )
$display("%h", struct_func.c ); // returns bc (last value of variable c)
end
Most cases you want to reuse struct/union definitions and should be defined as a typedef. The below function with the yeild the same results with the above initial block.
typedef struct { byte a,b; } my_struct;
function my_struct struct_func (byte a,b);
byte c;
c = a ^ b;
struct_func.a = a; // <== hierarchical name used inside the function
struct_func.b = ~b;
endfunction

using evalin to evaluate a function in the base workspace

I am trying to allow a function to have access to the base workspace using the evalin function, but I am having trouble. Here is a simple example:
My main code:
A = 1;
B = 2
evalin('base','[ C ] = FUN(B)');
C
My Function:
function [C ] = FUN( B )
C = A + B;
end
My error:
Undefined function or variable 'A'.
Error in FUN (line 4)
C = A + B;
Error in Test (line 4)
evalin('base','[ C ] = FUN(B)');
So, the function is not being evaluated in the base workspace because it does not know what the value of A is.
Can anyone suggest something? I have a lot of variables that I need to access in several functions and I don't want to pass them and I don't want to use global variables.
Thanks!
From the evalin documentation,
evalin(ws, expression) executes expression, a string containing any valid MATLAB® expression, in the context of the workspace ws. ws can have a value of 'base' or 'caller' to denote the MATLAB base workspace or the workspace of the caller function.
So the line of code
evalin('base','[ C ] = FUN(B)');
evaluates only the line of code
[ C ] = FUN(B)
in the context of the base workspace. It does not evaluate the body of the function within the context of the base workspace. So the error that you are observing makes sense.
Is there a particular reason why you don't want to pass the variables in to the function? Why do you have several variables in the base (?) workspace, or do you just have several variables within a main function?
If the latter, you could use nested functions to have access to the variables declared in the caller (function) workspace. For example, suppose you have a main function like
function main()
A = 1;
B = 2;
C = FUN();
function [C] = FUN()
C = A + B;
end
end
The function FUN has access to both A and B and so you don't have to pass in any arguments.
An alternative to passing in several different inputs, is to just pass in a structure that has different fields that your function can access at will. Using the above example, we could do the following
function main()
A = 1;
B = 2;
data.A = A;
data.B = B;
C = FUN(data);
end
function [C] = FUN(data)
C = data.A + data.B;
end
In this case, the function FUN can be a function within its own file or declared after main. Again, we only pass in one argument that has all the data that the function needed.
Actually Evalin function is used to take data from base workspace:
Syntax is :
evalin('base','variable')
Evalin function is used in the function .
For example see the below function
function [out1 out2 out3]=main_fun(in1,in2)
out1=in1+in2;
out2=in1-in2;
in3=evalin('base','in3');
in4=evalin('base','in4');
out3=in3+in4;
end
Here out3 value will have the sum of in3 and in4 from workspace.
out1 and out2 will have the sum and difference of in1 and in2 from current function workspace.

Self reference within an object method

Just started crash coursing in Matlab OO programing and I would like to write a set method for a object that will set the value then reciprocate by setting itself in the relevant field on the other object.
classdef Person
properties
age;
sex;
priority; % net priority based on all adjustment values
adjustment; % personal adjustment value for each interest
family;
end
methods
function obj = set.sex(obj, value)
if value == 'm' || value == 'f'
obj.sex = value;
else
error('Sex must be m or f')
end
end
function obj = set.family(obj,value)
if class(value) == 'Family'
obj.family = value;
else
error('Family must be of type Family')
end
end
end
end
classdef Family
properties
husband;
wife;
children;
elders;
adjustment; % interest adjustment values
end
methods
function this = set.husband(this,person)
if class(person) == 'Person'
this.husband = person;
person.family = this;
else
error('Husband must be of type Person')
end
end
function this = set.wife(this,person)
if class(person) == 'Person'
this.wife = person;
person.family = this;
else
error('Wife must be of type Person')
end
end
end
end
So what I have to do now is:
p = Person
f = Family
f.husband = p
p.family = f
What I would like is for family and person to auto set themselves in each other:
p = Person
f = Family
f.husband = p
And Family set.husband function will set p's family value to f. Why is my code not working? As far as I can tell I'm doing what is suggested in the comments.
Edit:
After some messing around I've confirmed that "this" and "person" are objects of the correct type. Ultimately the issue is that Matlab passes by value rather then by reference. Unless anyone knows a way around that I'll answer myself when I can.
Normal objects are usually considered value objects. When they are passed to a function or a method, only the value is passed not a reference to the original object. Matlab may use a read-only referencing mechanism to speed things up, but the function or method cannot change the properties of the original object.
To be able to pass an input parameter by reference, your custom object needs to be a handle object. Simply when defining your class, inherit from handle and that should do the trick:
classdef Person < handle
and
classdef Family < handle