How to properly declare an N-dimensional queue inline in SystemVerilog? - system-verilog

If I have 2D queue of ints, I would expect to be able to declare it inline like so:
int my_queue[$][$] = {{1, 2}, {3, 4}};
I have also seen
typedef int int_queue[$];
int_queue my_queue[$] = {{1, 2}, {3, 4}};
Instead, when I compile, VCS provides me with an Incompatible Complex Type error:
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'int$[$][$]', while the type of
the source is 'bit[63:0]'.
Which implies to me that VCS expects the right hand side of the equation to be cast properly. The way around this that I have been using is:
typedef int int_queue[$];
typedef int_queue int_queue_of_queues[$];
int_queue_of_queues my_queue = int_queue_of_queues'{{1, 2}, {3, 4}};
But this adds N extra typedefs and lines for N dimensions, and I would rather do this in one line. If I had a way to cast the right hand side of the declaration without a typedef, then this would be simple, but I don't know if that is possible.

The array concatenation syntax only works on a single dimension. You cannot nest the {}'s because of cases where there is ambiguity between array {} and integral {} concatenation. You need to use array assignment pattern in the outer, or both dimensions. I prefer using assignment patterns for both dimensions making it clearer that these are array elements, not integral concatenations.
int my_queue[$][$] = '{'{1, 2}, '{3, 4}};
See section 10.10 Unpacked array concatenation in the IEEE 1800-2017
LRM.

Related

What is the difference between constant variable which is type of list and constant list

This is a basic question, but can't find elsewhere.
In dart we can declare a constant variable as
const foo = [1,2,3];
or
var foo = const [1,2,3];
Is there any performance related change if we use either any one.
When you do
const foo = [1, 2, 3];
It means foo will always be equal to [1, 2, 3] independently of the previously executed code and won't change its value later.
When you do
var foo = const [1, 2, 3];
It means that you are declaring a variable foo (and not a constant) which equals at this moment to the constant [1, 2, 3] (it is not dependant on the previously executed code). But the value foo can change and you could do later:
foo = const [1, 2];
which will be legit since foo is a variable. You couldn't do that with foo as a constant (since it is constant)
Therefore, it is better when you can to write
const foo = [1, 2, 3];
because it indicates to the compiler that foo will never change its value.
If constants are called literals and literals are data represented directly in the code, how can constants be considered as literals?
The article from which you drew the quote is defining the word "constant" to be a synonym of "literal". The latter is the C++ standard's term for what it is describing. The former is what the C standard uses for the same concept.
I mean variables preceded with the const keyword are constants, but they are not literals, so how can you say that constants are literals?
And there you are providing an alternative definition for the term "constant", which, you are right, is inconsistent with the other. That's all. TP is using a different definition of the term than the one you are used to.
In truth, although the noun usage of "constant" appears in a couple of places in the C++ standard outside the defined term "null pointer constant", apparently with the meaning you propose here, I do not find an actual definition of that term, and especially not one matching yours. In truth, your definition is less plausible than TutorialPoint's, because an expression having const-qualified type can nevertheless designate an object that is modifiable (via a different expression).
const int MEANING = 42;
the value MEANING is a constant, 42 is a literal. There is no real relationship between the two terms, as can be seen here:
int n = 42;
where n is not a constant, but 42 is still a literal.
The major difference is that a constant may have an address in memory (if you write some code that needs such an address), whereas a literal never has an address.

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

Converting a 2D array into 3D array in systemverilog

