Altifigence Academy

10 / 20 · Lab

Lab: a skewed 2×2 array

Model one-edge forwarding delays and check every intermediate accumulator.

Make equal k values meet

Inject A(i,k) at the left boundary on logical edge k+i and B(k,j) at the top on k+j. Registered forwarding adds j edges horizontally and i vertically. Both operands therefore reach PE(i,j) on k+i+j. This staggered injection is input skew.

For A=[[1,2],[3,4]], B=[[5,6],[7,8]], clear finishes before E0. Boundary schedules are:

EdgeLeft row 0Left row 1Top col 0Top col 1
E01(k0)invalid5(k0)invalid
E12(k1)3(k0)7(k1)6(k0)
E2invalid4(k1)invalid8(k1)
E3invalidinvalidinvalidinvalid

Save the following as schedule-lab.mjs and run node schedule-lab.mjs. It requires no packages and prints Schedule lab passed. Invalid tokens are null; valid tokens carry value and k. This single-job model omits job tags but checks k explicitly.

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');

Each PE reads old state and writes next state. In-place iteration would incorrectly permit multi-hop forwarding within one edge.

After E0 only C(0,0)'s accumulator is five. E1 completes it at nineteen and begins its neighbors at six and fifteen. E2 completes those at twenty-two and forty-three, while the final PE has only eighteen. E3 adds thirty-two to produce fifty.

Change row injection from t−i to t. A tag assertion should detect misalignment. Completion requires four advance edges and every count equal to two. Initialization and serial output transfer are excluded. This executable model validates the stated schedule without claiming RTL or DDS execution.

Actual RTL: the registered 2×2 grid

The attached systolic_2x2.sv connects four instances from signed_mac_pe.sv, bounded to N=K=2. A moves right and B moves down through registered links carrying valid and k tags. The external boundary supplier performs skew; the testbench's step task drives the E0..E3 schedule directly. Clear finishes before E0 and no extra multiplier pipeline exists.

Save all three attachments together and run 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

The post-edge matrices are [[5,0],[0,0]], [[19,6],[15,0]], [[19,22],[43,18]] and [[19,22],[43,50]]. Done asserts only after E3. Two pauses give four advance edges and six physical compute edges. Checks also cover [[10,9],[−6,3]], complete state holding and reset mid-job. Expect RTL PASS:.

For an RTL modification exercise, replace a registered operand link with a combinational path. Predict the first tag-alignment or intermediate-sum failure, compare the log and restore the register. Extending this grid to N×N requires revisiting wiring, skew, widths, tags and completion together.

Try it yourself

After E2, what is PE(1,1)'s accumulator and remaining term? Why does it change at E3 despite invalid boundary inputs?

Read the explanation

The accumulator is 18 from 3×6, with 4×8=32 remaining. Those operands are in internal forwarding registers and arrive at E3; invalid boundaries do not instantly empty the array.

Lesson files

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

Your choice applies to this browser. Change it any time using the footer.