Explicit typecast vs explicit scope cast in ambiguous enumerated type tokens

I have fixed my problem but I don’t entirely understand exactly why one solution worked and the other attempt did not work.

In a testbench I have an initial block that is reading lines out of a command stimulus file and parsing them. In this block I have the following code snippet (the comment is referring to the solution as I’ve had to recreate the original situation for this post, so it’s not applicable in this first snippet):

// Process to the end of the file.
while (!$feof(cmd_fd)) begin
    if ($fgets(cmd_str, cmd_fd)) begin
        // Original design: Synchronize on slowest clock.
        // TODO: May need some other synchronization process.
        @(posedge zynq_clk_125);
        cmd = parse_cmd_line(cmd_str);
        // Have to explicitly cast these as just so happens that the
        // same tokens were used in an enumeration in Delegate package.
        case (cmd.cmd_type)
          TST_LOG_NAME:   do_tst_log_name(cmd, tst);
          TST_GROUP:      do_tst_heading(cmd, tst);
          TST_STEP:       do_tst_heading(cmd, tst);
          TST_INST:       do_tst_heading(cmd, tst);
          TST_REQ:        do_tst_req(cmd, tst);
          TST_ASSERT_REQ: do_tst_req(cmd, tst);
          DLGT_EQ:        do_dlgt_eq(cmd, tst, spi_bfm_mb);
          DLGT_EQ_LIST:   do_dlgt_eq_list(cmd, tst);
          ...

Now, by accident, it turns out that some of these tokens were used identically in another package.

I got the following errors:

# ** Error (suppressible): ./../../testbench/src/gra_tb_v2.sv(245): (vlog-2542) Identifier 'TST_GROUP' is not directly visible.
#    Found multiple Declaration of 'TST_GROUP' through wildcard imports from these packages : cmd_file_pkg (imported at './../../testbench/src/gra_tb_v2.sv:44'), delegate_intrf_pkg (imported at './../../testbench/src/gra_tb_v2.sv:48')
#        If suppressed, the declaration from the first imported package will be used.
# ** Error: ./../../testbench/src/gra_tb_v2.sv(245): (vlog-2730) Undefined variable: 'TST_GROUP'.

Alright, it’s seeing that there have been multiple declarations of the token “TST_GROUP”. So, I tried this. The tokens I want to use are in my cmd_file_pkg in the known_cmds_t enumerated typedef:

     case (cmd.cmd_type)
       ...  
       known_cmds_t'(TST_GROUP):  do_tst_heading(cmd, tst);
       ...

However this ended up producing the same error. I tried this next:

     case (cmd.cmd_type)
       ...  
       cmd_file_pkg::TST_GROUP:  do_tst_heading(cmd, tst);
       ...

This works.

So, my question is why did the explicit scope reference work and the explicit typecast did not work? It seems like both resolve the ambiguity of the token name.

Thanks for any thoughts!

The explicit type cast doesn’t work in this case because the expression being cast (TST_GROUP) needs to be resolved before applying the cast.

Is this true then of most dually defined enumerated types? In another instance (in that cmd_file_pkg where the enumerated type known_cmds_t is defined) I was making calls to functions in the class defined in that confounding package. For instance:

            // Create a delegate entry
            if (tst) begin
                tst.delegate_cmpr(
                    .cmpr(dlgt_cmpr_type'(DLGT_EQ)),
                    .actual($sformatf("%d", axi_transaction.data)),
                    .expected($sformatf("%d", exp_data)),
                    .post_analysis(""),
                    .inst($sformatf("AXI Register Verification: Addr: %x", addr))
                );

Here, the compiler was happy with the explicit typecast. However, I could certainly change these to delegate_intrf_pkg::DLGT_EQ

You might need to provide more code or a concise, complete example that shows why the type cast works in one scenario and not in the other.

In any case, the explicit package reference is likely the best solution anyway.

That’s fair though I’ll be honest, I’m not entirely sure what to share. I’m not entirely sure why the expression as an option in a case statement required the package name resolution, and the expression in the named argument did not. Perhaps because the function already has a parameter type declared where the function is defined, the ambiguity was resolved that the token (in this case DLGT_EQ) was an enumerated type, and it was only needing to know which enumerated type declaration was being expressed.

However your final statement is solid. I’m going to go through and change the typecasts in the function calls to be the package scope resolution and see if that continues to work. If it does, then the takeaway is to use package scope as the primary means to differentiate identical tokens.

QUICK EDIT: I altered one function call to use delegate_intrf_pkg::DLGT_EQ as compared to dlgt_cmpr_type’(DLGT_EQ) and compilation is happy so I’m going to convert the rest and call this solved, with the package scope resolution better for disambiguating than type conversion. Thanks!

Actually I have a theory now as to the difference. Don’t know if it’s reasonable but it works in my head. Since enumerated types basically work back as fancy ways to refer to integers, the function call was effectively expecting a pass-by-value integer. The trouble was that the same token DLGT_EQ referred to two different integers and it didn’t know which one was correct. Typecasting it caused to resolve the token into the integer where that variation was used. In the case statement, the choices are expressions but not strictly always integer types. So it encounters an ambiguous token and couldn’t even tell WHAT it was, let alone how it should be interpreted, so using the scope both gave it a resolving declaration and a value to use as the choice.

But… that could just be BS my brain made up to resolve the issue :D