Jump to content

    

Расслабление констрейнов по клоку, используемому только внутри модуля

Вводная:

Vivado, VU13P

У всего проекта интерфейсный клок и клок вычислителя.Клок вычислителя (clk_core) в несколько раз выше интерфейсного (clk_ctrl).

Сам проект содержит под сотню вычислителей,с которыми общаются на интерфейсном клоке, а сами вычислители молотят на клоке вычислителя.

Для улучшения QoR закрепил каждый вычислитель на конретные pBlock (до этого результаты WNS по конфигу 1 и конфигу 2 или 3 существенно различались).

 

 

Собственно все эксперименты по синтезу & PnR провожу в трёх конфигах:

конфиг 1 флоу с одним вычислителем

конфиг 2 флоу с одном SLR, полностью забитым вычислителями

конфиг 3 кристалл полностью забит вычислителями

 

 

Так вот - несмотря на то, что по факту ничего не поменялось (все вычислители зафикшены на pBlock) результаты в кейсе 2 и 3 деградируют по WNS.

Появилось подозрение, что в этих кейсах вивадо пытается построить CLOCK ROOT от SLR/всего кристалла, что не является для меня необходимым.

Все вычислительные клоки каждого вычислителя не обязаны быть синхронными между собой,  а коммуницируют вычислители с центром управления на медленном интерфейсном клоке, хочется дать вивадо информацию о том, чтобы позволить строить клоковое дерево независимо внутри каждого вычислителя и соответствующим образом выбирать локалько CLOCK ROOT.

 

 

Вопрос

Поскольку рантайм адовый - не хочется тратить время на эксперименты, а описать послабления наверняка:

1. Правильно ли понимаю, что для начала надо поименовать все клоки разных вычислителей?

Можно ли применить create_generated_clock к порту модуля?

2. Правильно ли будет потом применить между этими клоками  set_clock_groups -asynchronous ? Как  перенесёт вивадо эту команду с числом аргументов свыше сотни?

3. Либо надо писать set_clock_groups для пар каждого с каждым? Вот вроде как чутка похожий кейс: https://forums.xilinx.com/t5/Timing-Analysis/Asynchronous-inter-clock-paths-failed-to-meet-timing/td-p/761677

 

 

Share this post


Link to post
Share on other sites

Постою послушаю (ц)

По поводу пункта 2 - если между блоками (и клоками тоже) нет никакого взаимодействия, то вряд ли set_clock_groups -asynchronous даст какой-либо эффект. Ваша задача заставить построить clock tree не так, как этого хочет сама вивада. А она, по всей видимости делает один Clock root. Я пытался недавно решать подобную задачу, наставив bufg, сгенерировав тем самым обособленные клоки. Но при превышении этих bufg количества примерно 24 она их не смогла развести (см. UG949, High Fanout Clocks). Может быть в вашем случае будет достаточно породить клоки не на каждый отдельный вычислитель, а столько, сколько вивада сможет разместить.

Share this post


Link to post
Share on other sites
59 minutes ago, Doka said:

Появилось подозрение, что в этих кейсах вивадо пытается построить CLOCK ROOT от SLR/всего кристалла, что не является для меня необходимым.

Думаю, что дело не в желании, а в необходимости. При увеличении заполнения кристалла некоторые элементы вычислителей, скорее всего, размазываются по многим регионам.
Я бы настоятельно рекомендовал локализовать непосредственно каждый вычислитель из конфиг 2 в отдельный блок. Тогда сразу увидите, где у Вас возникают проблемы и сможете предсказуемо влиять на результат.

В целом, Вам уже более развёрнуто ответили:

 

create_generated_clock можно назначить или на клоковый вход синхронного элемента или на порты клоковых элементов. Есть в доках.

Share this post


Link to post
Share on other sites
5 minutes ago, TRILLER said:

При увеличении заполнения кристалла некоторые элементы вычислителей, скорее всего, размазываются по многим регионам.
Я бы настоятельно рекомендовал локализовать непосредственно вычислители из конфиг 2 в отдельные блоки

так у меня во всех конфигах вычислители каждый в своём лоченом pBlock - без этой меры просто не разводилось на уровне SLR/кристалла.

поэтому меня и удивило, что QoR так сильно зависит от "соседей":

конфиг 1 соседей нет

конфиг 2 соседи только в SLR

конфиг 3 соседи - весь кристалл

 

% утилизации каждого pBlocks в текущем конфиге не выше 70

Share this post


Link to post
Share on other sites

Вообще-то не должен, только опосредованно.
Вычислитель влезает в один тактовый регион?
Сколько у Вас Clock Skew на плохих путях? Если до 400пик - то это нормально и улучшить что-то в ряд ли получится. Да и не стоит.
Сколько регионов пересекает поломанный путь?

 

Share this post


Link to post
Share on other sites
2 hours ago, TRILLER said:

Вычислитель влезает в один тактовый регион?

Сколько регионов пересекает поломанный путь?

тут немного всё сложно, в том плане, что из-за того, что разные CLOCKREGION имеют разные размеры (отличающиеся почти в 2 раза), то вычислители объединены в мини-кластеры таким образом, чтобы  bPlock были сформированы из таких CLOCKREGIONs чтобы размеры (в LUT) получившихся bPlock были +/- идентичны.

На данный момент у меня один bPlock это квадрат 2х2 CLOCKREGION

 

2 hours ago, TRILLER said:

Сколько у Вас Clock Skew на плохих путях? Если до 400пик - то это нормально и улучшить что-то в ряд ли получится. Да и не стоит.

в конфиге 1 после роутинга -0.2нс

в конфиге 2/3 от -1.5нс до -6 нс в зависимости от условий

 

Share this post


Link to post
Share on other sites
1 hour ago, Doka said:

в конфиге 1 после роутинга -0.2нс

в конфиге 2/3 от -1.5нс до -6 нс в зависимости от условий

Даа, тогда Ваше первое предположение обретает почву.
Тут либо что-то в схеме приводит к такому поведению, либо глюки софта для SLR кристалла.
Думаю, действительно стоит попробовать явно развязать клоки для отдельных кластеров.
Я делаю так. В коде:

(* dont_touch = "true" *)wire       clkd_ibuf;
(* dont_touch = "true" *)wire       clkd;
(* dont_touch = "true" *)wire       clkj;

IBUFDS u_clkd_ibuf(
    .I                  (CLK_200_P),
    .IB                 (CLK_200_N), 
    .O                  (clkd_ibuf));    

BUFG u_clkd(
    .I                  (clkd_ibuf), 
    .O                  (clkd));  	

BUFG u_clkj(
    .I                  (clkd_ibuf), 
    .O                  (clkj)); 

В констейнах:

set_false_path -through [get_pins {u_aaa/u_clkd_ibuf/O}]
create_clock -period 5.000 -name clkd [get_pins u_aaa/u_clkd/O]
create_clock -period 5.000 -name clkj [get_pins u_aaa/u_clkj/O]
set_clock_groups -name async_groups -asynchronous -group clkd -group clkj

Позволяет надёжно развязать клоки из одного источника. Всё остальное ненадёжно(или не нашёл..)
Поставьте по буферу на кластер. Если не поможет, тогда надо схему ковырять, на мой взгляд.
Да, IBUFDS нужно заменить на BUFG, если внутренне сгенерированный клок.

Share this post


Link to post
Share on other sites

Не могу ничего сказать про Vivado, но Quartus лучше реагирует на -exclusive, чем на -asynchronous.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now