Multi Layered structure array is not getting created inside constraint policy approach

Hello !

  1. I have bunch of structures and some of them are multi layered.
  2. When I write constraints to create the arrays, it works fine when constrains are added directly in the class as shown below.
Code:
module maui;
    typedef struct {
      rand real aa[];
      rand real bb[]; 
    } ab_struct_s;
    
    typedef struct {
      rand integer step_num;
      rand ab_struct_s oa_0; 
    } gs_struct_s;

    typedef struct {
      rand integer num_fac;
      rand real acl_abc;
      rand gs_struct_s gs_struct[];
      rand integer oha[];
    } fv_struct_s;

    class maui;
        rand fv_struct_s fv_struct;         
    
        constraint fov_struct_c {
           fv_struct.acl_abc == 1.456;
           fv_struct.gs_struct.size() == 2;
           fv_struct.oha.size() == 5;

           fv_struct.gs_struct[0].oa_0.aa.size() == 2;
           fv_struct.gs_struct[0].oa_0.bb.size() == 2;
           
           fv_struct.gs_struct[1].oa_0.aa.size() == 4;
           fv_struct.gs_struct[1].oa_0.bb.size() == 4;
        }
    endclass: maui

    initial begin 
        maui mm = new();
        assert(mm.randomize());
        $display("mm: %0p\n", mm);
    end
endmodule: maui

