Jump to content

Constraint across properties of array of objects


Recommended Posts

Can a single constraint be used across an array of objects?   i.e. affecting the relation between a property which exists in each of those objects?

I'm trying to do something like an array reduction or sum, but instead of performing it on an array, performing it on the properties of objects in an array.
My goal is to better understand the capabilities of constraints.

Example below: (I do not show my failed attempts.)

//Class animal_c has a property "weight".
//A dynamic array is generated where each element points to an animal.
//The cumulative weight of the animals should be 100.
//How can this be done with constraints?
//Can a constraint expression reference properties referenced by handles?
//
//My goal is to better understand contraints, so I attempt to stuff as much as possible into the constraints.

module top;

  class animal_c;
    rand int   weight;
    constraint weight_legal_c {weight>1; weight<40;}  //allowed weight per animal.

    function void show();
      $display("animal weight:%2d", weight);
    endfunction
  endclass



  class group_of_animals_c;
    rand animal_c  animal_da[];

    constraint number_of_animals_c { animal_da.size() inside {[3:5]}; }

    //As I understand, array objects cannot be constructed in the randomize call that determines the array size.  (T or F?)
    //so, post_randomize seems the natural place to construct the objects in the array.
    function void post_randomize();
      foreach(animal_da[iii]) begin
        animal_da[iii]=new();               //create each object of array
        assert(animal_da[iii].randomize());
      end
    endfunction
    
    function void show_group();
      foreach(animal_da[iii])
        animal_da[iii].show();
    endfunction
  endclass


  initial begin
    group_of_animals_c  group_m;
    group_m             = new();
    assert(group_m.randomize());
    group_m.show_group();
  end

endmodule

https://www.edaplayground.com/x/4Dx5 

Link to comment
Share on other sites

Thanks, David.  Instead of using post_randomize(), I moved some of the work to pre_randomize().  That helped.   I show the code below.  But to get to the heart of the question I have, I will try to further shrink the code in a subsequent post.

//Class animal_c has a property "weight".
//A dynamic array is generated where each element points to an animal.
//The cumulative weight of the animals should be 100.
//How can this be done with constraints?
//Can a constraint expression reference properties referenced by handles?
//
//My goal is to better understand contraints, so I attempt to stuff as much as possible into the constraints.

module top;

  class animal_c;
    rand int   weight;
    constraint weight_legal_c {weight>1; weight<40;}  //allowed weight per animal.

    function void show();
      $display("animal weight:%2d", weight);
    endfunction
  endclass

  class group_of_animals_c;
    int initialized;
    int num_animals;
    rand animal_c  animal_da[];

    function void pre_randomize();
      if (!initialized) begin
        assert( std::randomize(num_animals) with { num_animals inside {[3:12]}; } );
        animal_da = new[num_animals];
        foreach (animal_da[jjj]) begin
          animal_da[jjj]=new();
        end
        initialized=1;
      end
    endfunction

    function void show_group();
      foreach(animal_da[iii])
        animal_da[iii].show();
    endfunction
  endclass


  initial begin
    group_of_animals_c  group_m;
    group_m             = new();
    assert(group_m.randomize());
    group_m.show_group();
  end
endmodule

 

Edited by ljepson74
Improve formatting.
Link to comment
Share on other sites

You can use group_of_animals_c::pre_randomize to create the array to the maximum possible size (12, given your constraint) and construct each element of the array.  The array may shrink during randomization to satisfy other constraints.  Something like this: 

   function void pre_randomize();
      animal_da = new[12];

      foreach(animal_da) begin
        if(animal_da == null) animal_da=new();
      end
    endfunction
 

Using array reduction is the right idea to constraint the sum of animal weights.   You can use a "with" clause to sum the individual animal weights.  Something like this:

    constraint total_weight {
       (animal_da.sum with (item.weight)) == 100;
    }

Link to comment
Share on other sites

I've simplified the example.

Goal: Using constraints in group_of_animals_c, can we constrain the sum of the animal weights?
I'd prefer to avoid procedural code in functions being called.  My goal is understand if/how a constraint might reach thru class handles and affect properties in the objects contained by the object which is being randomized.

 

//Class animal_c has a property "weight".
//For an array of animal_c (as part of class group_of_animals_c),
// the total weight of the animals should be 100.
//How can this be done with constraints?
//Can a constraint expression reference properties referenced by handles?
//
//My goal is to better understand contraints, so I attempt to stuff as much
// as possible into the constraints of class group_of_animals_c.

module top;

  class animal_c;
    rand int   weight;
    constraint weight_legal_c {weight>1; weight<60;}  //allowed weight per animal.

    function void show();
      $display("animal weight:%2d", weight);
    endfunction
  endclass


  class group_of_animals_c;
    rand animal_c  animal_da[3];

    function new();
      foreach (animal_da[jjj])
        animal_da[jjj]=new();
    endfunction

    function void post_randomize();
      int sum_weights=0;
      foreach(animal_da[iii]) begin
        animal_da[iii].show();
        sum_weights+=animal_da[iii].weight;
      end
      $display("***********************Total weight: %0d",sum_weights);
    endfunction
  endclass


  initial begin
    group_of_animals_c  group_m;
    group_m             = new();
    repeat (3) assert(group_m.randomize());
  end

endmodule

https://www.edaplayground.com/x/2NZE

Link to comment
Share on other sites

Note: There will be a reply coming soon by user “jdickol”.  (He recently registered, so his reply likely needs moderator approval, but he messaged me directly.)   Thanks for the solution, jdickol.
 

This is how the constraint can be written:

   constraint total_weight {
      (animal_da.sum with (item.weight)) == 100;
    }


Output:

# animal weight:39
# animal weight:24
# animal weight:37
# ***********************Total weight: 100
# animal weight: 7
# animal weight:36
# animal weight:57
# ***********************Total weight: 100
# animal weight:48
# animal weight:28
# animal weight:24
# ***********************Total weight: 100

 

And because I often refer to old questions I've asked on this forum, I'll post the follow-up question and answer here.
Q: Can the constraint dive further down through class handles?  
A: Yes.   In example below and attached "parasite_m" is a class handle.

animal_da[jjj].weight > animal_da[jjj].parasite_m.weight;

 

accellera_forum_sv_constraint_animals_parasites_question.txt

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...