Constraining a union of enums

What is the solution space for the following union?


typedef enum logic[1:0]{SMALL_SIZE=0, MEDIUM=1, BIG=2} size_t;
typedef enum logic[1:0]{SMALL=0,LARGE=3} size_1_t;
typedef union packed {
  size_t size;
  size_1_t size_1;
  logic[1:0] bit_val;
} sample_union;

Constraining size_1 to value LARGE results in constraint solver error

Solver failed when solving following set of constraints
rand bit[1:0] s1; // rand_mode = ON

constraint INTERNAL_0 // (constraint_mode = ON)
{
((s1 inside {2’h0, 2’h3}) && (s1 inside {[2’h0:2’h2]}));
}
constraint WITH_CONSTRAINT // (from this) (constraint_mode = ON) (testbench.sv:58)
{
(s1 == my_package::size_1_t::LARGE);
}

=======================================================

How can I get the constraint to work and why is the internal constraint ANDing the two enums?

Full code is below


package my_package;
typedef enum logic[1:0]{SMALL_SIZE=0, MEDIUM=1, BIG=2} size_t;
typedef enum logic[1:0]{SMALL=0,LARGE=3} size_1_t;
typedef union packed {
  size_t size;
  size_1_t size_1;
  logic[1:0] bit_val;
} sample_union;

class Base;
  // Properties
  rand bit test_result;
  rand sample_union s1;

endclass

endpackage

module GRG_constraint;
  import my_package::*;

  Base  B_h;
  bit result;
  
initial begin
  B_h = new;  
  if(B_h.randomize() with {
    s1.size_1 == LARGE;
  })
    $display("B_h.s1.size_1 = %0s",B_h.s1.size_1.name());
	else
	  $error("Failed to randomize Base");    
    #10;

end

endmodule


In reply to prang:

This is one of the clarifications made to the recent 1800-2017 LRM. The solver is not allowed to choose a value that lies outside the set of named values of the enum type. This is something constraint solvers were already doing, just not documented.

In your union, 0 is the only value common to the two enum types.

I’m not sure what you are trying to accomplish with the packed union; there might be alternatives like created lists of values with queues or associative arrays.

In reply to dave_59:

The packed union containing enums is part of an interface struct, we ran into this issue while randomizing input values.

I looked at 2017 LRM and found this section. Is this the clarification you referred to?

If a rand variable of packed structure or packed untagged union type has a member of enum type,
the rules in 18.3 restricting the random values of an enum variable shall not apply to that member.
For example:


typedef enum bit [1:0] { A=2'b00, B=2'b11 } ab_e;
typedef struct packed {
ab_e ValidAB;
} VStructEnum;
typedef union packed {
ab_e ValidAB;
} VUnionEnum;

When randomizing a variable of type ab_e, the solver can only select a random value of 2’b00 or
2’b11 (A or B, respectively). However, when randomizing a variable of type VStructEnum or
VUnionEnum, the solver can select 2’b00, 2’b01, 2’b10 or 2’b11.

To me, this implies my standalone testcase should work. If I extend the definition of VUnionEnum as follows

typedef enum bit [1:0] { C=2'b01, D=2'b10 } cd_e;
typedef union packed {
ab_e ValidAB;
cd_e ValidCD;
} VUnionEnum;

when randomizing ValidCD, I have values b01 and b10 available. While randomizing ValidAB, I have values b00 and b11 available. While Randomizing VUnionEnum, I have all 4 values available. Is this right?

In reply to prang:
Sorry I missed the “packed” in your union declaration. This is yet another clarification in the LRM that many not be implemented in your tool. Please contact your tool vendor.