SystemVerilog name alias - system-verilog

Does SystemVerilog enables aliases for module instances and enumerations? Eg, how could I code this:
enum logic {foo, bar} myEnum
enum logic {baz, qux} myEnum
ie, baz and qux are aliases of foo and bar respectively.

The let construct can do this for any expression
enum logic {foo, bar} myEnum
let baz = foo;
let qux = bar;
You cannot alias an instance name.

They cannot be aliased, but the can be casted/converted. Refer to IEEE Std 1800-2012 § 6.19.4 Enumerated types in numerical expressions. Example for the LRM:
typedef enum {Red, Green, Blue} Colors;
typedef enum {Mo,Tu,We,Th,Fr,Sa,Su} Week;
Colors C;
Week W;
int I;
C = Colors'(C+1); // C is converted to an integer, then added to
// one, then converted back to a Colors type
C = C + 1; C++; C+=2; C = I; // Illegal because they would all be
// assignments of expressions without a cast
C = Colors'(Su); // Legal; puts an out of range value into C
I = C + W; // Legal; C and W are automatically cast to int

Related

32-bit vs. 4-bit in enum declaration

When I change the enumerated type variables from 4 bit to 32 bit, my error is appeased. I am wondering why I cannot keep it at 4 bit in this code.
Here are some pertinent snippets; I have deleted code related to non-pertinent variables:
Testbench:
module ALUtestbench;
//Variable Declaration
typedef enum {ADD = 32'b00, SUB = 32'b01, INV = 32'b10, RED = 32'b11} opcode_t;
opcode_t opcode; //declare typed variable
//Module Instance
alu alu_inst(
.opcode(opcode));
initial begin
opcode = opcode.first();
#10;
do
begin
$display(opcode);
$display("For opcode %s the result is: %0h", opcode.name, result);
opcode = opcode.next;
#10;
end
while (opcode != opcode.first);
end
endmodule
Design:
module ALU;
input reg A [4:0];
inout reg B [4:0];
output reg C [4:0];
initial begin
always # (*)
begin
case(opcode)
ADD : C = A + B;
SUB : C = A - B;
INV : C = ~A;
endcase
end
endmodule
At first, I had
typedef enum {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
opcode_t opcode; //declare typed variable
and the compiler gave me the error:
SystemVerilog requires the width of a sized constant in this context
to match the width of the enumeration type.
I then changed to 32-bit, and the code now does not have this error. I am wondering why I needed to do that. Does the case statement reject anything less than 32-bit?
From IEEE Std 1800-2017, section 6.19 Enumerations:
In the absence of a data type declaration, the default data type shall
be int. Any other data type used with enumerated types shall require
an explicit data type declaration.
Since int is 32-bit, you do not get an error when your constants are 32-bit.
If you want to use 4-bit constants, you need to explicitly declare your enum as 4-bit. Change:
typedef enum {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
to:
typedef enum bit [3:0] {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
This has nothing to do with the case statement.
If you do not explicitly declare a base type for an enumeration, the implicit datatype is int, which has a 32-bit width. Earlier versions of the SystemVerilog LRM also allowed you to use the label assignments form sized literals (i.e. ADD = 32'b00) to define the width explicitly instead of an explicit base type. But now the LRM only allows explicit base types. But it still has this rule in the IEEE 1800-2017 SystemVerilog LRM, section 6.19 Enumerations
If the integer value expression is a sized literal constant, it shall be an error if the size is
different from the enum base type, even if the value is within the representable range.
So either drop the size for the literals
typedef enum {ADD = 'b00, SUB = 'b01, INV = 'b10, RED = 'b11} opcode_t;
or write it as
typedef enum bit [3:0] {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;

how to match the structures in C?

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.

Is there a way to cast an SystemVerilog assignment pattern into a packed struct?

Per the System Verilog LRM "Assignment pattern format", a data structure can be printed into a string as follows:
module top;
typedef enum {ON, OFF} switch_e;
typedef struct {switch_e sw; string s;} pair_t;
pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}};
initial begin
$display("va[int] = %p;",va);
$display("va[int] = %0p;",va);
$display("va[10].s = %p;", va[10].s);
end
endmodule : top
This example may print:
va[int] = '{10:'{sw:OFF, s:"switch10"}, 20:'{sw:ON, s:"switch20"}} ;
va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}} ;
va[10].s = "switch10";
Is there a way to do the reverse? What I'd like to do is to take an assignment pattern string as a plusarg or a line read from a file, and assign that to a variable at run time, e.g.:
string assign_pattern = "'{10:'{sw:OFF, s:"switch10"}, 20:'{sw:ON, s:"switch20"}}";
$cast(va, assign_pattern); // ** This doesn't work **
If not generally possible, is there a way to do that specifically for packed struct types?
You can't do the reverse. SystemVerilog was designed as a compiled language—there's no parser available at run-time. You would have to create a parser in SystemVerilog or C smart enough to decode the assignment patterns you expect to read in.
Another option is converting the file of assignment patterns into code that could be compiled in with the rest of your code.
Another option based on your comments
You can use a bit-stream or streaming operator to parse a bit-string into a struct. The struct does not need to be packed, it just needs to be made up from fixed-sized, integral values.
module top;
typedef enum bit [1:0] {ON, OFF, INBETWEEN} switch_e;
typedef struct {switch_e sw; bit [8*8:1] s; bit [5:0] value;} trio_s; // 72 bits
typedef bit [71:0] uint72_t;
trio_s v,x;
uint72_t l;
initial begin
x = '{sw:OFF, s:"switch10", value:'h0a};
l = uint72_t'(x);
$displayh(l);
v = trio_s'(l);
$displayh("v = %p",v);
$display("v.s = %s",v.s);
end
endmodule
This displays
# 5cddda5d18da0c4c0a
# v = '{sw:OFF, s:8320234785195176240, value:10}
# v.s = switch10
pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}};
is the same as
pair_t va[int]
initial begin
va[10].sw = OFF;
va[10].s = "switch10";
..
Saying that, you can write your own parser of a +arg string (or strings) which will assign values to the array fields in a task. This is the only possibility. For exmple:
string indx = "1";
string sw = "off";
initial begin
int i = indx.atoi();
va[i].sw = sw == "off" ? OFF : ON;
...