Output:
mm: '{fv_struct:'{num_fac:436169175, acl_abc:1.456, gs_struct:'{'{step_num:1261410630, oa_0:'{aa:'{1543857315105.327, 8.712996039271156e-07}, bb:'{-2.400445456556682e-11, 0.008615784022056735}}}, '{step_num:2049814541, oa_0:'{aa:'{-1.197309124675167e-12, 95.84324722893554, -0.000162805931616192, -1.270639223379571e-08}, bb:'{-6.877835401836651e-07, 0.008630354298874768, 3.934404050926106e-10, -0.2016849396089287}}}}, oha:'{-2087058360, -747428130, 1443735644, 62258165, -1241979847}}}
  1. When I try the same code using constraint policy list, the simulation doesn’t error out but it doesn’t create the necessary arrays.
Code:
`include "uvm_macros.svh"
 import uvm_pkg::*;

module maui;
    typedef struct {
      rand real aa[];
      rand real bb[]; 
    } ab_struct_s;
    
    typedef struct {
      rand integer step_num;
      rand ab_struct_s oa_0; 
    } gs_struct_s;
    
    typedef struct {
      rand integer num_fac;
      rand real acl_abc;
      rand gs_struct_s gs_struct[];
      rand integer oha[];
    } fv_struct_s;
   
    class policy_base#(type ITEM=uvm_object);
        ITEM item;
        
        virtual function void set_item(ITEM item);
            this.item = item;
        endfunction
   
        function pre_randomize();
            get_plusargs();
        endfunction: pre_randomize

        virtual function get_plusargs();
        endfunction: get_plusargs
    endclass: policy_base

    class policy_list#(type ITEM=uvm_object) extends policy_base #(ITEM);
        rand policy_base#(ITEM) policy[$];
        
        function void add(policy_base#(ITEM) pcy);
            policy.push_back(pcy);
        endfunction
        
        function void set_item(ITEM item);
            foreach(policy[i]) begin 
                policy[i].set_item(item);
            end    
        endfunction
    endclass: policy_list

    // Top Level Constraints 
    class top_gen_base;
        rand policy_base #(top_gen_base) top_policy[$];
        
        rand fv_struct_s fv_struct;

        function new();
        endfunction: new

        function pre_randomize();
            foreach (top_policy[i]) begin 
                top_policy[i].set_item(this);
            end    
        endfunction: pre_randomize 
    endclass: top_gen_base 

    class top_fv_struct extends policy_base #(top_gen_base);
        constraint item_c {
           soft item.fv_struct.acl_abc == 1.456;
           soft item.fv_struct.gs_struct.size() == 2;
           soft item.fv_struct.oha.size() == 5;
        
           // soft item.fv_struct.gs_struct[0].oa_0.aa.size() == 2;
           // soft item.fv_struct.gs_struct[0].oa_0.bb.size() == 2;
           // 
           // soft item.fv_struct.gs_struct[1].oa_0.aa.size() == 4;
           // soft item.fv_struct.gs_struct[1].oa_0.bb.size() == 4;
        }
    endclass: top_fv_struct
 
    class top_gen extends top_gen_base;
        policy_list#(top_gen_base) top_pcy;

        function new();
            top_fv_struct       tfs;

            top_pcy = new;
            tfs = new();

            top_pcy.add(tfs);
            top_policy.push_back(top_pcy);
        endfunction: new
    endclass: top_gen

    initial begin 
        top_gen  tg = new();
        assert(tg.randomize());
        $display("tg = %0p\n", tg);
    end

endmodule: maui

Output:
tg = '{super:'{top_policy:'{maui.policy_base#(top_gen_base)@1810_1}, fv_struct:'{num_fac:70243015, nacl_abc:1.456, gs_struct:'{}, oha:'{2139805943, 894566753, 42405809, 2015313403, -86690185}}},

I am confused what is affecting in the constraint policy which is not allowing to create the struct array.
Any comments would be helpful. Thanks.

Note: Please ignore the garbage value of the real numbers.

You have have a number of differences between the two codes

  1. missing rand qualifiers
  2. commented out constraints on array sizes
  3. missing void return types on functions
  4. constraints on real numbers is a SystemVerilog1800-2023 feature that many tools do not support by default.
  5. UVM code was unnecessary and cluttered up the example.

This code worked for me

module maui;
   typedef struct {
      rand real aa[];
      rand real bb[]; 
   } ab_struct_s;
   
   typedef struct {
      rand integer step_num;
      rand ab_struct_s oa_0; 
   } gs_struct_s;
   
   typedef struct {
      rand integer num_fac;
      rand real acl_abc;
      rand gs_struct_s gs_struct[];
      rand integer oha[];
   } fv_struct_s;
   
class policy_base#(type ITEM);
   rand ITEM item;
   
   virtual function void set_item(ITEM item);
      this.item = item;
   endfunction

endclass: policy_base
   
class policy_list#(type ITEM) extends policy_base #(ITEM);
   rand policy_base#(ITEM) policy[$];
   
   function void add(policy_base#(ITEM) pcy);
      policy.push_back(pcy);
   endfunction
   
   function void set_item(ITEM item);
      foreach(policy[i]) begin 
         policy[i].set_item(item);
      end    
   endfunction
endclass: policy_list
   
   // Top Level Constraints 
class top_gen_base;
   rand policy_base #(top_gen_base) top_policy[$];
   rand fv_struct_s fv_struct;
endclass: top_gen_base 
   
class top_fv_struct extends policy_base #(top_gen_base);
   constraint item_c {
      item.fv_struct.acl_abc == 1.456;
      item.fv_struct.gs_struct.size() == 2;
      item.fv_struct.oha.size() == 5;
      
      item.fv_struct.gs_struct[0].oa_0.aa.size() == 2;
      item.fv_struct.gs_struct[0].oa_0.bb.size() == 2;
      
      item.fv_struct.gs_struct[1].oa_0.aa.size() == 4;
      item.fv_struct.gs_struct[1].oa_0.bb.size() == 4;
   }
endclass: top_fv_struct
   
class top_gen extends top_gen_base;
   rand policy_list#(top_gen_base) top_pcy;
   
   function new();
      top_fv_struct       tfs;
      
      top_pcy = new;
      tfs = new();
      
      top_pcy.add(tfs);
      top_policy.push_back(top_pcy);
   endfunction: new
endclass: top_gen
   
   initial begin 
      static top_gen  tg = new();
      assert(tg.randomize());
      $display("tg = %p\n", tg);
   end
   
endmodule: maui

Hello @dave_59 Thanks for your timely response.

  1. Kinda-off confused how the code works at your end ? I.e. without setting the link to the object using set_item how is the following line item.fv_struct inside the class top_fv_struct works ?

  2. Also, when I tried running your code in the EDA playground with simulator type Mentor Questa 2021.3 I faced the below error. May be this is some old version of the tool.

# ** Error: (vsim-7073) testbench.sv(50): Attempt to dereference null class reference (top_policy[0].policy[0].item.fv_struct) in constraint.
#    Time: 0 ns  Iteration: 0  Process: /maui/#INITIAL#76(#ublk#473273#76) File: testbench.sv Line: 78
# ** Error: Assertion error.
#    Time: 0 ns  Scope: maui File: testbench.sv Line: 78
# tg = '{top_policy:'{@policy_list__1@1}, fv_struct:'{num_fac:x, acl_abc:0, gs_struct:'{}, oha:'{}}, top_pcy:@policy_list__1@1}
# 
# exit