Ограничение в матрице 2d пикселей - PullRequest
0 голосов
/ 01 июля 2019

Предположим, есть матрица 2d пикселей размером 1920 x 1080. Я хочу ограничить матрицу таким образом, чтобы в окрестности отключенного пикселя (0) были только включенные пиксели (1-255). Шаблон должен быть примерно таким, для меньшей матрицы 5x4:

x x x x 
x 0 x 0
x x x x
x 0 x 0
x x x x

Что может быть лучше для решения этого ограничения, если я не использую цикл foreach, как описано ниже:

foreach(mat[i][j]){
  mat[i][i] = 0;
}
foreach(mat[i][j]){
  if(mat[i][j] == 0) begin
     mat[i-1][j] = $urandom_range(1,255);
     mat[i][j-1] = $urandom_range(1,255);
     mat[i-1][j-1] = $urandom_range(1,255);
     ..etc
  end
}

1 Ответ

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

Прежде всего, если вы хотите сделать ограниченную рандомизацию, вы не можете использовать $urandom(...). Вам нужно использовать классы и функцию randomize().

Поместите пиксели в класс matrix:

class matrix;

  parameter WIDTH = 10;
  parameter HEIGHT = 5;

  rand bit pixels[HEIGHT][WIDTH];

  // ...

endclass

Я использовал bit вместо bit [7:0], потому что мы хотим рандомизировать, включен ли пиксель или нет. Можно использовать bit [7:0], но пиксели в выключенном состоянии маловероятны. Подробнее об этом позже.

Мы моделируем ограничения, утверждающие, что рядом с недопустимым пикселем включены все остальные:

class matrix;

  // ...

  constraint on_next_to_off {
    foreach (pixels[i,j]) {
      if (pixels[i][j] == 0) {
        pixels[i-1][j-1] != 0;
        pixels[i-1][j] != 0;
        pixels[i-1][j+1] != 0;

        pixels[i][j-1] != 0;
        pixels[i][j+1] != 0;

        pixels[i+1][j-1] != 0;
        pixels[i+1][j] != 0;
        pixels[i+1][j+1] != 0;
      }
    }
  }
endclass

Мы можем попытаться запустить это, но это не удастся. Это потому, что мы не занимались крайними случаями. Если пиксель находится на самой верхней строке, то нет никаких пикселей выше для ограничения, поэтому ограничения, которые ссылаются на i-1, не имеют смысла и должны исключать этот случай. То же самое относится к самой нижней строке и к левому и крайнему правому столбцам. Мы должны добавить охрану для всех этих случаев:

class matrix;

  // ...

  constraint on_next_to_off {
    foreach (pixels[i,j]) {
      if (pixels[i][j] == 0) {
        if (i > 1) {
          if (j > 1)
            pixels[i-1][j-1] != 0;
          pixels[i-1][j] != 0;
          if (j < WIDTH-1)
            pixels[i-1][j+1] != 0;
        }

        if (j > 1)
          pixels[i][j-1] != 0;
        if (j < WIDTH-1)
          pixels[i][j+1] != 0;

        if (i < HEIGHT-1) {
          if (j > 1)
            pixels[i+1][j-1] != 0;
          pixels[i+1][j] != 0;
          if (j < WIDTH-1)
            pixels[i+1][j+1] != 0;
        }
      }
    }
  }
endclass

Для отладки мы можем добавить функцию print() к matrix:

class matrix;

  // ...

  function void print();
    foreach (pixels[i]) begin
      string line;
      foreach (pixels[,j])
        line = $sformatf("%s %d", line, pixels[i][j]);
      $display(line);
    end
  endfunction

endclass

Мы можем попробовать это с помощью следующего кода:

module test;

  initial begin
    matrix m = new();
    if (!m.randomize())
      $fatal(0, "randerr");
    m.print();
  end

endmodule

Если вы хотите использовать bit [7:0] вместо bit, ограничения будут работать. Как я упоминал выше, очень маловероятно, что решатель выберет 0 в качестве значения для пикселя, потому что у него есть 255 других возможностей для выбора. Чтобы сделать это более вероятным, вы можете добавить дополнительное ограничение, в котором говорится, что пиксели либо включены, либо выключены с равной вероятностью:

class matrix;

  // ...

  constraint on_or_off_equal {
    foreach (pixels[i,j]) {
      pixels[i][j] == 0 dist {
        0 := 1,
        1 := 1
      };
    }
  }

endclass
...