Download formal/lane_map.mlw from Snapkitty/bit-string-accelerator: direct link, hf CLI and curl.
- Browser
- Download file 7.09 kB
-
https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/formal/lane_map.mlw
- Command line
-
hf download hf://Snapkitty/bit-string-accelerator/formal/lane_map.mlw
-
curl -L -o lane_map.mlw https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/formal/lane_map.mlw
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 | |