nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Квартус призывает к перфекционизму?

Странные вещи творятся. Добавил к программе очередной кусочек, откомпилировал. Сунул в папку с QuatCore очередные файлики QuatCoreCode.mif, QuatCoreData.mif (для инициализации внутренних блоков памяти - для кода и для данных соответственно), а также QuatCoreCallTable.v (таблица адресов для вызова функций).

Запускаю компиляцию проекта в квартусе, Analysis&Synthesis проходит нормально, запускается Fitter (Place&Route), доходит до 96% - и натурально крашится:

*** Fatal Error: Access Violation at 0X08DB3606
Module: quartus_fit.exe
Stack Trace:
0x1D3606  : VPR10K20K_QI_FACADE::vpr_qi_main + 0x51B76 (fitter_vpr10k20kmain)
0x1D35CA  : VPR10K20K_QI_FACADE::vpr_qi_main + 0x51B3A (fitter_vpr10k20kmain)

End-trace


причём делает это на двух разных компьютерах - один домашний (Intel Quad Core Q8200, Win7 x64), другой на работе (Intel Atom D510, WinXP 32 бита).

Начальное содержимое памяти вообще на это дело не должен оказывать влияния - по-моему он недостаточно умён, чтобы "прочухать" - "нам тут по старшему биту положили сплошные нули во всех адресах, а модуль сделан как ПЗУ, без линий записи, значит, можно половину логики выкинуть, она никогда не включится". По крайней мере, не замечал, чтобы простейшая программа, явно не использующая и половины команд, приводила к уменьшению количества ЛЭ.

Значит, единственное, что поменялось - QuatCoreCallTable.


Встречался с таким поведением и раньше - адреса в этой таблице чуточку сменились - и ранее синтезировавшийся проект перестал это делать - Could not find fit - пока я не выкинул отладочный выход MemContents. Можно заметить - здесь он есть нижней строкой, а здесь - уже нет. Когда вызываемых функций стало чуть больше - внезапно оно перестало влезать.

Такое поведение меня не сильно удивляло, я и в прошлых "опытах" видел, что стоит попытаться подключить все 32 бита результата - и Place&Route не может "развести дорожки", всё-таки в стареньких ПЛИС и межсоединения не очень мощные.

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

А тут просто "аварийное завершение" - и делай что хошь.

Вот он, ВЕЛИКИЙ И УЖАСНЫЙ МОДУЛЬ, переломивший хребет квартусу:

//адреса для вызова процедур, "вшитые" в модуль QuatCorePC
module QuatCoreCallTable (input [7:0] SrcAddr, output [7:0] addr);
wire [1:0] index = SrcAddr[1:0];
	assign addr = 
		(index==0)? 8'd8:		//AffineAlgorithm
		(index==1)? 8'd140:		//NormSiCo
		(index==2)? 8'd132:		//ShiftOrigin
		(index==3)? 8'd125:		//SwapPoints
		8'bxxxxxxxx;
endmodule


Мне подумалось - может он очень обижается, что мы на полном серьёзе ожидаем, что 2-битное число index может принять какое-то значение, отличное от 0,1,2,3 - и напрочь потеряв веру в человечество убивает себя об стену? Чуть поменял эту штуку:

module QuatCoreCallTable (input [7:0] SrcAddr, output [7:0] addr);

wire [1:0] index = SrcAddr[1:0];
	assign addr = 
		(index==0)? 8'd8:		//AffineAlgorithm
		(index==1)? 8'd140:		//NormSiCo
		(index==2)? 8'd132:		//ShiftOrigin
			    8'd125;		//SwapPoints
	
endmodule

Как ни странно, количество ЛЭ не изменилось, и опять возник Fatal Error на 96% выполнения Place&Route, но уже другой:

*** Fatal Error: Access Violation at 0X052BD8E0
Module: quartus_fit.exe
Stack Trace:
0x1D8E0   : TDC_ACCESSORIES_PATH_TIMING::update_path_requirements + 0x30 (TSM_TDC)
0x37CF5   : clock + 0x41 (MSVCR90)
0x19B089  : VPR10K20K_QI_FACADE::vpr_qi_main + 0x195F9 (fitter_vpr10k20kmain)
0x98D2A   : VPR10K20K_QI_FACADE::operator= + 0x97CDA (fitter_vpr10k20kmain)
0x1B90B1  : VPR10K20K_QI_FACADE::vpr_qi_main + 0x37621 (fitter_vpr10k20kmain)

End-trace

Хотя не уверен, что другая ошибка вызвана внесёнными изменениями - по-моему они просто чередуются, что само по себе странно, процесс, казалось бы, должен быть детерминированным!

А ведь модуль очень простой. Мы лишь хотим получить такие двоичные выходы в зависимости от 2-битного входного адреса:
0:  0000_1000
1:  1000_1100
2:  1000_0100
3:  0111_1101


Видно, что на первом разряде (самый младший мы называем нулевым, и далее до седьмого) вообще всегда ноль должен быть, а нулевой, 4-й, 5-й и 6-й совпадают! Именно на их формирование идёт один ЛЭ, и ещё по одному на второй, третий и седьмой, вот они четыре.

И вот наверное эта подача одинакового сигнала на разные дальнейшие элементы каким-то образом убивает Place&Route. По крайней мере, общая компоновка на удивление чувствительна к одному этому вроде бы безобидному модулю!

В данный момент, мы могли бы обойтись без ЛЭ вообще - ведь у нас выделено 16 адресов SrcAddr для вызова функций, т.е младшие 4 бита как раз задают один из 16. А у нас тут как раз всего 4 "нетривиальных" выхода, так что можно было бы соединить их напрямую:

module QuatCoreCallTable (input [7:0] SrcAddr, output [7:0] addr);
					
	assign addr[0] = SrcAddr[0];
	assign addr[1] = 1'b0;
	assign addr[2] = SrcAddr[1];
	assign addr[3] = SrcAddr[2];
	assign addr[4] = SrcAddr[0];
	assign addr[5] = SrcAddr[0];
	assign addr[6] = SrcAddr[0];
	assign addr[7] = SrcAddr[3];
		
endmodule


Такая схема синтезируется в 0 ЛЭ, что логично. А весь процессор в сборе - в кои-то веки синтезируется, без Fatal Error'ов, в 435 ЛЭ.

Правда, программа не заработает ни разу, потому что в коде прописаны адреса 0..3 для вызова процедур, а их нужно заменить на 0x4, 0xE, 0xA и 0x7, соответственно.

Но в целом забавно - у меня всё роятся разные идеи, как автоматизировать очень "экономную" генерацию этих адресов, учитывая, что их можно переставлять как угодно, но я их старательно задвигал - "ну сэкономишь сейчас 4 ЛЭ, это вообще ни о чём, даже в масштабах 5576ХС6Т, там их 2880, лучше за видеообработку берись!". А вот как будто бы всё-таки надо - почему-то когда этот модуль генерируется автоматически, "в лоб" - потом не работает ни разу!
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

Recent Posts from This Journal

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

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

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

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

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

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

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 18 comments

Recent Posts from This Journal

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

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

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

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

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

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