I have an 2 D dynamic array as
logic [511:0] array[];
I wan to convert it into a 3 D dynamic array defined as
logic [32][16]M[];
eg.
array[0]= 1110110000111000...512 bits....
M[0][0]= 1110110000111000...32 bits....
M[0][1]= next 32 bits....
and so on.
Can some please suggest how to accomplish this task.Did I declare my 3D array properly.I know dynamic array can only be defined in unpacked array. Can I define array as
logic [31:0] M[16][]; ?
Any suggestion or correction would be helpful.
Based on the example you gave it seems as if you want a dynamic array of an unpacked array of 16 32-bit packed words. That would be:
logic [31:0] M[16][];
You can use a bit-stream cast to assign one type shape to another type shape as long as the number of bits in the source can be fit into an exact match number of bits into the target. You need a typedef identifier for the target type (and it's a good practice to use typedefs in general when declaring variables).
typedef [31:0] my_3d_t[16][];
my_3d_t M;
M = my_3d_t'(array);
That does the assignment as
M[0][0][31:0] = array[0][511:480];
M[0][1][31:0] = array[0][479:448];
...
M[0][15][31:0] = array[0][31:0];
M[1][0][31:0] = array[1][511:480];
...

concatenation of arrays in system verilog

I wrote a code for concatenation as below:
module p2;
int n[1:2][1:3] = {2{{3{1}}}};
initial
begin
$display("val:%d",n[2][1]);
end
endmodule
It is showing errors.
Please explain?
Unpacked arrays require a '{} format. See IEEE Std 1800-2012 § 5.11 (or search for '{ in the LRM for many examples).
Therefore update your assignment to:
int n[1:2][1:3] = '{2{'{3{1}}}};
int n[1:2][1:3] = {2{{3{1}}}};
Just looking at {3{1}} this is a 96 bit number 3 integers concatenated together.
It is likely that {3{1'b1}} was intended.
The main issue looks to be the the left hand side is an unpacked array, and the left hand side is a packed array.
{ 2 { {3{1'b1}} } } => 6'b111_111
What is required is [[3'b111],[3'b111]],
From IEEE std 1800-2009 the array assignments section will be of interest here
10.9.1 Array assignment patterns
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. In other words, the following examples are not required to cause size warnings:
bit unpackedbits [1:0] = '{1,1}; // no size warning required as
// bit can be set to 1
int unpackedints [1:0] = '{1'b1, 1'b1}; // no size warning required as
// int can be set to 1’b1
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.
unpackedbits = '{2 {y}} ; // same as '{y, y}
int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}}

How to assign an array to struct member array?

How to assign c type array to struct member that is also an array of the same type? Here's my struct:
typedef struct {
uint8_t type;
uint8_t data[10];
} MyStruct;
Here's the creation of the struct:
MyStruct myStruct;
Here's generation of some array:
uint8_t generatedArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Here's my assignment:
myStruct.data = generatedArray;
As other answers have stated an array is not directly assignable and you must use a function such as memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
However...
C is a language with a long history. Early languages had roughly the notion of "little" and "large" types, the former being directly assignable and the latter not. Some later languages made everything assignable (or for functional languages, values).
Original C had primitive types; integer, float, etc.; and arrays of these types. The former, being "little", were assignable, the latter, being "large", were not. Subsequently C gained structures, and decided these were "little"...
So, a little strangely, while you cannot directly assign one array to another you can assign on structure to another, and in particular you can assign a structure with just one field which is an array... You can also write literal structure values, including for those with array-valued fields; and being C with its "types are comments" approach you can cast a pointer to an array to a pointer to a structure...
The above means you can write "fun" code like:
typedef struct
{
uint8_t type;
uint8_t data[10];
} MyStruct;
typedef struct
{
uint8_t data[10];
} MyArray;
typedef struct
{
uint8_t type;
MyArray array;
} MyStruct2;
void arrayAssignment(int x)
{
MyStruct myStruct;
MyArray generatedArray = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; // structure literal
*(MyArray *)&myStruct.data = generatedArray;
uint8_t generatedArray2[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; // array literal
*(MyArray *)&myStruct.data = *(MyArray *)generatedArray2;
MyStruct2 myStruct2;
myStruct2.array = generatedArray; // no casts at all, but element access is myStruct2.array.data[index]
}
Note that none of the casts, indirections, etc. or in the final example the extra array. in the indexing cost anything in the compiled code - they are all simply ways to persuade the compiler to use its built-in array assignment.
Many would of course argue against regular uses of these techniques!
Arrays cannot be assigned to each other, that is, an array identifier is not allowed to be on the left side of an assignment. When on the right side, the array is said to decay to a pointer to its first element, so it doesn't really represent the whole chunk.
You should use memcpy instead, and pass the size of the array which can be obtained via the sizeof operator. For short arrays, an optimizing compiler may be able to substitute the memcpy call with more efficient instructions to exploit the target architecture better.
You are attempting to assign to an array, but an array cannot be assigned to. An array is, however, an lvalue:
The following object types are lvalues, but not modifiable lvalues:
An array type
An incomplete type
A const-qualified type
An object is a structure or union type and one of its members has a const-qualified type
You'll need to use memcpy instead. You ought to pass sizeof(myStruct.data) as the third argument to memcpy:
memcpy(myStruct.data, generatedArray, sizeof(myStruct.data));
You can't directly assign an array like that. You'll have to copy it over.
I wonder how your compiler let you do that assignment. You cannot use array as modifiable lvalue. Also when used as rvalue an array represents a pointer to the first element in the array.
Other ways of achieving this would be to use pointers or to use memcopy()
With C99 you can use compound literals and string literals as initializer ( if uint8_t has the same bit-representation as char )
MyStruct myStruct={.data="\1\2\3\4\5\6\7\x8\x9\xa"};
...
MyStruct myStruct;
myStruct = (MyStruct){.data="\1\2\3\4\5\6\7\x8\x9\xa"};