Система Verilog Рандомизация 2-мерного динамического массива - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь использовать системный решатель ограничений 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, я считаю, что размер массива будет решен до присвоения значения массиву. </p>

Кроме того, я также хотел узнать, можно ли использовать уникальные для двумерного динамического массива.

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Попробуйте это!класс ABC;rand bit [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

module 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

0 голосов
/ 12 октября 2018

Вы не можете использовать генератор случайных чисел (RNG), чтобы перечислить все возможные решения вашей проблемы.Это не построено для этого.RNG может предоставить вам одно из этих решений при каждом вызове randomize().Не гарантируется, однако, что это дает вам другое решение с каждым вызовом.Скажем, у вас есть 3 решения, S0, S1, S2.Решатель может дать вам S1, затем S2, затем S1, затем S1, затем S0 и т. Д. Если вы знаете, сколько существует решений, вы можете остановиться, как только увидите ихвсе.Как правило, однако, вы не знаете этого заранее.

Однако, что может сделать ГСЧ, это проверить, является ли решение, которое вы предлагаете, правильным.Если вы перебираете все возможные решения, вы можете отфильтровать только те, которые являются правильными.В вашем случае у вас есть 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().Однако вам это не нужно, если вы хотите проверить, является ли решение действительным.Это связано с ограничениями размеров массивов в диапазоне от arrangement до solution_array.

...