nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

Что там со "старым" алгоритмом обнаружения?

Пока я развлекался с фильтрами БИХ, компьютер долго и мучительно моделировал первые 16 миллисекунд работы QuatCore + GPU со "старым" алгоритмом обнаружения. И пришёл практически к такому же ошибочному списку пятен, что и "в железе":

(257; 85), 65452,  в железе было (255; 83), 65441
(466; 112), 65027, в железе было (471; 115), 65006
(715; 126), 0,     в железе было (717; 130), 0


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

Вся "осциллограмма" - на экране, все 400 000 тактов, выбирай любой :) Осталось только понять, откуда начать расследование...

Видимо, ошибка происходит уже после 8 мс, поскольку до них у нас оба списка были адекватными. Стоит посмотреть место, где пятно переносится из списка ActivePoints в AllPoints. Мы ещё ни разу это место не проверяли, может, там и есть ошибка.


Впрочем, найти это место на осциллограмме не так-то уж просто! В итоге написал отдельный дурацкий модулёк:

module Debug8C_PC (input clk, input [7:0] PC, input VSync, output reg RemovePoint = 1'b0);

always @(posedge clk)
	RemovePoint <= VSync? 1'b0 : (PC == 8'h8C)? 1'b1 : RemovePoint;

endmodule


Чтобы он нашёл у меня, когда мы первый раз попадаем на этот фрагмент:

89  CD0C  @@RemoveBlob: X       AllPoints
8A  FCB4                [SP]    CALL(ListOp)
8B  CDDD                X       Y           ;теперь [X] ссылается уже не на обработанную и удалённую точку, а на предыдущую, так что всё верно
8C  B021                JMP     @@ResetPending  ;ура...                 
8D  2022  @@FinalRange: ACQ     WholeRow


Значение PC = 0x89 ещё возможно, когда мы на самом деле не выполняем этот фрагмент, т.к счётчик "убегает вперёд" аж на 2 такта, т.е когда PC = 0x89, выполняется часть SrcAddr для PC = 0x88 и часть DestAddr для PC = 0x87.

И PC = 0x8D уже вовсю возникает на каждой строке. А вот PC = 0x8C - это непременно означает, что мы только что удалили пятно.

После очередной очень долгой симуляции, мы наконец-то находим искомое место:


Строка изображения 0x84 = 132. Вот она:


Одна из первых строк, в которые попадает аж ТРИ пятна. Мы на удивление последовательны: сначала делали симуляцию с одним пятном, пока оно не заработало корректно. Одна ошибка затаилась, пока на одной строке не оказалось ДВА пятна, и вот вышли на ТРИ :)

Чуть отмотав назад "осциллограмму", удалось найти, где начались проблемы: одно строкой ранее, вот это место:


Ещё не закончилась обработка предыдущей строки, а буфер заданий (входной буфер GPU) уже был заполнен до упора. Давали туда одно задание (DestAddr = 0x20, что означает ACQ) до координаты X = 0x2C3 = 707 (это крайнее правое пятно) - застряли, пока не дошли до конца текущей строки (ACQ WholeRow). А начали укладывать следующее задание до координаты X = 0x2CC = 716 - и застряли, очевидно, до синхроимпульса (ACQ HSync). И всё бы ничего, но потом мы запросили результаты по ещё не оконченной строке:


И СНОВА ЗАСТРЯЛИ, поскольку имевшиеся уже результаты были затёрты, когда пришёл синхроимпульс! Поэтому мы начали ждать первые результаты по следующей строки, и ошибочно забрали их!

Дальше не буду вас мучать кучей скриншотов, опишу словами. Получив яркую точку на "крайнем правом отрезке" (примерно от 754 до 1023) с координатой ВНЕЗАПНО 0xD4 = 212, алгоритм "не чувствуя подвоха" сравнивает её с пятном слева от себя с координатой центра 0x2F2 = 754 и диаметром 0x43 = 67. И понимает, что она ЛЕВЕЕ ПРАВОЙ КРОМКИ ЭТОГО ПЯТНА (опять же ВНЕЗАПНО), а значит, нужно это пятно расширить. Вот в результате этого расширения у нас и получается X-координата "ни к селу ни к городу" 467 и ОТРИЦАТЕЛЬНЫЙ ДИАМЕТР.

Потом похожие вещи происходят с другими пятнами: в этот раз точки обнаруживаются правее, чем надо, уже внутри этих пятен, и в результате RightMerge эти пятна "схлопываются" - их диаметр становится нулевым или вовсе отрицательным. А дальше они очень быстро "выбывают из игры" и попадают в список AllPoints.

Забавно, что прерывания UFLO (исчерпание очереди заданий, когда GPU не знает что делать, а пиксели уходят, никого не ждут) и OFLO (переполнение очереди результатов GPU, которых не успевает забрать процессор) нам здесь не помогают: заполнение очереди заданий это нормальное явление. В общем-то, всё могло сработать правильно, если бы у нас не стирались результаты работы по приходу строчного синхроимпульса.

Нда, мне такое исполнение с самого начала не очень нравилось, надо прислушиваться к себе!

Как водится, есть несколько вариантов, как исправить ситуацию.
Можно просто повысить вместимость буферов, чтобы не возникало такой заминки. Самое простое, одну циферку переправляешь, и потом танцуешь с бубном, чтобы Place&Route нормально всё это развело и дало максимальную частоту 25 МГц или выше.

А можно улучшить логику работы видеопроцессора. Сейчас мне это представляется так:

Удаления всех результатов не происходит, что к тому же позволит при необходимости заменить FIFO на логических элементах (см. раз, два, три) на модуль памяти. Одновременный сброс всех ячеек памяти - штука очень специфическая, лучше к такому не прибегать!

Вместо этого в результаты добавляется младший бит номера строки, по сути "чётность". Тем самым мы можем отличить "старые" результаты от "новых". Также уже на выходе имеется 1-битный регистр, указывающий, какая строка нам нужна сейчас? Он переключается отдельной командой с QuatCore, которая вызывается, когда мы начинаем новую строку.

И дальше логика такова: если мы запрашиваем результат и чётность строки в нём совпадает - всё хорошо, мы получаем этот результат. Если чётность не совпала - выполнение останавливается, пока мы не вышвырнем (один за другим) все результаты с неправильной чётностью. Это и будет механизмом, позволяющим "восстановиться" после того, как однажды за время работы туда попадёт ошибочное задание.


Фух, проблема ясна, сейчас исправим...
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • Нахождение двух самых отдалённых точек

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

  • Слишком общительный счётчик

    Вчера я чуть поторопился отсинтезировать проект,параметры не поменял: RomWidth = 8 вместо 7, RamWidth = 9 вместо 8, и ещё EnableByteAccess=1, чтобы…

  • Балансируем конвейер QuatCore

    В пятницу у нас всё замечательно сработало на симуляции, первые 16 миллисекунд полёт нормальный. А вот прошить весь проект на ПЛИС и попробовать "в…

  • Огари разговаривают

    Сегодня по пути на работу встретил огарей прямо в Лосином острове, на берегу Яузы. Эти были на удивление бесстрашны, занимались своими делами, не…

  • Обнаружение на новом GPU - первые 16 мс

    Закончилась симуляция. UFLO и OFLO ни разу не возникли, что не может не радовать. За это время мы дошли до строки 0x10F = 271. Поглядим дамп памяти:…

  • Новый GPU - наконец-то результаты

    Первые 9 миллисекунд отработаны штатно, безо всяческих UFLO и OFLO. За это время успели дойти до строки 139, она показана голубым: И дамп памяти…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments