系统Verilog二维动态阵列随机化

时间:2018-10-11 11:53:40

标签: system-verilog

我正在尝试使用系统Verilog约束求解器来解决以下问题陈述:

我们有N个球,每个球具有唯一的权重,因此需要将这些球分配到各个组中,以使每个组的权重不超过阈值(MAX_WEIGHT)。 现在我想找到所有可能的解决方案。我在SV中编写的代码如下:

`define NUM_BALLS 5
`define MAX_WEIGHT_BUCKET 100

class weight_distributor;
int ball_weight [`NUM_BALLS];

	rand int unsigned solution_array[][];

	constraint c_solve_bucket_problem
	{		
		foreach(solution_array[i,j]) {
			solution_array[i][j] inside {ball_weight};
			//unique{solution_array[i][j]};
			foreach(solution_array[ii,jj])
				if(!((ii == i) & (j == jj))) solution_array[ii][jj] != solution_array[i][j];
		}
		foreach(solution_array[i,])
			solution_array[i].sum() < `MAX_WEIGHT_BUCKET;

	}

	function new();
		ball_weight = {10,20,30,40,50};
	endfunction

	function void post_randomize();		
		foreach(solution_array[i,j])
			$display("solution_array[%0d][%0d] = %0d", i,j,solution_array[i][j]);
		$display("solution_array size = %0d",solution_array.size);
	endfunction
   endclass

module top;
	weight_distributor weight_distributor_o;
	initial begin
		weight_distributor_o = new();
		void'(weight_distributor_o.randomize());	
	end
endmodule

我在这里面临的问题是我希望基于约束solution_array [i] .sum()<`MAX_WEIGHT_BUCKET;来随机确定数组的两个维度的大小。 。根据我对SV约束的理解,我相信在将值分配给数组之前,将解决数组的大小。

此外,我还想知道unique是否可以用于2维动态数组。

2 个答案:

答案 0 :(得分:0)

您不能使用随机数生成器(RNG)来列举问题的所有可能解决方案。它不是为此而构建的。每次调用randomize()时,RNG可以为您提供这些解决方案之一。但是,不能保证每次调用都会为您提供不同的解决方案。假设您有3个解决方案,S0, S1, S2。求解器可以给您S1,然后给S2,然后给S1,然后给S1,然后给S0,依此类推。如果您知道有多少个解决方案,您可以在看到所有内容后停止。通常,尽管如此,您事先并不知道这一点。

但是,RNG可以执行的操作是检查您提供的解决方案是否正确。如果遍历所有可能的解决方案,则只能过滤出正确的解决方案。在您的情况下,您有N个球,最多N个组。您可以先将每个球放在一个组中,然后尝试一下这是否是正确的解决方案。然后,您可以将2个球放在一个组中,将所有其他N-2放在一个组中。您可以将另外两个球放到一个组中,将所有其他球放到一个组中。您可以开始将2个球放入一组,将另外2个球放入一组,而将所有其他N-4放入一组。您可以继续执行此操作,直到将所有N个球放入同一组。我不太确定如何轻松列举所有解决方案。组合学可以为您提供帮助。在此方法的每个步骤中,您都可以检查某个球的布置是否满足约束条件:

// Array describing an arrangement of balls
// - the first dimension is the group
// - the second dimension is the index within the group
typedef unsigned int unsigned arrangement_t[][];

// Function that gives you the next arrangement to try out
function arrangement_t get_next_arrangement();
  // ...
endfunction

arrangement = get_next_arrangement();

if (weight_distributor_o.randomize() with {
  solution.size() == arrangement.size();
  foreach (solution[i]) {
    solution[i].size() == arrangement[i].size();
    foreach (solution[i][j])
      solution[i][j] == arrangement[i][j];
  }
})
  all_solutions.push_back(arrangement);

现在,让我们看一下weight_distributor。我建议您在自己的约束中编写每个需求,因为这会使代码更具可读性。

您可以缩短使用双unique运算符编写的唯一性约束:

class weight_distributor;

  // ...

  constraint unique_balls {
    unique { solution_array };
  }

endclass

您已经有一个约束,每个组最多只能有MAX_WEIGHT

class weight_distributor;

  // ...

  constraint max_weight_per_group {
    foreach (solution_array[i])
      solution_array[i].sum() < `MAX_WEIGHT_BUCKET;
  }

endclass

由于解决了数组大小的问题,因此不可能编写约束来确保您可以使用简单的调用randomize()计算出有效的解决方案。但是,如果要检查解决方案是否有效,则不需要此功能。这是由于在arrangementsolution_array之间对数组大小的限制。

答案 1 :(得分:0)

尝试一下!!     ABC类;     rand位[3:0] md_array [] []; //未知大小的多维数组

constraint c_md_array { 
 // First assign the size of the first dimension of md_array
 md_array.size() == 2; 

 // Then for each sub-array in the first dimension do the following:
 foreach (md_array[i]) {

    // Randomize size of the sub-array to a value within the range
    md_array[i].size() inside {[1:5]};

    // Iterate over the second dimension 
    foreach (md_array[i][j]) {

       // Assign constraints for values to the second dimension
       md_array[i][j] inside {[1:10]};
     }
  }
 }

endclass

模块tb;

initial begin
  ABC abc = new;
  abc.randomize();
  $display ("md_array = %p", abc.md_array);
end

endmodule

https://www.chipverify.com/systemverilog/systemverilog-foreach-constraint