Altifigence Academy

10 / 20 · Esercitazione

Laboratorio: array 2×2 con ingressi sfasati

Modella ritardi di inoltro di un fronte e verifica ogni accumulatore intermedio.

Fai incontrare valori k uguali

Inserisci A(i,k) al confine sinistro al fronte logico k+i e B(k,j) a quello superiore a k+j. L'inoltro registrato aggiunge j fronti orizzontalmente e i verticalmente. Entrambi gli operandi raggiungono quindi PE(i,j) a k+i+j. Questo inserimento scaglionato è lo sfasamento degli ingressi.

Per A=[[1,2],[3,4]], B=[[5,6],[7,8]], clear termina prima di E0. Le pianificazioni al confine sono:

FronteSinistra riga 0Sinistra riga 1Alto colonna 0Alto colonna 1
E01(k0)non valido5(k0)non valido
E12(k1)3(k0)7(k1)6(k0)
E2non valido4(k1)non valido8(k1)
E3non validonon validonon validonon valido

Salva il codice seguente come schedule-lab.mjs ed esegui node schedule-lab.mjs. Non richiede pacchetti e stampa Schedule lab passed. I token non validi sono null; quelli validi trasportano value e k. Questo modello con un solo lavoro omette i tag job ma verifica esplicitamente k.

javascript
import assert from 'node:assert/strict';
const A=[[1,2],[3,4]],B=[[5,6],[7,8]],N=2,K=2;
const fresh=()=>({a:null,b:null,acc:0,count:0});
let grid=Array.from({length:N},()=>Array.from({length:N},fresh));
const expected=[[[5,0],[0,0]],[[19,6],[15,0]],
                [[19,22],[43,18]],[[19,22],[43,50]]];
const token=(value,k)=>({value,k});
for(let t=0;t<K+2*N-2;t++) {
 const next=grid.map(r=>r.map(p=>({...p})));
 for(let i=0;i<N;i++) for(let j=0;j<N;j++) {
  const ka=t-i,kb=t-j;
  const a=j?grid[i][j-1].a:(ka>=0&&ka<K?token(A[i][ka],ka):null);
  const b=i?grid[i-1][j].b:(kb>=0&&kb<K?token(B[kb][j],kb):null);
  const p=next[i][j];p.a=a;p.b=b;
  if(a&&b){assert.equal(a.k,b.k);assert.equal(a.k,p.count);
   p.acc+=a.value*b.value;p.count++;}
 }
 grid=next;
 assert.deepEqual(grid.map(r=>r.map(p=>p.acc)),expected[t]);
}
assert.deepEqual(grid.map(r=>r.map(p=>p.count)),[[2,2],[2,2]]);
console.log('Schedule lab passed');

Ogni PE legge lo stato precedente e scrive quello successivo. Un'iterazione con aggiornamenti diretti consentirebbe erroneamente l'inoltro su più collegamenti in un solo fronte.

Dopo E0 soltanto l'accumulatore di C(0,0) vale cinque. E1 lo completa a diciannove e avvia i vicini a sei e quindici. E2 completa questi ultimi a ventidue e quarantatré, mentre il PE finale ha soltanto diciotto. E3 aggiunge trentadue producendo cinquanta.

Cambia l'inserimento delle righe da t−i a t. Un'asserzione sui tag deve rilevare il disallineamento. Il completamento richiede quattro fronti di avanzamento e ogni count uguale a due. Inizializzazione e trasferimento seriale di uscita sono esclusi. Questo modello eseguibile convalida la pianificazione dichiarata senza attestare l'esecuzione RTL o DDS.

RTL effettivo: la griglia 2×2 registrata

L'allegato systolic_2x2.sv collega quattro istanze da signed_mac_pe.sv, limitate a N=K=2. A si muove verso destra e B verso il basso tramite collegamenti registrati che trasportano valid e tag k. Il fornitore esterno al confine esegue lo sfasamento; il task step del testbench applica direttamente la pianificazione E0..E3. Clear termina prima di E0 e non esiste una pipeline aggiuntiva del moltiplicatore.

Salva insieme tutti e tre gli allegati ed esegui Icarus Verilog:

bash
iverilog -g2012 -s tb_systolic_2x2 -o systolic.vvp signed_mac_pe.sv systolic_2x2.sv tb_systolic_2x2.sv
vvp systolic.vvp

Le matrici dopo i fronti sono [[5,0],[0,0]], [[19,6],[15,0]], [[19,22],[43,18]] e [[19,22],[43,50]]. Done si attiva soltanto dopo E3. Due pause danno quattro fronti di avanzamento e sei fronti fisici di calcolo. Le verifiche coprono anche [[10,9],[−6,3]], mantenimento completo dello stato e reset durante il lavoro. Attenditi RTL PASS:.

Come esercizio di modifica RTL, sostituisci un collegamento registrato degli operandi con un percorso combinatorio. Prevedi il primo errore di allineamento dei tag o somma intermedia, confronta il log e ripristina il registro. Estendere questa griglia a N×N richiede di rivedere insieme cablaggio, sfasamento, larghezze, tag e completamento.

Prova tu

Dopo E2, qual è l'accumulatore di PE(1,1) e quale termine rimane? Perché cambia a E3 nonostante gli ingressi al confine non validi?

Leggi la spiegazione

L'accumulatore è 18 da 3×6, con 4×8=32 rimanente. Questi operandi sono nei registri interni di inoltro e arrivano a E3; confini non validi non svuotano istantaneamente l'array.

Lesson files

schedule-lab.mjs ↓signed_mac_pe.sv ↓systolic_2x2.sv ↓tb_systolic_2x2.sv ↓

La scelta vale per questo browser. Puoi modificarla in qualsiasi momento dal piè di pagina.