Перейти к содержанию

    

Запрет оптимизации (выбрасывания) неподключенной логики в Vivado

Тема стара, как мир, тем не менее, однозначного решения найти не удалось.

 

Прототипируем фрагмент дизайна ASIC на самой большой UltraScale. Около 5000 ног интерконнекта висит в воздухе внутри FPGA, поэтому Vivada выбрасывает все, что не завязано на физические выводы, после чего часть дизайна перестает отзываться на запросы по интерфейсу, торчащему из FPGA.

В Quartus есть замечательный неинвазивный инструмент как раз для такого случая - Virtual Pin, который позволяет сохранить возможность эффективного синтеза/раскладки и сохранить нужную логику от выбрасывания.

 

Полный дизайн ASIC-а (включая подсистему, которую мучаю я) собирается и работает без проблем (т.к. в нем все ноги моей подсистемы подключены). Стоит задача собрать автономный дизайн с подсистемой, чтобы не ждать 1,5 дня на пересборку общего дизайна.

 

Что испробовано на данный момент:

1. (* keep = "true" *) на сигналы, висящие в воздухе

Как оказалось, это не уберегает логику, привязанную к этому сигналу от оптимизации. Через интерфейс видится только часть дизайна.

 

2. (* dont_touch = "true" *) на сигналы, висящие в воздухе

Эта директива работает "рекурсивно" ко всей подключенной логике, запрещая какую-либо оптимизацию вообще, из-за чего на пустом месте растет resource optimization и появляются большие слаки. Через интерфейс все равно видится только часть дизайна.

 

3. (* mark_debug = "true" *) на сигналы, висящие в воздухе

Какого-либо эффекта (в т.ч. автоматического создания ILA) не замечено. Через интерфейс видится только часть дизайна.

 

4. Выделение всей подсистемы в обертку в режиме Out-of-context.

OOC, как я понял, работает только для синтеза, если входы подсистемы болтаются в воздухе, то на этапе implementation Vivado выдает ошибку - входы LUT должны быть подключены. Если на входы подсистемы повесить константу, implementation видит "constant propagation" и выбрасывает еще больше логики.

 

На сайте Xilinx и нашем форуме поискал, в основном предлагаются перечисленные способы.

 

Есть ли еще какие-либо человеческие способы, которые можно попробовать до того, как возиться с сдвиговыми регистрами на входах и выходах?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

Да в Vivado не все так просто. Например вариант с (* dont_touch = "true" *) или (* mark_debug = "true" *)  прекрасно работает если нет иерархии - то есть делает виртуальные порты  если логика расположена в этом же модуле.

...
(* mark_debug = "true" *)
logic [7:0]  in_reg1;
(* mark_debug = "true" *)
logic [7:0]  in_reg2;

(* mark_debug = "true" *)
logic [7:0]  ou_reg1;
(* mark_debug = "true" *)
logic [7:0]  ou_reg2;

always_ff @(posedge clk) begin
  ou_reg1 <= in_reg1 + in_reg2;
  ou_reg2 <= in_reg1 ^ in_reg2;
end
...

А вот для иерархии этого уже не достаточно - на выходе нужна доп прокладка  в виде промежуточной цепи с keep атрибутом или временных регистров чтобы оптимизация не выбрасывала логику из нижележащего модуля.  Ну и на нижележащий модуль надо навесить (* keep_hierarchy="yes" *)

Spoiler

(* keep_hierarchy="yes" *)
module test #(parameter WH=8) (
  input  wire           clk, 
  input  wire  [WH-1:0] in1,
  input  wire  [WH-1:0] in2,
  output logic [WH-1:0] ou1,
  output logic [WH-1:0] ou2
);

always_ff @(posedge clk) begin
  ou1 <= in1 + in2;
  ou2 <= in1 ^ in2;
end
endmodule

module top (
  input  wire  clk, //
  output logic ou
);

localparam PIN_WH = 4;

(* mark_debug = "true" *)
logic [PIN_WH-1:0]  in_pin1;
(* mark_debug = "true" *)
logic [PIN_WH-1:0]  in_pin2;

(* keep="true" *)
logic [PIN_WH-1:0]  ou_pin1;
logic [PIN_WH-1:0]  ou_pin2;

(* mark_debug="true"*)
logic [PIN_WH-1:0]  ou_reg1;
(* mark_debug="true"*)
logic [PIN_WH-1:0]  ou_reg2;

test #(.WH(PIN_WH)) i_test (
  .clk(clk    ),
  .in1(in_pin1),
  .in2(in_pin2),
  .ou1(ou_pin1),
  .ou2(ou_pin2)
);

assign ou_reg1 = ou_pin1;

always_ff @(posedge clk) begin
  ou_reg2 <= ou_pin2;
end

endmodule

Да и (* mark_debug = "true" *) не создает ILA сам, а только помечает цепи чтобы их можно было легко подключить. Для создания ILA надо либо ручками это делать открыв проект после синтеза. Либо скриптом tcl подключив последний как constraint файл.

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
On 3/11/2019 at 4:07 PM, hdl_student said:

2. (* dont_touch = "true" *) на сигналы, висящие в воздухе

Эта директива работает "рекурсивно" ко всей подключенной логике, запрещая какую-либо оптимизацию вообще, из-за чего на пустом месте растет resource optimization и появляются большие слаки. Через интерфейс все равно видится только часть дизайна.

а если в два приёма?

1. синтезим нужную часть подсистемы в режиме оut-of-context (со всеми мыслимыми и немыслимыми оптимизациями)

2. делаем обёртку под неё (stub) и подключаем подсистему как black-box, а в обёртке уже делаем где надо keep|dont_touch

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация