how to match the structures in C? - system-verilog

In SV,
struct
{
int a;
int b;
} abc, abc1;
where the abc and abc1 are matching type but the
struct {int a; int b; } abc2; abc2 is not matching to abc1.
Why is it so, even though the members of the structures are same?

The rules in section 6.22 Type compatibility of the 1800-2017 SystemVerilog LRM explain that anonymous types can only match:
objects declared within the same declaration statement and no other
data types
In general, SystemVerilog has a strong typing policy for unpacked structs. This means the criteria for matching types is the name alone and not by looking into the layout of the structure.

Related

How to initialize unpacked array of unpacked union of unpacked structs?

What is the legal method of initializing this?
module tb();
typedef struct {
logic [3:0] A;
} a_t;
typedef struct {
logic [7:0] B;
} b_t;
typedef union {
a_t a;
b_t b;
} a_b_t;
a_b_t a_b [8];
initial begin
a_b <= '{default: '{default: 0}};
end
endmodule
xrun gives this error:
xmelab: *E,APBLHS (./tmp.sv,14|23): Assignment pattern - LHS must be an array or structure [SystemVerilog].
I've tried a variety of other ways, and I can't quite get this right. I'm working around it right now by initializing each entry separately with 2 lines of initialization.
As the error message state, assignment patterns only work with struct and arrays, not unions. You would need to use a foreach loop to assign each union member.
initial
foreach (a_b[i]) begin
a_b[i].a <= '{default:0};
a_b[i].b <= '{default:0};
end
Note that unless you are using the DPI for C compatibility, unpacked unions have little usefulness in SystemVerilog. Use packed unions instead.

What is meant by this SystemVerilog typedef enum statement?

typedef enum logic [1:0] {S0, S1, S2} statetype;
Does this statement mean that any variable declared as 'statetype' can only take three values, 2'b00, 2'b01, and 2'b10? If so, what happens if I assign the said variable with the value 2'b11?
The IEEE Std 1800-2017, section 6.19.3 Type checking, states:
Enumerated types are strongly typed; thus, a variable of type enum
cannot be directly assigned a value that lies outside the enumeration
set unless an explicit cast is used or unless the enum variable is a
member of a union. This is a powerful type-checking aid, which
prevents users from accidentally assigning nonexistent values to
variables of an enumerated type. The enumeration values can still be
used as constants in expressions, and the results can be assigned to
any variable of a compatible integral type.
Enumerated variables are type-checked in assignments, arguments, and
relational operators.
What I observe in practice is that some simulators issue a compile warning while others issue a compile error. You can see what happens on multiple simulators on edaplayground (if you sign up for a free account there).
For example, with VCS, the following code:
module tb;
typedef enum logic [1:0] {S0, S1, S2} statetype;
statetype s;
initial begin
s = S0;
$display("n=%s,s=%0d,", s.name(), s);
s = 3;
$display("n=%s,s=%0d,", s.name(), s);
end
endmodule
issues this warning:
Warning-[ENUMASSIGN] Illegal assignment to enum variable
tb.v, 16
tb, "s = 3;"
Only expressions of the enum type can be assigned to an enum variable.
The type int is incompatible with the enum 'statetype'
Expression: 3
Use the static cast operator to convert the expression to enum type.
but, it still runs the simulation and prints:
n=S0,s=0
n=,s=3
I believe the question should be rephrased to say that what is this is happening in our test-bench and how to avoid it. This will gives us more cleaner and bug free code.
efficient code to avoid the confusion:
typedef enum logic [1:0] {S0, S1, S2} statetype;
module top();
statetype st_e;
initial begin
for(int val=0;val<4; val++) begin
// casting for avoid confusion and gotchas
if (!$cast(st_e,val)) begin
$error("Casting not possible -> statetype:%0s and val:%0d",st_e,val);
end else begin
$display("statetype:%0s and val:%0d",st_e,val);
end
end
end
endmodule: top
This code is already there in edaplayground feel free to try it and update it. This could be replace with the sv macro for more efficiency. Please let me know I will provide the example for macros.
Output will be:
# run -all
# statetype:S0 and val:0
# statetype:S1 and val:1
# statetype:S2 and val:2
# ** Error: Casting not possible -> statetype:S2 and val:3
# Time: 0 ns Scope: top File: testbench.sv Line: 14
# exit

Verifying programs with heterogeneous arrays in VST

I'm verifying a c program that uses arrays to store heterogeneous data - in particular, the program uses arrays to implement cons cells, where the first element of the array is an integer value, and the second element is a pointer to the next cons cell.
For example, the free operation for this list would be:
void listfree(void * x) {
if((x == 0)) {
return;
} else {
void * n = *((void **)x + 1);
listfree(n);
free(x);
return;
}
}
Note: Not shown here, but other code sections will read the values of the array and treat it as an integer.
While I understand that the natural way to express this would be as some kind of struct, the program itself is written using an array, and I can't change this.
How should I specify the structure of the memory in VST?
I've defined an lseg predicate as follows:
Fixpoint lseg (x: val) (s: (list val)) (self_card: lseg_card) : mpred := match self_card with
| lseg_card_0 => !!(x = nullval) && !!(s = []) && emp
| lseg_card_1 _alpha_513 =>
EX v : Z,
EX s1 : (list val),
EX nxt : val,
!!(~ (x = nullval)) &&
!!(s = ([(Vint (Int.repr v))] ++ s1)) &&
(data_at Tsh (tarray tint 2) [(Vint (Int.repr v)); nxt] x) *
(lseg nxt s1 _alpha_513)
end.
However, I run into troubles when trying to evaluate void *n = *(void **)x; presumably because the specification states that the memory contains an array of ints not pointers.
The issue is probably as follows, and can almost be solved as follows.
The C semantics permit casting an integer (of the right size) to a pointer, and vice versa, as long as you don't actually do any pointer operations to an integer value, or vice versa. Very likely your C program obeys those rules. But the type system of Verifiable C tries to enforce that local variables (and array elements, etc.) of integer type will never contain pointer values, and vice versa (except the special integer value 0, which is NULL).
However, Verifiable C does support a (proved-foundationally-sound) workaround to this stricter enforcement:
typedef void * int_or_ptr
#ifdef COMPCERT
__attribute((aligned(_Alignof(void*))))
#endif
;
That is: the int_or_ptr type is void*, but with the attribute "align this as void*". So it's semantically identical to void*, but the redundant attribute is a hint to the VST type system to be less restrictive about C type enforcement.
So, when I say "can almost be solved", I'm asking: Can you modify the C program to use an array of "void* aligned as void*" ?
If so, then you can proceed. Your VST verification should use int_or_ptr_type, which is a definition of type Ctypes.type provided by VST-Floyd, when referring to the C-language type of these array elements, or of local variables that these elements are loaded into.
Unfortunately, int_or_ptr_type is not documented in the reference manual (VC.pdf), which is an omission that should be correct. You can look at progs/int_or_ptr.c and progs/verif_int_or_ptr.v, but these do much more than you want or need: They axiomatize operators that distinguish odd integers from aligned pointers, which is undefined in C11 (but consistent with C11, otherwise the ocaml garbage collector could never work). That is, those axiomatized external functions are consistent with CompCert, gcc, clang; but you won't need any of them, because the only operations you're doing on int_or_pointer are the perfectly-legal "comparison with NULL" and "cast to integer" or "cast to struct foo *".

systemverilog unpacked array concatenation

