Declaring class handle as rand type in System Verilog - class

Please See this for better clarification of of my codeWhat happens when we declare class handle as rand type?
will it affect the randomization?
I am trying to do sorting using constraint guards.
class Sorting;
rand int unsigned n;
rand Sorting next;
constraint C0 { n inside {[2:20]};}
constraint sort {if( next != null ) n < next.n;}
endclass
module random;
Sorting s;
initial
begin
s=new;
repeat(10)
begin
assert(s.randomize());
$write("%0d\t",s.n);
end
end
endmodule
I am getting the warning in VCS like these -> Warning-[CNST-PPRW] Constraint randomize NULL object warning
The same code is in the LRM under the constraint guard section. I am curious to know whether we can sort the random data using the constraint guard technique? I have done sorting the random data using foreach loop inside the constraint. I am just trying this way. Help me with it.
Thanks!

You are correct. According to the LRM this should not produce any warning.
VCS produces a warning, which it should not. At least it is not an error and you can safely ignore it. There might be a way to turn the warning off, if you wish. Check command line switches.
BTW, NC does not produce any warning.

Related

How to control the property rand_mode in a SystemVerilog class?

Suppose there is a class A like below:
class A;
rand logic [3:0] a;
rand logic [3:0] b;
rand logic [3:0] c;
constraint a_const{
a<'h4;
}
constraint b_const{
b<'h4;
}
endclass
When I use :
A at = new();
at.b_const.constraint_mode(0);
assert(at.randomize());
b is also randomized. But, I don't want that.
Is there a way I can only randomize a without randomizing b and c?
Because there can be many logics in a class, sometimes I just want to rand some of them. Put some of the logics in one class like A while some in other class B is one of the solutions, but it is too complicated.
If you only want one of the rand variables in a class to be randomized, then you can pass the variable to the randomize function:
assert(at.randomize(a));
Alternately, as you mentioned in the title to your question, you can use rand_mode to disable randomization of individual class variables:
at.b.rand_mode(0);
at.c.rand_mode(0);
assert(at.randomize());
Refer to IEEE Std 1800-2017, section 18.8 Disabling random variables with rand_mode().
With either of the above approaches, only a will be randomized.
I suspect you expected b_const.constraint_mode(0) to disable randomization of variable b. That line simply disables the named constraint, leaving b unconstrained. This means that b will be randomized in your original code (which is what you observed).
SystemVerilog gives you two mode controls rand_mode() and constraint_mode, and they operate independently. Active constraints must be satisfied regardless of whether the variables are random or not(state-variables).
You should probably separate the variables you want randomized into different groups of different classes and perhaps put them into a hierarchy.
If you only want to randomize one variable with a single constraint, use std::randomize()
assert( std::randomize(a) with { a < 'h4;});

What is the use of minizinc fix function?

i see that fix documentation says:
http://www.minizinc.org/doc-lib/doc-builtins-reflect.html#Ifunction-dd-T-cl-fix-po-var-opt-dd-T-cl-x-pc
function array [$U] of $T: fix(array [$U] of var opt $T: x)
Check if the value of every element of the array x is fixedat this point in evaluation. If all are fixed, return an array of their values, otherwise abort.
I am thinking it can be used to coerce a var to a par.
Here is the code.
array [1..num] of var int: value ;
%% generate random numbers from 0..num-1, this should fix the value of the var "value" or so i think
constraint forall(i in index_set(value))(let {int:temp_value=discrete_distribution([1|i in index_set(value)]); } in value[i]=trace(show(temp_value)++"\n", temp_value));
%%% this i was expecting to work, as "value" elements are fixed above
array [1..num] of int:value__ =[ trace(show(fix(value[i])), fix(value[i])) | i in index_set(value)] ;
But i get:
MiniZinc: evaluation error:
with i = 1
in call 'trace'
in call 'fix'
expression is not fixed
My questions are:
1) I think i should expect this error as minizinc is not sequential execution language?
2) Examples of fix in user guide is only where output statement is used. Is it the only place to use fix?
3) How would i coerce a var to a par?
By the way I am trying this var to par conversion because i am having problem with array generator expression. Here is the code
int:num__=200;
int:seed=134;
int: two_m=2097184;
%% prepare weights for generating numbers form 1..(two_m div 64), basically same weight
array [1..(two_m div 64)] of int: value_6_wt= [seed+1 | i in 1..(two_m div 64)] ;
%% generate numbers. this dose not work gives out
%% in variable declaration for 'value6'
%% parameter value out of range
array [1..num__] of int : value6 = [ discrete_distribution(value_6_wt) | j in 1..num__];
In the MiniZinc language the difference between a parameter and a variable is only the fact that a parameter must have a value at compile time. Within the compiler we turn as many variables into parameters as we can. This saves the solver from having to do some work. When we know that a variable has been turned into a parameter, then we can use the fix function to convince the type system that we really can use this variable as a parameter and see its value.
The problem here however is that fix is defined to abort when the variable is not fixed to one value. If no testing is done, this requires some (magic/)knowledge about the compilation process. In your case it seems that the second array is evaluated before the optimisation stage, in which all aliasing is resolved. This is the reason why it does not work. (This is indeed one of the things that is a consequence of a declarative language)
Although fix might only be used in the output statements in the examples (where it's guaranteed to work), it is used in many locations in the MiniZinc libraries. If we for example look at the library that is used for MIP solvers, there are many constraints that can be encoded more efficiently if one of the arguments is a parameter. Therefore, you will often see that the a constraint in this library first tests its arguments with is_fixed, and then use a better encoding if this returns true.
The output statement and when is_fixed returns true will both give the guarantee that a variable is fixed and ensure that the compilation doesn't abort. There is no other way to coerce a variable to a parameter, but unless you are dealing with dependant predicate definitions, you can just trust the MiniZinc compiler to ensure that the resulting FlatZinc will contain a parameter instead of a variable.

assignment in SystemVerilog, compilation error - token is 'assign'

I have this code:
integer [31:0]R;
integer [15:0]R_f1;
integer [15:0]R_f2;
assign R_f1 = R[15:0];
assign R_f2 = R[31:16];
But it is not compiled because of assign.
What changes do I need to do ? It can also be in the header file.
There was a bug in the original implementation of Verilog-XL that it ignored the packed dimensions of integer declarations. And integer/int/byte did not have a fixed size. For these reasons, SystemVerilog disallows specifying packed dimensions for any of these built-in types. Use bit or logic instead.
Also, since you tagged this with SystemVerilog make sure the file has a *.sv suffix. An alternative to what you are trying to do is
integer [31:0]R;
let R_f1 = R[15:0];
let R_f2 = R[31:16];
Depending on the language you use. In verilog, only the net types can be assigned using continuous assignment. integer is not a net type, therefore theses assignments are not allowed in verilog. I guess you compiled your code in verilog mode and got the message about assignment statements.
Also packed dimensions on integer types are not allowed. So, the following declaration is illegal: integer [31:0]R;. Some compilers will just ignore the declaration. All integers are 32 bit wide in any case.
So, to fix it in verilog mode you can use always #* instead:
integer R = 10;
integer R_f1;
integer R_f2;
always #* R_f1 = R[15:0];
always #* R_f2 = R[31:16];
Though by the sound of your initial question, you need to use a different type of the data type, which allows you to have real vectors. In verilog they are reg and one of the net types, i.e. wire. With wires you can use assign statement, with reg you need to use always blocks. Something like the following:
reg[31:0] R = 10;
reg[15:0] R_f1;
reg[15:0] R_f2;
always #* R_f1 = R[15:0];
always #* R_f2 = R[31:16];
Since you marked your question as a system verilog question, you can use one of the system verilog types, i.e. logic or bit. If you use those, you can apply both, assign or always blocks to them. BTW, assign will also work for integeres.
logic[31:0] R = 10;
logic[15:0] R_f1;
logic[15:0] R_f2;
assign R_f1 = R[15:0];
assign R_f2 = R[31:16];
just make sure that you compile in a system-verilog mode.

What is '(signal_name)' notation mean in Specman?

I am new to Specman and trying to learn it by reading existing code.
I came across the following function and can't find an explanation in specman documentation...
VerifyNode(end_point:string, derived_value:uint) is also {
if ('(end_point)' === ~derived_value) {
message("Error1");
}
else if ('(end_point)' === derived_value) {
message("Error2");
}
else {
message("Error3");
}
}
I assume logically the '(end_point)' is getting actual value of end_point signal in run-time. Is that true?
Error1 will be the message if value of end_point at run time is negate the derived_value unsigned integer.
Error2 will be the message if value of end_point at run time is the same as the derived_value unsigned integer.
How can i explain the "Error3" condition?
Indeed this is the very old school of signal access based on string. I recommend you search for "simple_port".
The end_point is a string, that should be the full HDL path of the signal you want to read. Example of calling this method:
// check if signal has the value 3:
VerifyNode("top.module_a.sig_val", 3);
The official name of '' is called the tick notation in Specman documentation. Search for the term "tick notation" in cdnshelp and you will find it.
'(end_point)' is two things. It is old-school, non-port access to the device under test (DUT) and the (end_point) part of that snippet is the way to do string substitution directly in the '' access to the DUT. Using the old style of access to the DUT can drastically slow down simulation speed, if your design is big enough for that to be a concern for you. Also, this methodology lacks more static compile time checks as those strings can be anything and you'll only know the path is wrong when you simulate it and the DUT path cannot be found, creating an error.

How to pass a variable value to a macro in SystemVerilog?

I think the question sums it up pretty well as to what I want: passing the value of a variable to a macro in SystemVerilog.
For example, what I want:
Say, there are 4 signals by the name of abc_X_def and I want to initialize all of them to 0.
So, without macros:
abc_0_def = 4'b0000;
abc_1_def = 4'b0000;
abc_2_def = 4'b0000;
abc_3_def = 4'b0000;
Now, the code that I have written is having a problem:
`define set_value(bit) abc_``bit``_def = 4'b0000
for (int i = 0; i < 4; i++) begin
`set_value(i);
end
The error is that it's trying to find the signal abc_i_def which is obviously wrong. Just wondering if it's possible to pass the actual value of the variable 'i' to the macro.
The preprocessor directives are evaluated by the preprocessor and modify the code that is presented to the compiler.
The for loop is a verilog construct that is evaluated by the compiler.
So your preprocessor is not evaluating the for loop. It sees:
`define `set_value(bit) abc_``bit``_def = 4'b0000
[some verilog]
`set_value(i);
[some verilog]
So 'i' is just i. It doesn't become a number until compilation.
Why don't you use local params with generate, so the local params are created in a loop at elaboration as the for loop is unrolled?
This is one of the many places that macros are a problem. Generate is a problem in other places (like when you want to control port lists).
I dug into this a bit more. Parameters and local parameters inside a generate are created a localparams in the scope of the generate. See here: System Verilog parameters in generate block. I had to get back to work before I could test it.
I would just use code and populate an array. This compiles in VCS:
module veritest
#(
parameter MAX_X = 5,
MAX_Y = 3,
MAX_Z = 2
)
(); // empty port list
logic [4:0] abc_def[1:MAX_X][1:MAX_Y][1:MAX_Z];
always #*
begin
for (integer z=1; z<(MAX_X+1);z=z+1)
for (integer y=1; y<(MAX_Y+1);y=y+1)
for (integer x=1; x<(MAX_X+1);x=x+1)
begin
abc_def[x][y][z] = 4'b0000;
end
end
endmodule
Since you said the naming conventions is out of your control, you should consider using another tool to generate the verilog for you.
You can have the code generated by your preferred programming then use an `include statement in your verilog file. Or you can go with an embedded route.
Perl had EP3 : http://search.cpan.org/~gspivey/Text-EP3-Verilog-1.00/Verilog.pm
Ruby has eRuby : http://www.tutorialspoint.com/ruby/eruby.htm
I'm sure something like it exists for other languages to. Such as Python, Tcl, JavaScript, etc.
Concept is the same, just a difference in embedded language and tool used for conversion.