How to implement static cast on array of enum while using bitstream operator

Hi I was trying to stream the commands from one array to different array dimension and the edaplyground tool runs and gives the expected output but there is a warning saying that static cast needs to be applied.
How can I apply the static cast while using the streaming operation and streaming the enum values?


typedef enum {unset, wr, rd} cmd;
module main;
  initial begin
    cmd prev[8];
    cmd act[2][4] = '{0: '{default: rd}, 1: '{default: wr}};
    
    prev = {>>{act}};
    $display("%0p", prev);
  end
endmodule

Warning msg i’m getting is:
Warning-[ENUMASSIGN] Illegal assignment to enum variable
testbench.sv, 47
main, “prev = { >> 1 {act}};”
Only expressions of the enum type can be assigned to an enum variable.
Expression: { >> 1 {act}}
Use the static cast operator to convert the expression to enum type.

In reply to NaveenReddy:

The streaming cast assignment to prev is legal, while the static variable initialization to act is not. You should report both these issues to your tool vendor.

The streaming operators work on the same bitstream types allowed with a static cast. The streaming operators give you more flexibility in bit ordering with less type safety. A bitstream cast gives you the same functionality of a simple left-to-right streaming operator.

typedef enum {unset, wr, rd} cmd;
typedef cmd cmd8_t[8];
module main;
  cmd prev[8];
  cmd act[2][4] = '{0: '{default: rd}, 1: '{default: wr}};
  initial begin
    prev = cmd8_t'(act);
    $display("%0p", prev);
  end
endmodule

In reply to dave_59:

Thanks that helped. I have this follow up question.

prev = cmd8_t’(act);

  1. can I view it like this ?? since streaming operators work on the same bitstream types, here it is an enum with integer index(32 bits). after streaming of 32 bits into destination variable every time the casting is applied with enum type since streamed bits width matched with bitstream type width??
  2. Could you please comment abot the Method 3 i’m talking in the below code

`define axis1 1
`define axis2 1
`define axis3 4
typedef enum {unset, wr, rd} cmd;
typedef cmd cmd_arr[`axis1][`axis2][`axis3]; 
typedef cmd cmd8_t[8];

class test;
  //cmd prev[8];  // store previous values
  cmd8_t prev;
  
  // assuming i have matched the cmd8_t to the total number of enum cmds in my_arr
  // i can initialize my_arr in below methods but im looking for a way to initialize the array in method3
  
  // *Method1: if the array size is more it will be tedious and i feel its not recommended way
  // static cmd_arr my_arr[2] = '{0: '{default: rd}, 1: '{default: wr}};
  
  // Method2: assign default array blocks to all indexes using the function
  //static cmd_arr my_arr[2] = '{default: test::initArr()};
  
  // Method3: initialize each index with different enum through mannual index access or some loop(for/foreach etc...)
  // instead of initializing like this. >>> static cmd_arr my_arr[2] = '{0: test::initArr(rd), 1: test::initArr(wr)};
  /*
  is the below achieved only by writing another static method ??
  static cmd_arr my_arr[3];
  my_arr[0] = test::initArr(rd);
  my_arr[1] = test::initArr(wr);
  my_arr[2] = test::initArr(unset);
  */
  
  extern function void pre_randomize();
  extern static function cmd_arr initArr(cmd c);
endclass
    
function cmd_arr test::initArr(cmd c=unset);
  cmd_arr temp;
  temp = '{default: c};
  return temp;
endfunction
    
function void test::pre_randomize();
  prev = cmd8_t'(test::my_arr);
endfunction
   
module main;
  initial begin
    test t;
    t = new();
    t.randomize();
    
    $display("%0p", t.prev);
    $display("0: %0p \n1: %0p",test::my_arr[0], test::my_arr[1]);
    foreach(t.prev[i]) $display("i: %0d cmd: %0s", i, t.prev[i]);
  end
endmodule

In reply to NaveenReddy:

For Q1, I think you have the correct understanding. Both streaming operator and cast define a intermediate linear “bitstream” of data the goes between the source and destination. If SystemVerilog defines a way for a source variable of a particular type into that bitstream, then there’s a way to get to the target using the reverse definition.

For Q2, first i hope you’re not confusing static cast with static variable lifetimes. Declaring static variables in not necessary for discussing bitstreams. I don’t see a problem with your method 1. You just have to make sure that all elements are covered, or use a default. Your function initArr is returning a 3-dimensional array and you are trying to assign it to 2-dimensions of my_arr. I don’t understand what your overall goal is.

In reply to dave_59:
Thanks Dave!
For Q1, No I’m not getting confused between the static cast and static variable lifetime.
For Q2, I was going over my goal again and I actually found my solution.

The goal I was trying to achieve there is as below.


// lets say that my_arr is of depth 5
// I can do declare and initialize like below in single line.
static cmd_arr my_arr[5] = '{0:test::initArr(wr), 1:test::initArr(rd), default: test::initArr()};

// But I was looking for something like below (declaring and initializing in different lines within the class and without using any static class methods or inline initialization)
class test;
  static cmd_arr my_arr[5];
  test::my_arr[0] = test::initArr(wr);  // written directly inside class like this
  test::my_arr[1] = test::initArr(rd);
  test::my_arr[2] = test::initArr(unset);
  test::my_arr[3] = test::initArr(rd);
  test::my_arr[4] = test::initArr(wr);
endclass

// instead I should have done the array initialization in module block like below
class test;
    static cmd_arr my_arr[5];
endlcass
module main;
  initial begin
    test::my_arr[0] = test::initArr(wr);
    test::my_arr[1] = test::initArr(rd);
    test::my_arr[2] = test::initArr(unset);
    test::my_arr[3] = test::initArr(rd);
    test::my_arr[4] = test::initArr(wr);
  end
endmodule
//

In reply to NaveenReddy:

What you wrote is no different from

// with index labels
  initial begin
    test::my_arr = '{0:test::initArr(wr),
                     1:test::initArr(rd),
                     2:test::initArr(unset),
                     3:test::initArr(rd),
                     4:test::initArr(wr);
  end
// or positional
  initial begin
    test::my_arr =  '{test::initArr(wr),
                     test::initArr(rd),
                     test::initArr(unset),
                     test::initArr(rd),
                     test::initArr(wr);
  end
//or with no function (positional)
  initial begin
    test::my_arr =  '{default:wr),
                      default:rd),
                      default:unset),
                      default:rd),
                      default:wr),

//or a loop
cmd list[]={wr,rd,unset,rd,wr};
initial
  foreach (list[op]) test::my_arr[op] = '{default:list[op]};