import Base import ../kernel_gemm.bend as Gemm import ../kernel_rows.bend as Rows import ../kernel_tile.bend as Tile import ../traversal_loop.bend as Loop import ./storage_witness.bend as Witness # The k loop returns every owner it received. Index, context and the erased # accumulators are whatever the steps produced. type Looped<-input: Array,-weights: Array,-bias: Array,-output: Array,-state: Gemm.Loop> is Data: Looped{index: U32,context: Gemm.Context,-accumulators: Rows.Rows, equation: {state == Gemm.Loop{input,weights,bias,output,index,context,accumulators} : Gemm.Loop}} def after_input(-input: Array,-weights: Array,-bias: Array,-output: Array,+index: U32,+context: Gemm.Context, -accumulators: Rows.Rows,-samples: Rows.Rows,+address: U32,read: Witness.Read) -> Looped: Witness.Read{value,equation} = read %Equal.sym(Array & Tile.Tile8,Array.get(Tile.Tile8,input,address),(input,value),equation) : Looped Looped{(index + 1 : U32),context,Gemm.update(accumulators,value,samples),{==}} def after_weights(~upper: Bool,-input: Array,-weights: Array,-bias: Array,-output: Array,+index: U32,+context: Gemm.Context, +input_base: U32,-accumulators: Rows.Rows,+address: U32,input_evidence: Witness.ArrayWitness, read: Witness.Read) -> Looped: Witness.Read{value,equation} = read %Equal.sym(Array & Tile.Tile8,Array.get(Tile.Tile8,weights,address),(weights,value),equation) : Looped after_input(input,weights,bias,output,index,context,accumulators,Rows.half(upper,value),(input_base + index : U32), Witness.observed(Tile.Tile8,input,(input_base + index : U32),input_evidence)) def step_at(~upper: Bool,-input: Array,-weights: Array,-bias: Array,-output: Array,+index: U32,context: Gemm.Context, -accumulators: Rows.Rows,+input_evidence: Witness.ArrayWitness,+weight_evidence: Witness.ArrayWitness) -> Looped: Gemm.Context{+row,+position,+rows,+columns,+input_base,+weight_base} = context after_weights(~upper,input,weights,bias,output,index,Gemm.Context{row,position,rows,columns,input_base,weight_base},input_base,accumulators, (weight_base + index : U32),input_evidence,Witness.observed(Tile.Tile8,weights,(weight_base + index : U32),weight_evidence)) def step(~upper: Bool,-input: Array,-weights: Array,-bias: Array,-output: Array,-state: Gemm.Loop, +input_evidence: Witness.ArrayWitness,+weight_evidence: Witness.ArrayWitness, evidence: Looped) -> Looped: Looped{+index,+context,accumulators,equation} = evidence %Equal.sym(Gemm.Loop,state,Gemm.Loop{input,weights,bias,output,index,context,accumulators},equation) : Looped step_at(~upper,input,weights,bias,output,index,context,accumulators,input_evidence,weight_evidence) def run(~upper: Bool,count: Nat,-input: Array,-weights: Array,-bias: Array,-output: Array,-state: Gemm.Loop, +input_evidence: Witness.ArrayWitness,+weight_evidence: Witness.ArrayWitness, evidence: Looped) -> Looped: match count: case 0n: evidence case 1n+rest: run(~upper,rest,input,weights,bias,output,Gemm.step(~upper,state),input_evidence,weight_evidence, step(~upper,input,weights,bias,output,state,input_evidence,weight_evidence,evidence))