alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post Всем доброго дня. Ситуация такая. Есть система на Zynq Ultrascale+. К PS подключен мастер (на AXI HP Slave у PS), который пишет в память. Если запускаю транзакцию, а затем делаю Xil_DcacheInvalidateRange, то в памяти для процессора изменения не видны (память не меняется якобы). При этом дебагом вижу по сигналам на AXI, что транзакция проходит как надо. Если до запуска транзакции поставить Xil_DcacheFlushRange, то после запуска транзакции и Xil_DcacheInvalidateRange все изменения видны в памяти процессором. До сих пор думал, что Xil_DcacheFlushRange делает так, чтобы все, что видно процессору с учетом кэша, сохраняется в физической памяти. Xil_DcacheInvalidateRange делает всю кэш в диапазоне "грязной" и процессор при обращении к данным из этого диапазона берет их из физической памяти, а не из кэша. Поясните пожалуйста, как же все-таки Xil_DcacheInvalidateRange работает? Что нужно сделать, чтобы при обращении к памяти процессор заново читал данные из нее, а не из кэша? Quote Share this post Link to post Share on other sites More sharing options...
GenaSPB 34 December 25, 2025 Posted December 25, 2025 (edited) · Report post сперва invalidate потом отдаем этот буфер для получения в память данных дожидаемся окончания используем данные Edited December 25, 2025 by GenaSPB 1 Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post А! Сначала invalidate, потом данные закачиваем в память? Попробую, спасибо большое! Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post А с DcacheFlash в какой порядок правильный? Считаем процессором (он там в кэше что-то считает...) затем DcacheFlash чтобы в памяти отобразились все результаты с учетом кэша? Quote Share this post Link to post Share on other sites More sharing options...
GenaSPB 34 December 25, 2025 Posted December 25, 2025 · Report post 2 hours ago, alexPec said: с DcacheFlash в какой порядок правильный? Считаем процессором (он там в кэше что-то считает...) затем DcacheFlash чтобы в памяти отобразились все результаты с учетом кэша? Да, в эту сторону порядок правильный Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 332 December 25, 2025 Posted December 25, 2025 · Report post А какая модель когерентности кэша в ультраскейле? По идее, то, как делал ТС должно было сработать тоже. Ну то есть: 1) старт транзакции, ожидание ее завершения; 2) invalidate кэша; 3) чтение данных. P.S. Хотя... invalidate вроде влияет только на L1, L2 остается в неведении. В таком случае предложенный Геннадием вариант тоже не заработает. Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post 13 минут назад, Arlleex сказал: А какая модель когерентности кэша в ультраскейле? По идее, то, как делал ТС должно было сработать тоже. Ну то есть: 1) старт транзакции, ожидание ее завершения; 2) invalidate кэша; 3) чтение данных. Там cortex A53, про когерентность не скажу. Но делаю как сказал уважаемый GenaSPB (т.е.меяю местами п.1 и п.2) и все работает как надо. Тоже странно кажется. Если мы объявили кэш грязным, потом стали читать, то все равно ядро должно в память за данными лезть. Тоже думал что надежнее по Вашей схеме, т.е. объявить грязным кэш как можно ближе к чтению данных, чтобы проц не накэшировал что-нибудь за время транзакции из предыдущих данных. Может GenaSPB прояснит детали такого поведения кэша? Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 332 December 25, 2025 Posted December 25, 2025 · Report post Т.е. Вы запускали трансфер, потом (не дожидаясь его завершения!) делали invalidate, и по окончании трансфера уже читали память? И именно так делали в первом своем посте, когда говорили, что не работало? Или Вы дожидались окончания трансфера, и только потом invalidate, и данные не видны? 17 минут назад, alexPec сказал: т.е. объявить грязным кэш как можно ближе к чтению данных, чтобы проц не накэшировал что-нибудь за время транзакции из предыдущих данных. Нет, так не нужно думать при операциях с кэшем. Ближе/не ближе - это весьма расплывчато и не надежно. А должно быть консистентно и надежно в любых обстоятельствах. Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post 9 минут назад, Arlleex сказал: Т.е. Вы запускали трансфер, потом (не дожидаясь его завершения!) делали invalidate, Нет, конечно дожидался окончания трансфера, потом invalidate. Потом читал данные Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 332 December 25, 2025 Posted December 25, 2025 · Report post Интересно. А что за второй мастер такой, если не секрет? Это уже, скорее, особенности внутренней сигнализации для кэш-когерентности между разными доменами кэша и памятью. Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post Один - сам процессор, вернее PS, второй - аппаратный ускоритель, подключенный к PS через AXI шину. Quote Share this post Link to post Share on other sites More sharing options...
fpga_dev 11 December 25, 2025 Posted December 25, 2025 (edited) · Report post В теории на 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 December 25, 2025 by fpga_dev Quote Share this post Link to post Share on other sites More sharing options...
alexPec 6 December 25, 2025 Posted December 25, 2025 · Report post Да у меня нет необходимости автоматизировать манипуляции с кэшем. Я вполне представляю когда оптимально данные в кэше или очистить или скинуть в память. Важна простота мастера, чтобы побольше скорость была, и нужно понимание, как (в каком порядке) манипулировать кэшем чтобы получить требуемый результат. Quote Share this post Link to post Share on other sites More sharing options...
fpga_dev 11 December 25, 2025 Posted December 25, 2025 · Report post И вообще вот здесь пишут 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 т.е записывает грязные данные в память Quote Share this post Link to post Share on other sites More sharing options...
fpga_dev 11 December 25, 2025 Posted December 25, 2025 · Report post 23 minutes ago, alexPec said: Важна простота мастера, чтобы побольше скорость была, и нужно понимание, как (в каком порядке) манипулировать кэшем чтобы получить требуемый результат. От мастера тут мало что зависит, ему все это по барабану, все что он может сделать это выставить правильный AxCACHE ну и естественно дождаться последнего bvalid перед тем как рапортовать о завершении операции. Т.е. весь вопрос в софте. И кстати InvalidateCacheRange совсем не быстрая операция. Посмотрите код в xil_cache.c он шагает по всему буфферу с шагом 64 байта и для каждого адреса выдаёт invalidate. Если нужно быстро то лучше все сделать cache coherent, но тут хозяин-барин. Да ещё адрес и размер буфера должен быть кратным 64 иначе работать не будет. Quote Share this post Link to post Share on other sites More sharing options...