ljepson74 Posted August 15, 2020 Report Share Posted August 15, 2020 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 Quote Link to comment Share on other sites More sharing options...
David Black Posted August 17, 2020 Report Share Posted August 17, 2020 Or... Use pre-randomize to establish the size and create the array, then you can constrain element creation normally. Determining the size is usually less complex than constraining the contents, so this approach may be more flexible. Quote Link to comment Share on other sites More sharing options...
ljepson74 Posted August 20, 2020 Author Report Share Posted August 20, 2020 (edited) 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 August 20, 2020 by ljepson74 Improve formatting. Quote Link to comment Share on other sites More sharing options...
jdickol Posted August 20, 2020 Report Share Posted August 20, 2020 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; } ljepson74 1 Quote Link to comment Share on other sites More sharing options...
ljepson74 Posted August 20, 2020 Author Report Share Posted August 20, 2020 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 Quote Link to comment Share on other sites More sharing options...
ljepson74 Posted August 20, 2020 Author Report Share Posted August 20, 2020 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.