I'm trying to create an unpacked array like this:
logic [3:0] AAA[0:9];
I'd like to initialize this array to the following values:
AAA = '{1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
For efficiency I'd like to use repetition constructs, but that's when things are falling apart.
Is this not possible, or am I not writing this correctly? Any help is appreciated.
AAA = { '{4{1}}, '{3{2}}, '{2{3}}, 4 };
Firstly, the construct you are using is actually called the replication operator. This might help you in future searches, for example in the SystemVerilog LRM.
Secondly, you are using an array concatenation and not an array assignment in your last block of code (note the missing apostrophe '). The LRM gives the following (simple) example in Section 10.10.1 (Unpacked array concatenations compared with array assignment patterns) to explain the difference:
int A3[1:3];
A3 = {1, 2, 3}; // unpacked array concatenation
A3 = '{1, 2, 3}; // array assignment pattern
The LRM says in the same section that
...unpacked array concatenations forbid replication, defaulting, and
explicit typing, but they offer the additional flexibility of
composing an array value from an arbitrary mix of elements and arrays.
int A9[1:9];
A9 = {9{1}}; // illegal, no replication in unpacked array concatenation
Lets also have a look at the alternative: array assignment. In the same section, the LRM mentions that
...items in an assignment pattern can be replicated using syntax, such as '{ n{element} }, and can be defaulted using the default: syntax. However, every element item in an array assignment pattern must be of the same type as the element type of the target array.
If transforming it to an array assignment (by adding an apostrophe), your code actually translates to:
AAA = '{'{1,1,1,1}, '{2,2,2}, '{3,3}, 4};
This means that the SystemVerilog interpreter will only see 4 elements and it will complain that too few elements were given in the assignment.
In Section 10.9.1 (Array assignment patterns), the LRM says the following about this:
Concatenation braces are used to construct and deconstruct simple bit vectors. A similar syntax is used to support the construction and deconstruction of arrays. The expressions shall match element for element, and the braces shall match the array dimensions. Each expression item shall be evaluated in the context of an assignment to the type of the corresponding element in the array.
[...]
A syntax resembling replications (see 11.4.12.1) can be used in array assignment patterns as well. Each replication shall represent an entire single dimension.
To help interprete the bold text in the quote above, the LRM gives the following example:
int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}}
You can't do arbitrary replication of unpacked array elements.
If your code doesn't need to be synthesized, you can do
module top;
typedef logic [3:0] DAt[];
logic [3:0] AAA[0:9];
initial begin
AAA = {DAt'{4{1}}, DAt'{3{2}}, DAt'{2{3}}, 4};
$display("%p",AAA);
end
endmodule
I had another solution but I'm not sure if it is synthesizable. Would a streaming operator work here? I'm essentially taking a packed array literal and streaming it into the data structure AAA. I've put it on EDA Playground
module tb;
logic [3:0] AAA[0:9];
initial begin
AAA = { >> int {
{4{4'(1)}},
{3{4'(2)}},
{2{4'(3)}},
4'(4)
} };
$display("%p",AAA);
end
endmodule
Output:
Compiler version P-2019.06-1; Runtime version P-2019.06-1; Mar 25 11:20 2020
'{'h1, 'h1, 'h1, 'h1, 'h2, 'h2, 'h2, 'h3, 'h3, 'h4}
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
CPU Time: 0.580 seconds; Data structure size: 0.0Mb
Wed Mar 25 11:20:07 2020
Done

How does an integer store a literal (eg var x = 0)

when i write var x = 0
I know that x is an object that has properties and methods (created from Int Structure).
Where and how does x store the 0 ?
Is the 0 stored as a property of x ?
If yes, what would be the type of that property ?
If not, where is it stored ?
x is not an object, strictly speaking. "Object" is a name we give to instances of classes, not structs. x is an instance of the Int struct.
The Int structure wraps a Builtin integer type, and defines a bunch of methods you can call on it. That builtin integer literal type isn't accessible from Swift (nor is there a reason for it to be). Like all structures, instances of Int are stored on the runtime stack. They're not objects on the heap like Integer in Java, for example.
You can see the implementation details of (U)Int(8/16/32/64) here. This file uses the Generate Your Boilerplate (GYB) preprocessor created by the Swift team to generate .swift files from .swift.gyb template files.
On line 221, you can see the property _value of type Builtin.${BuiltinName}. The GYB preprocessor expands this out so that Int has a _value of type Builtin.Int, Int64 has Built.Int64, etc.