(vsim-3971) $cast to type

interface file : -

interface ahb_intf(input logic HCLK);

        logic HRESETn;
        logic HREADY;
        logic [1:0] HTRANS;
        logic [2:0] HBURST;
        logic [2:0] HSIZE;
        logic HWRITE;
        logic [31:0] HADDR;
        logic [31:0] HWDATA;
        logic [31:0] HRDATA;
        logic [1:0] HRESP;


        clocking mdrv_cb@(posedge HCLK);
                default input #1 output #0;

                output HTRANS;
                output HBURST;
                output HSIZE;
                output HWRITE;
                output HADDR;
                output HWDATA;
                input HREADY;
                input negedge HRESP;
                input HRDATA;

        endclocking
        clocking mmon_cb@(posedge HCLK);
                default input #1 output #0;

                input HRESETn;
                input HREADY;
                input HTRANS;
                input HBURST;
                input HSIZE;
                input HWRITE;
                input HADDR;
                input HWDATA;
                input HREADY;
                input HRESP;
                input HRDATA;

        endclocking
endinterface

Define file : -

typedef enum bit[1:0] {IDLE, BUSY, NONSEQ, SEQ} transfer_t;
typedef enum bit {READ, WRITE} rw_t;
typedef enum bit [2:0] {SINGLE, INCR, WRAP4, INCR4, WRAP8, INCR8, WRAP16, INCR16} burst_t;
typedef enum bit [2:0] {BYTE, HALFWORD, WORD, WORDx2, WORDx4, WORDx8, WORDx16, WORDx32} size_t;
typedef enum bit [1:0] {OKAY, ERROR, RETRY, SPLIT} resp_t;

slave xtn file : -

class ahb_sxtn extends uvm_sequence_item;

        bit reset;
        bit [31:0] address[$];
        bit [31:0] write_data[$];
        transfer_t trans_type;
        burst_t burst_mode;
        size_t trans_size;
        rw_t read_write;

        bit [31:0] read_data[$];
        rand resp_t response;
        rand bit ready[];




slave monitor code : -

 task ahb_smonitor::monitor();
        begin: mon1
                xtn = ahb_sxtn::type_id::create("xtn");

                do
                begin: collect
                        $cast(xtn.trans_type, vif.mmon_cb.HTRANS);  // error 
                        $cast(xtn.burst_mode, vif.mmon_cb.HBURST);  // error
                        $cast(xtn.trans_size, vif.mmon_cb.HSIZE);   // error
                        $cast(xtn.read_write, vif.mmon_cb.HWRITE);  // error
                        $cast(xtn.response, vif.mmon_cb.HRESP);     // error
                        xtn.address.push_back(vif.mmon_cb.HADDR);   // error

                        if((xtn.trans_type == IDLE) && (vif.HRESETn == 1))
                        begin
                                @(vif.mmon_cb);
                                `uvm_info(get_type_name(), "IDLE Transaction Detected..", UVM_MEDIUM)
                            ---------------------
                            ---------------------
                            

while executing the code I am getting the following error : -

# ** Error: (vsim-3971) $cast to type 'enum bit[1:0] ahb_spkg::transfer_t' from 'reg[1:0]' failed in file /work/lk/projects/sim../../env/ahb/ahb_slv_agent/ahb_smonitor.svh at line 84.
 ** Error: (vsim-3971) $cast to type 'enum bit[2:0] ahb_spkg::burst_t' from 'reg[2:0]' failed in file /work/lk/projects/sim/../../env/ahb/ahb_slv_agent/ahb_smonitor.svh at line 85.

I am using Questa sim simulator

can anyone tell me the problem ?

In reply to lalithjithan:

You want to cast using the ’ operator:


xtn.trans_type = transaction_t'(vif.mmon_cb.HTRANS); 
xtn.burst_mode = burst_t'(vif.mmon_cb.HBURST);
xtn.trans_size = size_t'(vif.mmon_cb.HSIZE);
xtn.read_write = rw_t'(vif.mmon_cb.HWRITE);
xtn.response = resp_t'(vif.mmon_cb.HRESP);

Section 6.19.4 of the LRM does refer to Section 6.24.2 (Dynamic casting with $cast), but I believe that will only work with compatible data types. Since reg is 4-state and bit is 2-state, the assignment types are not compatible.

In reply to lalithjithan:

There is no cast needed. SystemVerilog differentiates between the simple cast (using ') and the dynamic casting (using $cast). For the details see chapter 6.24 in the LRM. The details cannot be explained in a few lines only.
What you are doing can be simply done using an assignment like

xtn.trans_type = vif.mmon_cb.HTRANS;

In reply to chr_sue:

This is wrong. When you are assigning to an enumerated type, you can only assign the same enumerated type or you need to use a cast.

Section 6.19.4:

An enum variable or identifier used as part of an expression is automatically cast to the base type of the enum declaration (either explicitly or using int as the default). A cast shall be required for an expression that is assigned to an enum variable where the type of the expression is not equivalent to the enumeration type of the variable.

The correct assignment is:


xtn.trans_type = transfer_t'(vif.mmon_cb.HTRANS);

In reply to cgales:

Agreeing with Chuck, you must use the static cast operator
typename’(expression)
when making an assignment to an enumerated type and the RHS expression type does not match. And here’s why:

Because the LRM says so. :smiling_face:

Seriously, the rules in section 6.22 of the 1800-2017 LRM make enumerations strong types, meaning they do not have implicit casting rules, for example byte to int, or int to real do.

It would help if people did not think of $cast as a cast, rather it is an assignment compatibility test. The only place you must use $cast is when there is a possibility for the test to fail. That can happen when downcasting class handles, or when you have assignments involving parameterized types.