Get letter corresponding to number in e (IEEE 1646)

I want to convert from integer values to string characters as follows:
0 to "a"
1 to "b"
and so forth up to
26 to "z"
Is there a way to do this in e without a big case statement?
Note: e is strongly typed and it isn't possible to do any type of arithmetic on string values. There also isn't any char-like type.
Another node: To all you C/C++ hotshots who keep down-voting my question, this isn't as easy a problem as you might think.
You can do something like this:
{0c"a"+my_num}.as_a(string)
0c"a" denotes the ASCII value of the letter 'a'. And an as_a() conversion of a list of numbers (actually, bytes) into a string creates a string where each character has the ASCII value of the corresponding list element.
You can define a new enum type to correspond to the alphabet, and use the fact that enum values are backed by int values to transform a list of ints to a list of enums, or to a string.
Consider the following example:
<'
type chars : [a, b, c, d, e, f, g];
extend sys {
run() is also {
var l : list of int[0..6];
var s: string = "";
gen l keeping {it.size() == 5};
print l;
for each in l { print it.as_a(chars); };
for each in l { s = append(s, it.as_a(chars)); };
print s;
};
};
'>
The output of this example will be:
l =
0. 4
1. 0
2. 6
3. 4
4. 5
it.as_a(chars) = e
it.as_a(chars) = a
it.as_a(chars) = g
it.as_a(chars) = e
it.as_a(chars) = f
s = "eagef"
Note that you can assign custom values to elements in the enum. In that way, you can assign standard ASCII values to enum elements.
type chars : [a=10, b=11, c=12, d=13, e=14, f=15, g=16];

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