SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
0ba037b verified
Raw History Blame Contribute Delete
7.09 kB
(* Lane mapping of BULK in pcie/rtl/bitacc_engine.sv.
The bit store has L lanes; word w lives in lane (w mod L) at local address
(w div L). BULK pairs dst word D + k with src word S + k for k = 0 .. n-1,
L elements per step j. Per lane i the RTL computes, once per operation:
r i = (i - S) mod L src element offset (RTL: LW'(i) - S[LW-1:0])
sa i = (S + r i) div L src local base (RTL: sa)
q m = (m - D) mod L dst element offset (RTL: q_off)
da m = (D + q m) div L dst local base (RTL: da)
delta = (D - S) mod L rotation (RTL: r_delta)
In step j, lane i reads src local address j + sa i, which holds element
k = j*L + r i; dst lane m reads and writes local address j + da m, holding
element j*L + q m, and takes its src word from lane (m - delta) mod L.
Proved here, for every L > 0 (the RTL uses L = 2^LW, where LW-bit
subtraction is subtraction mod L, Part 1):
- lane i's src read is word S + k of lane i (Part 2);
- every element k >= 0 is read by exactly one lane, in step k div L (Part 2);
- the rotation delivers element k to the lane and local address of word
D + k, i.e. dst lane m and src lane (m - delta) mod L hold the same k
(Part 3).
Bounds (k < n, addresses inside the store) are checked by the RTL's kvalid
and the decode-time range checks, and tested in pcie/tb. *)
module LaneMap
use int.Int
use int.EuclideanDivision
constant l : int
axiom l_pos : l > 0
(* Each lemma is a lemma function whose assertions name the quotient
witnesses, so that every step is linear arithmetic plus one instance of
the standard library's Div_mod, Div_unique, Div_mult or Mod_mult. *)
(* ---------------------------------------------------------------- Part 1: residues *)
let lemma mod_add_multiple (a t : int)
ensures { mod (a + t * l) l = mod a l }
= assert { a + t * l = l * t + a }
(* Linear step of rotation_pairs_elements, kept apart so that the prover
sees it without the residue lemmas in its context. *)
let lemma rotation_arith (m d s t e : int)
requires { d - s = l * t + e }
ensures { m - e + (- s) = (m - d) + t * l }
= ()
let lemma rotation_mod (m d s t e : int)
requires { d - s = l * t + e }
ensures { mod (m - e + (- s)) l = mod (m - d) l }
= rotation_arith m d s t e;
mod_add_multiple (m - d) t
let lemma div_add_multiple (a t : int)
ensures { div (a + t * l) l = div a l + t }
= assert { a + t * l = l * t + a }
let lemma mod_small (a : int)
requires { 0 <= a < l }
ensures { mod a l = a }
= assert { div a l = 0 };
assert { a = l * div a l + mod a l }
let lemma mod_sum_left (a b : int)
ensures { mod (mod a l + b) l = mod (a + b) l }
= assert { a = l * div a l + mod a l };
assert { a + b = (mod a l + b) + div a l * l };
mod_add_multiple (mod a l + b) (div a l)
let lemma mod_sum_right (a b : int)
ensures { mod (a + mod b l) l = mod (a + b) l }
= mod_sum_left b a;
assert { mod b l + a = a + mod b l /\ b + a = a + b }
(* LW-bit subtraction of residues (the RTL's r, q_off, r_delta) is the
residue of the difference when L = 2^LW. *)
let lemma mod_sub_residues (a b : int)
ensures { mod (mod a l - mod b l) l = mod (a - b) l }
= assert { a = l * div a l + mod a l };
assert { b = l * div b l + mod b l };
assert { a - b = (mod a l - mod b l) + (div a l - div b l) * l };
mod_add_multiple (mod a l - mod b l) (div a l - div b l)
(* ---------------------------------------------------------------- Part 2: src side *)
function r (s i : int) : int = mod (i - s) l
function sa (s i : int) : int = div (s + r s i) l
function k_src (s i j : int) : int = j * l + r s i
lemma r_bounds : forall s i : int. 0 <= r s i < l
(* Lane i's element of step j lives in lane i ... *)
let lemma src_lane (s i j : int)
requires { 0 <= i < l }
ensures { mod (s + k_src s i j) l = i }
= assert { i - s = l * div (i - s) l + r s i };
assert { s + k_src s i j = i + (j - div (i - s) l) * l };
mod_add_multiple i (j - div (i - s) l);
mod_small i
(* ... at local address j + sa i. *)
let lemma src_local (s i j : int)
ensures { div (s + k_src s i j) l = j + sa s i }
= assert { s + k_src s i j = (s + r s i) + j * l };
div_add_multiple (s + r s i) j
(* Every element k is the element of lane (s + k) mod L in step k div L ... *)
let lemma src_covers (s k : int)
ensures { k_src s (mod (s + k) l) (div k l) = k }
= mod_sum_left (s + k) (- s);
assert { s + k + (- s) = k };
assert { k = l * div k l + mod k l }
(* ... and of no other lane in that step. *)
let lemma src_unique (s i1 i2 j : int)
requires { 0 <= i1 < l /\ 0 <= i2 < l }
requires { k_src s i1 j = k_src s i2 j }
ensures { i1 = i2 }
= src_lane s i1 j;
src_lane s i2 j
(* The element of step j is in [j L, j L + L): different steps hold
different elements. *)
let lemma src_step (s i j : int)
ensures { div (k_src s i j) l = j }
= assert { j * l <= k_src s i j < j * l + l }
let lemma src_steps_disjoint (s i1 i2 j1 j2 : int)
requires { k_src s i1 j1 = k_src s i2 j2 }
ensures { j1 = j2 }
= src_step s i1 j1;
src_step s i2 j2
(* ---------------------------------------------------------------- Part 3: dst side, rotation *)
(* The dst offsets have the same form as the src offsets, with d for s. *)
function q (d m : int) : int = r d m
function da (d m : int) : int = sa d m
function k_dst (d m j : int) : int = k_src d m j
function delta (d s : int) : int = mod (d - s) l
function src_lane_for (d s m : int) : int = mod (m - delta d s) l
(* Dst lane m's element of step j is word d + k of lane m, at j + da m. *)
let lemma dst_lane (d m j : int)
requires { 0 <= m < l }
ensures { mod (d + k_dst d m j) l = m }
= src_lane d m j
let lemma dst_local (d m j : int)
ensures { div (d + k_dst d m j) l = j + da d m }
= src_local d m j
(* The src lane the rotation selects is a lane ... *)
lemma rotation_in_range :
forall d s m : int. 0 <= src_lane_for d s m < l
(* ... and it holds the same element k as dst lane m, in every step. *)
let lemma rotation_pairs_elements (d s m j : int)
ensures { k_src s (src_lane_for d s m) j = k_dst d m j }
= let t = div (d - s) l in
let e = delta d s in
assert { r s (src_lane_for d s m) = mod (mod (m - e) l + (- s)) l };
mod_sum_left (m - e) (- s);
assert { r s (src_lane_for d s m) = mod (m - e + (- s)) l };
assert { d - s = l * t + e };
rotation_mod m d s t e
(* Element k from src lane i goes to dst lane (i + delta) mod L. *)
let lemma rotation_target (d s i j : int)
requires { 0 <= i < l }
ensures { mod (d + k_src s i j) l = mod (i + delta d s) l }
= assert { i - s = l * div (i - s) l + r s i };
assert { d + k_src s i j = (i + (d - s)) + (j - div (i - s) l) * l };
mod_add_multiple (i + (d - s)) (j - div (i - s) l);
mod_sum_right i (d - s)
end