Altifigence Academy

19 / 20 · 实验

综合项目:分块 N×N 验证模型

结合任意 N 和 K、填充及暂停,并与独立参考比较。

组装完整模型

综合项目在 N×N 网格上接收形状为 M×K 的 A 和 K×P 的 B。每个空间分块从空状态开始,填充操作数为有效零,存储按坐标屏蔽。每个分块只容纳一个任务,全局暂停保持逻辑时间。输出量化在宽和之后独立测试。

将代码保存为 capstone-lab.mjs,运行 node capstone-lab.mjs。不需要软件包。输入为 JavaScript Number 精确范围内的小整数测试数据;更大范围需要 BigInt 和明确的位宽检查。这验证 Node 算术/调度模型,与 RTL 或 DDS 执行独立。

javascript
import assert from 'node:assert/strict';
function golden(A,B){return A.map(r=>B[0].map((_,j)=>
 r.reduce((s,a,k)=>s+a*B[k][j],0)));}
function solve(A,B,N,pauses=new Set()){
 const M=A.length,K=A[0].length,P=B[0].length;
 assert.ok(N>=1&&Number.isInteger(N)&&K>=1);assert.equal(B.length,K);
 assert.ok(A.every(r=>r.length===K)&&B.every(r=>r.length===P));
 const C=Array.from({length:M},()=>Array(P).fill(null));
 let advances=0,physical=0;
 for(let r0=0;r0<M;r0+=N)for(let c0=0;c0<P;c0+=N){
  const job=r0*P+c0;
  let g=Array.from({length:N},()=>Array.from({length:N},()=>
   ({a:null,b:null,acc:0,count:0})));
  const token=(value,k)=>({value,k,job});let t=0,p=0;
  while(t<K+2*N-2){
   if(pauses.has(p)){p++;continue;}
   const next=g.map(r=>r.map(pe=>({...pe})));
   for(let i=0;i<N;i++)for(let j=0;j<N;j++){
    const ka=t-i,kb=t-j;
    const a=j?g[i][j-1].a:(ka>=0&&ka<K?
     token(r0+i<M?A[r0+i][ka]:0,ka):null);
    const b=i?g[i-1][j].b:(kb>=0&&kb<K?
     token(c0+j<P?B[kb][c0+j]:0,kb):null);
    const pe=next[i][j];pe.a=a;pe.b=b;
    if(a&&b){assert.equal(a.job,b.job);assert.equal(a.k,b.k);
     assert.equal(a.k,pe.count);pe.acc+=a.value*b.value;pe.count++;}}
   g=next;t++;p++;
  }
  for(let i=0;i<N;i++)for(let j=0;j<N;j++){
   assert.equal(g[i][j].count,K);
   if(r0+i<M&&c0+j<P){assert.equal(C[r0+i][c0+j],null);
    C[r0+i][c0+j]=g[i][j].acc;}}
  advances+=t;physical+=p;
 }
 return {C,advances,physical};
}
const A=[[1,2,3],[4,5,6],[7,8,9]],B=[[1,0,2],[0,1,0],[2,0,1]];
for(const N of [1,2,3])assert.deepEqual(
 solve(A,B,N,new Set([1,2])).C,golden(A,B));
const run=solve(A,B,2,new Set([1,2]));
assert.deepEqual(run.C,[[7,2,5],[16,5,14],[25,8,23]]);
assert.equal(run.advances,20);assert.equal(run.physical,28);
assert.deepEqual(solve([[2,-1],[0,3]],[[4,5],[-2,1]],2).C,
 [[10,9],[-6,3]]);
assert.deepEqual(solve([[-128]],[[-128]],1).C,[[16384]]);
console.log('Capstone lab passed');

golden 函数只负责矩阵算术。求解器独立移动带标签令牌,检查有序项,并屏蔽存储。N=2 时,四个分块需要二十个推进时钟沿。每个分块在实际时钟沿一和二暂停,增加八次暂停,共二十八个实际时钟沿。不包含初始化、存储器加载和串行化输出传送。

提交日志、一个分块的已使用 k 跟踪、有符号位宽分析,以及 valid/ready 结果封装设计。转化为 RTL 时保留时钟沿约定。先从 N=1、K=1 和 2×2 开始,再扩展。每次只增加量化、保留部分和或双缓冲中的一项,并加入新的明确检查。

三种网格尺寸覆盖不同映射:N=1 重复执行无错位点积,N=2 覆盖四个填充分块,N=3 使用一个完整分块。三者必须产生相同数学矩阵。将 C 初始化为 null,可以区分有效零与未交付输出,并检测重复存储。此处由分块计算的 job 编号唯一;真实 RTL 必须定义标签位宽和复用策略。扩展练习可尝试 M=2、K=3、P=1,并手算预期值。内部网格仍是正方形,输出矩阵则为矩形。检查每个分块使用完整 K,并抑制超范围存储。

自己试试

3×3 示例中,N=3,实际时钟沿一和二暂停。推进沿数和实际沿数是多少?如果测量包含前面的一个 clear 时钟沿,结果如何?

阅读解释

推进时钟沿有七个,包含两次暂停的计算区间实际时钟沿有九个。如果加入前面的一个 clear 时钟沿,共十个;仍不含加载和输出传送。

Lesson files

capstone-lab.mjs ↓

你的选择适用于此浏览器,可随时在页脚更改。