Jump to content
    

Как же все таки DcacheInvalidateRange работает?

Всем доброго дня.
Ситуация такая. Есть система на Zynq Ultrascale+. К PS подключен мастер (на AXI HP Slave у PS), который пишет в память. Если запускаю транзакцию, а затем делаю Xil_DcacheInvalidateRange, то в памяти для процессора изменения не видны (память не меняется якобы). При этом дебагом вижу по сигналам на AXI, что транзакция проходит как надо. Если до запуска транзакции поставить Xil_DcacheFlushRange, то после запуска транзакции  и Xil_DcacheInvalidateRange все изменения видны в памяти процессором.

До сих пор думал, что Xil_DcacheFlushRange делает так, чтобы все, что видно процессору с учетом кэша, сохраняется в физической памяти. Xil_DcacheInvalidateRange делает всю кэш в диапазоне "грязной" и процессор при обращении к данным из этого диапазона берет их из физической памяти, а не из кэша.

Поясните пожалуйста, как же все-таки Xil_DcacheInvalidateRange работает? Что нужно сделать, чтобы при обращении к памяти процессор заново читал данные из нее, а не из кэша?

Share this post


Link to post
Share on other sites

  1. сперва invalidate
  2. потом отдаем этот буфер для получения в память данных
  3. дожидаемся окончания
  4. используем данные
     
Edited by GenaSPB

Share this post


Link to post
Share on other sites

А с DcacheFlash в какой порядок правильный? Считаем процессором (он там в кэше что-то считает...) затем DcacheFlash чтобы в памяти отобразились все результаты с учетом кэша?

 

Share this post


Link to post
Share on other sites

2 hours ago, alexPec said:

с DcacheFlash в какой порядок правильный? Считаем процессором (он там в кэше что-то считает...) затем DcacheFlash чтобы в памяти отобразились все результаты с учетом кэша?

 

Да, в эту сторону порядок правильный

Share this post


Link to post
Share on other sites

А какая модель когерентности кэша в ультраскейле?

По идее, то, как делал ТС должно было сработать тоже. Ну то есть:

1) старт транзакции, ожидание ее завершения;
2) invalidate кэша;
3) чтение данных.

P.S. Хотя... invalidate вроде влияет только на L1, L2 остается в неведении. В таком случае предложенный Геннадием вариант тоже не заработает.

Share this post


Link to post
Share on other sites

13 минут назад, Arlleex сказал:

А какая модель когерентности кэша в ультраскейле?

По идее, то, как делал ТС должно было сработать тоже. Ну то есть:

1) старт транзакции, ожидание ее завершения;
2) invalidate кэша;
3) чтение данных.

Там cortex A53, про когерентность не скажу. Но делаю как сказал уважаемый GenaSPB (т.е.меяю местами п.1 и п.2) и все работает как надо. Тоже странно кажется. Если мы объявили кэш грязным, потом стали читать, то все равно ядро должно в память за данными лезть. Тоже думал что надежнее по Вашей схеме, т.е. объявить грязным кэш как можно ближе к чтению данных, чтобы проц не накэшировал что-нибудь за время транзакции из предыдущих данных. Может GenaSPB прояснит детали такого поведения кэша?

Share this post


Link to post
Share on other sites

Т.е. Вы запускали трансфер, потом (не дожидаясь его завершения!) делали invalidate, и по окончании трансфера уже читали память? И именно так делали в первом своем посте, когда говорили, что не работало? Или Вы дожидались окончания трансфера, и только потом invalidate, и данные не видны?

17 минут назад, alexPec сказал:

т.е. объявить грязным кэш как можно ближе к чтению данных, чтобы проц не накэшировал что-нибудь за время транзакции из предыдущих данных.

Нет, так не нужно думать при операциях с кэшем. Ближе/не ближе - это весьма расплывчато и не надежно. А должно быть консистентно и надежно в любых обстоятельствах.

Share this post


Link to post
Share on other sites

9 минут назад, Arlleex сказал:

Т.е. Вы запускали трансфер, потом (не дожидаясь его завершения!) делали invalidate,

Нет, конечно дожидался окончания трансфера, потом invalidate. Потом читал данные

Share this post


Link to post
Share on other sites

Интересно. А что за второй мастер такой, если не секрет?

Это уже, скорее, особенности внутренней сигнализации для кэш-когерентности между разными доменами кэша и памятью.

Share this post


Link to post
Share on other sites

Один - сам процессор, вернее PS, второй - аппаратный ускоритель, подключенный к PS через AXI шину.

Share this post


Link to post
Share on other sites

В теории на  Ultrascale+ можно все сделать  cache coherent и обойтись без танцев с бубном. 

Для этого нужно подключаться через S_AXI_HPCx, выставить правильный AxCACHE и ещё кое-что по мелочи. Вот здесь есть примеры https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842098/Zynq+UltraScale+MPSoC+Cache+Coherency

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

Весь поток данных пускать через когерентный порт накладно поэтому как правило чтение/запись дескрипторов идёт  через HPC, а сами данные обычно через HP или вообще в обход PS.

При этом PS тупо читает индекс головы очереди из регистра, добавляет в конец очереди несколько новых дескрипторов и записывает новый указатель хвоста в регистр, все это без каких либо манипуляций с кешем.

5 hours ago, alexPec said:

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

Invalidate нужно делать до начала операции в противном случае есть шанс что грязные данные будут вытеснены из кеша в память и записаны поверх новых данных пришедших по DMA еще до того как вы сделаете Invalidate.

Edited by fpga_dev

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

И вообще вот здесь пишут

https://docs.amd.com/r/en-US/oslib_rm/Xil_DCacheInvalidateRange

Quote

Note: In Cortex-A53, functionality to simply invalid the cachelines is not present. Such operations are a problem for an environment that supports virtualisation. It would allow one OS to invalidate a line belonging to another OS. This could lead to the other OS crashing because of the loss of essential data. Hence, such operations are promoted to clean and invalidate which avoids such corruption.

Т.е invalidate всегда сначала делает clean т.е записывает грязные данные в память

Share this post


Link to post
Share on other sites

23 minutes ago, alexPec said:

Важна простота мастера, чтобы побольше скорость была, и нужно понимание, как (в каком порядке) манипулировать кэшем чтобы получить требуемый результат. 

От мастера тут мало что зависит, ему все это по барабану, все что он может сделать это выставить правильный AxCACHE ну и естественно дождаться последнего bvalid перед тем как рапортовать о завершении операции. Т.е. весь вопрос в софте. И кстати InvalidateCacheRange совсем не быстрая операция. Посмотрите код в xil_cache.c он шагает по всему буфферу с шагом 64 байта и для каждого адреса выдаёт invalidate. Если нужно быстро то лучше все сделать cache coherent, но тут хозяин-барин.  Да ещё адрес и размер буфера должен быть кратным 64 иначе работать не будет.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...