nabbla (nabbla1) wrote,
nabbla
nabbla1

Category:

QuatCoreImmTable здорового человека без вредных привычек

Извините, если кого испугал названием предыдущей записи (QuatCoreImmTable короновирусного больного). Нужна была ещё одна градация после здорового человека и курильщика. Та ужасающая таблица, которая при длине в 24 записи занимала 56 ЛЭ (и задержку распространения 30 нс), уступила своё место усовершенствованной, которая занимает 27 ЛЭ.

Сейчас вооружился четвёртым томом Кнута и заставил свой компилятор для QuatCore генерировать такой вот модуль:

//таблица непосредственных значений, сгенерированная под конкретный исполняемый код
module QuatCoreImmTable (input [7:0] SrcAddr, output [15:0] Q);
	wire[6:0] adr = SrcAddr[6:0];
	assign Q[0]=adr[6];
	assign Q[1]=adr[5];
	assign Q[2]=adr[4];
	assign Q[3]=adr[3];
	assign Q[4]=adr[2];
	assign Q[8]=adr[5];
	assign Q[10]=adr[5];
	assign Q[11]=adr[5];
	assign Q[12]=1'b0;
	assign Q[13]=1'b0;
	assign Q[14]=adr[1];
	wire [3:0] adr15={adr[6],adr[2],adr[1],adr[0]};
	assign Q[15]=
		(adr15==4'b0000)?	1'b0:
		(adr15==4'b1100)?	1'b0:
		(adr15==4'b0001)?	1'b1:
		(adr15==4'b1001)?	1'b0:
		(adr15==4'b0101)?	1'b0:
		(adr15==4'b1101)?	1'b0:
		(adr15==4'b0011)?	1'b0:
			1'bx;
	wire [2:0] adr9={adr[3],adr[2],adr[0]};
	assign Q[9]=
		(adr9==3'b000)?	1'b0:
		(adr9==3'b110)?	1'b1:
		(adr9==3'b001)?	1'b0:
		(adr9==3'b011)?	1'b1:
			1'b0;
	wire [2:0] adr7={adr[4],adr[2],adr[1]};
	assign Q[7]=
		(adr7==3'b000)?	1'b0:
		(adr7==3'b010)?	1'b1:
		(adr7==3'b110)?	1'b1:
		(adr7==3'b001)?	1'b0:
		(adr7==3'b101)?	1'b0:
		(adr7==3'b011)?	1'b0:
			1'b1;
	wire [3:0] adr6={adr[6],adr[3],adr[2],adr[1]};
	assign Q[6]=
		(adr6==4'b0000)?	1'b0:
		(adr6==4'b1000)?	1'b0:
		(adr6==4'b0100)?	1'b1:
		(adr6==4'b0010)?	1'b1:
		(adr6==4'b1110)?	1'b1:
		(adr6==4'b0001)?	1'b0:
		(adr6==4'b1001)?	1'b0:
		(adr6==4'b0101)?	1'b0:
		(adr6==4'b1101)?	1'b0:
		(adr6==4'b0011)?	1'b0:
		(adr6==4'b1011)?	1'b0:
		(adr6==4'b0111)?	1'b0:
			1'b1;
	wire [4:0] adr5={adr[6],adr[5],adr[4],adr[3],adr[1]};
	assign Q[5]=
		(adr5==5'b00000)?	1'b0:
		(adr5==5'b10000)?	1'b0:
		(adr5==5'b01100)?	1'b1:
		(adr5==5'b01110)?	1'b0:
		(adr5==5'b11110)?	1'b1:
		(adr5==5'b00001)?	1'b0:
		(adr5==5'b10001)?	1'b0:
		(adr5==5'b01001)?	1'b1:
		(adr5==5'b11001)?	1'b0:
		(adr5==5'b10101)?	1'b1:
		(adr5==5'b01101)?	1'b1:
		(adr5==5'b11101)?	1'b0:
		(adr5==5'b10011)?	1'b1:
		(adr5==5'b11011)?	1'b0:
		(adr5==5'b00111)?	1'b1:
		(adr5==5'b10111)?	1'b1:
		(adr5==5'b01111)?	1'b0:
			1'b0;
//Непосредственные значения и их адреса:
// Значение (dec) Значение (hex) Маска Адрес Где используется                                                    
// 181            00B5           00FF  0057  SP Stack/NOP 0/NOP 0                                                
// 1              0001           FFFF  0041  j 1/i 1/JGE ProcessFrame::@NotSoBright/SUB 1/JL AcqQueue::@queue    
// 32768          8000           C3FF  0001  ACQ VSync                                                           
// 10             000A           001F  002B  k 10                                                                
// 15             000F           00FF  007B  Z D1                                                                
// 16384          4000           C3FF  0003  ACQ HSync/ACQ HSync                                                 
// 125            007D           007F  005F  kLOOP ProcessFrame::@topRows/iLOOP AcqQueue::@updCycle              
// 720            02D0           FFFF  0005  [SP+2j] ImgHeight                                                   
// 54             0036           007F  0037  JMP ProcessFrame::@FinalRange                                       
// 16             0010           00FF  0007  X ActivePoints                                                      
// 3583           0DFF           FFFF  007D  Acc Threshold                                                       
// 17             0011           00FF  0047  JL ProcessFrame::@MidCycle/X AllPoints                              
// 7              0007           007F  0073  JL ProcessFrame::@DoMerge                                           
// 118            0076           007F  0035  iLOOP ProcessFrame::@checkCycle                                     
// 19             0013           00FF  0067  Y Heap                                                              
// 34             0022           007F  0023  JMP ProcessFrame::@MidCycle/i 2                                     
// 0              0000           FFFF  0000  Acc 0/SUB 0                                                         
// 14             000E           007F  003B  JGE ProcessFrame::@FinalRange                                       
// 11             000B           007F  006B  JMP ProcessFrame::@ActPointsStart/JMP ProcessFrame::@ActPointsStart 
// 121            0079           007F  004F  JL ProcessFrame::@QueueAnyway                                       
// 1023           03FF           C3FF  007C  ACQ WholeRow                                                        
// 78             004E           007F  0039  JGE ProcessFrame::@newRow                                           
// 60             003C           007F  001F  JMP main::@endless                                                  
// 3              0003           007F  0063  JL ListOp::@OutOfMem                                                
endmodule


Он занимает всего 7 ЛЭ, а задержка распространения (tpd) составляет 16 нс.


Теперь компилятор не ограничивается тем, что выписывает оставшиеся 5 выходных бит как логическую функцию от 7 входных. Он берётся за каждый из этих бит и прямым перебором проверяет: нельзя ли его выразить как функцию от ОДНОГО из 7 входных бит (Из 4 возможных вариантов: всегда единица, всегда ноль, повторение входного бита и инверсия, непроверенной осталась лишь инверсия), если этого не получилось - ищет функцию от двух из 7 входных бит (все возможные сочетания), затем функцию от трёх бит - и так далее.

Ясное дело, совпадение требуется только там, где в маске стоит единица, а там, где мы рисовали буквы 'x', может быть что угодно. За счёт этого и удаётся резко сократить количество входных бит. Как видим, 2 раза мы обошлись тремя входными битами, ещё 2 раза четырьмя и один раз - пятью.


Увы, когда я попробовал синтезировать всю схему в сборе (процессор + видеопроцессор в тесной связке), тайминги опять были завалены. Ну не хватает у фиттера усидчивости нормально всё расставить и соединить, хоть ты тресни! Ну хоть размер схемы снизился: вместо 991 ЛЭ получили 950 ЛЭ.

В работе фиттера хватает случайности: чуть-чуть где-то что-то поменял - и он совсем по-другому всё соединяет. Одно только избавление от выходных пинов очень сильно влияет на результаты его работы. Наверное, надо смириться пока с заваленными таймингами - и посмотреть работу всего этого дела на симуляции со сниженной тактовой частотой. А там, когда вместо вытаскивания "внутренностей" процессора наружу (как-то SrcAddr, DestAddr, DataBus) туда пойдёт UART и SPI, тайминги внезапно придут в норму. А если нет - у меня есть ещё пара тузов в рукаве...
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

Recent Posts from This Journal

  • О вытягивании себя из болота по методу Мюнхгаузена

    Всё готовлюсь к встрече с представителями РКК Энергия, нужно убедить их в моём способе определения положения ВидеоИзмерителя Параметров Сближения на…

  • Ремонт лыжных мостиков

    Вернулся с сегодняшнего субботника. Очень продуктивно: отремонтировали все ТРИ мостика! Правда, для этого надо было разделиться, благо народу…

  • Гетто-байк

    В субботу во время Великой Октябрьской резни бензопилой умудрился петуха сломать в велосипеде. По счастью, уже на следующий день удалось купить…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 8 comments