CharlesCNorton commited on
Commit
c953041
·
1 Parent(s): f0cf221

float mul: full IEEE subnormal support via a unified right-shift renormalizer (right-shift the product by F+1-min(nlz,exp_base)); oracle validated bit-exact against numpy over all classes including deep underflow; all float variants rebuilt

Browse files
neural_computer.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f3168c466f9fc791c09b76e1c61d92290db6c2e4861a9f3a918538a5e5739f1b
3
- size 32744930
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9340602703da2e7563954a45a2febb1d8ed026ac861b493883add2d5311f1f9d
3
+ size 33592582
src/build.py CHANGED
@@ -1334,18 +1334,16 @@ def add_float_mul(tensors: Dict[str, torch.Tensor], family: str,
1334
 
1335
  Self-contained circuit; external inputs are the raw operand words
1336
  $a[0..W-1] / $b[0..W-1] (MSB-first). Contract: exact IEEE specials
1337
- (NaN, infinities, signed zeros), flush-to-zero for subnormal operands
1338
- and results, round-to-nearest-even for the mantissa.
1339
 
1340
  Datapath: (F+1)x(F+1) partial products accumulated shift-add into the
1341
- 2F+2-bit product, a one-bit normalize mux, guard/round/sticky extraction
1342
- with a round-to-nearest-even incrementer on the fraction, an
1343
- E+2-bit two's-complement exponent chain computing exp_a + exp_b - bias
1344
- + msb plus a rounding-overflow carry, range detectors, and a one-hot
1345
- specials selection network producing the output word.
1346
-
1347
- Rounding: round-to-nearest-even (RNE). Underflow still flushes to zero
1348
- and NaN/Inf specials are exact.
1349
  """
1350
  E, F = exp_bits, frac_bits
1351
  prefix = f"{family}.mul"
@@ -1354,14 +1352,19 @@ def add_float_mul(tensors: Dict[str, torch.Tensor], family: str,
1354
  add_gate(tensors, f"{prefix}.sign_xor.layer1.nand", [-1.0, -1.0], [1.0])
1355
  add_gate(tensors, f"{prefix}.sign_xor.layer2", [1.0, 1.0], [-2.0])
1356
 
1357
- # Operand classification (FTZ: exp == 0 means the operand is zero).
 
1358
  for op in ("a", "b"):
1359
  add_gate(tensors, f"{prefix}.{op}.exp_zero", [-1.0] * E, [0.0])
 
1360
  add_gate(tensors, f"{prefix}.{op}.exp_max", [1.0] * E, [-float(E)])
1361
  add_gate(tensors, f"{prefix}.{op}.frac_nz", [1.0] * F, [-1.0])
1362
  add_gate(tensors, f"{prefix}.{op}.frac_zero", [-1.0] * F, [0.0])
1363
  add_gate(tensors, f"{prefix}.{op}.is_nan", [1.0, 1.0], [-2.0])
1364
  add_gate(tensors, f"{prefix}.{op}.is_inf", [1.0, 1.0], [-2.0])
 
 
 
1365
 
1366
  # exp_add: exp_a + exp_b in E+1 bits.
1367
  for bit in range(E + 1):
@@ -1377,46 +1380,75 @@ def add_float_mul(tensors: Dict[str, torch.Tensor], family: str,
1377
  for bit in range(2 * F + 2):
1378
  add_full_adder(tensors, f"{prefix}.mant_mul.acc.s{stage}.fa{bit}")
1379
 
1380
- # Normalize by one: product in [1, 4); frac output muxes.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1381
  for k in range(F):
1382
- add_gate(tensors, f"{prefix}.norm.bit{k}.not_sel", [-1.0], [0.0])
1383
- add_gate(tensors, f"{prefix}.norm.bit{k}.and_a", [1.0, 1.0], [-2.0])
1384
- add_gate(tensors, f"{prefix}.norm.bit{k}.and_b", [1.0, 1.0], [-2.0])
1385
- add_gate(tensors, f"{prefix}.norm.bit{k}.or", [1.0, 1.0], [-1.0])
1386
-
1387
- # Round-to-nearest-even. Guard/round selected on the normalize bit; sticky
1388
- # ORs the product tail; round-up = G AND (L OR R OR S); the fraction is
1389
- # incremented, with the carry-out bumping the exponent.
1390
- for nm in ("g", "r"):
1391
- add_gate(tensors, f"{prefix}.round.{nm}.not_sel", [-1.0], [0.0])
1392
- add_gate(tensors, f"{prefix}.round.{nm}.and_a", [1.0, 1.0], [-2.0])
1393
- add_gate(tensors, f"{prefix}.round.{nm}.and_b", [1.0, 1.0], [-2.0])
1394
- add_gate(tensors, f"{prefix}.round.{nm}.or", [1.0, 1.0], [-1.0])
1395
- add_gate(tensors, f"{prefix}.round.sticky_base", [1.0] * (F - 2), [-1.0])
1396
- add_gate(tensors, f"{prefix}.round.sticky_extra", [1.0, 1.0], [-2.0])
1397
- add_gate(tensors, f"{prefix}.round.sticky", [1.0, 1.0], [-1.0])
1398
- add_gate(tensors, f"{prefix}.round.rsl", [1.0, 1.0, 1.0], [-1.0])
1399
- add_gate(tensors, f"{prefix}.round.up", [1.0, 1.0], [-2.0])
1400
  for k in range(F):
1401
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.or", [1.0, 1.0], [-1.0])
1402
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.nand", [-1.0, -1.0], [1.0])
1403
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer2", [1.0, 1.0], [-2.0])
1404
  add_gate(tensors, f"{prefix}.rnd.bit{k}.carry", [1.0, 1.0], [-2.0])
1405
-
1406
- # exp_r = exp_add + msb + (2^(E+2) - bias), E+2-bit two's complement.
1407
- for bit in range(E + 2):
1408
- add_full_adder(tensors, f"{prefix}.exp_r.fa{bit}")
1409
-
1410
- # exp_final = exp_r + rounding carry-out (E+2-bit incrementer).
1411
  for bit in range(E + 2):
1412
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
1413
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
1414
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
1415
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.carry", [1.0, 1.0], [-2.0])
1416
-
1417
- # Range detectors on exp_final.
1418
  add_gate(tensors, f"{prefix}.exp_r.zero", [-1.0] * (E + 2), [0.0])
1419
- add_gate(tensors, f"{prefix}.exp_r.underflow", [1.0, 1.0], [-1.0])
1420
  add_gate(tensors, f"{prefix}.exp_r.not_neg", [-1.0], [0.0])
1421
  add_gate(tensors, f"{prefix}.exp_r.and_low", [1.0] * E, [-float(E)])
1422
  add_gate(tensors, f"{prefix}.exp_r.ge_emax", [1.0, 1.0], [-1.0])
@@ -2989,13 +3021,14 @@ def infer_float_mul_inputs(gate: str, reg: SignalRegistry, family: str,
2989
  one = reg.get_id("#1")
2990
 
2991
  def m_a(k: int) -> int:
2992
- return one if k == F else a(W - 1 - k)
2993
 
2994
  def m_b(k: int) -> int:
2995
- return one if k == F else b(W - 1 - k)
2996
 
2997
- def exp_sig(word, k: int) -> int:
2998
- return word(E - k) if k < E else zero
 
2999
 
3000
  def P(k: int) -> int:
3001
  return R(f"mant_mul.acc.s{F - 1}.fa{k}.ha2.sum.layer2")
@@ -3004,47 +3037,67 @@ def infer_float_mul_inputs(gate: str, reg: SignalRegistry, family: str,
3004
  exp_b_field = [b(1 + i) for i in range(E)]
3005
  frac_a_field = [a(1 + E + i) for i in range(F)]
3006
  frac_b_field = [b(1 + E + i) for i in range(F)]
3007
-
3008
  suffix = gate[len(prefix) + 1:] if gate != prefix else ""
3009
-
3010
  bias = (1 << (E - 1)) - 1
3011
- K = (1 << (E + 2)) - bias
 
 
 
 
 
 
 
 
 
 
 
 
3012
 
3013
  table = {
3014
  "sign_xor.layer1.or": [a(0), b(0)],
3015
  "sign_xor.layer1.nand": [a(0), b(0)],
3016
  "sign_xor.layer2": [R("sign_xor.layer1.or"), R("sign_xor.layer1.nand")],
3017
- "a.exp_zero": exp_a_field, "a.exp_max": exp_a_field,
3018
  "a.frac_nz": frac_a_field, "a.frac_zero": frac_a_field,
3019
  "a.is_nan": [R("a.exp_max"), R("a.frac_nz")],
3020
  "a.is_inf": [R("a.exp_max"), R("a.frac_zero")],
3021
- "b.exp_zero": exp_b_field, "b.exp_max": exp_b_field,
 
 
3022
  "b.frac_nz": frac_b_field, "b.frac_zero": frac_b_field,
3023
  "b.is_nan": [R("b.exp_max"), R("b.frac_nz")],
3024
  "b.is_inf": [R("b.exp_max"), R("b.frac_zero")],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3025
  "exp_r.zero": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E + 2)],
3026
- "exp_r.underflow": [R(f"exp_round.bit{E + 1}.xor.layer2"), R("exp_r.zero")],
3027
  "exp_r.not_neg": [R(f"exp_round.bit{E + 1}.xor.layer2")],
3028
  "exp_r.and_low": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E)],
3029
  "exp_r.ge_emax": [R(f"exp_round.bit{E}.xor.layer2"), R("exp_r.and_low")],
3030
  "exp_r.overflow": [R("exp_r.not_neg"), R("exp_r.ge_emax")],
3031
- "round.sticky_base": [P(k) for k in range(F - 2)],
3032
- "round.sticky_extra": [P(2 * F + 1), P(F - 2)],
3033
- "round.sticky": [R("round.sticky_base"), R("round.sticky_extra")],
3034
- "round.rsl": [R("round.r.or"), R("round.sticky"), R("norm.bit0.or")],
3035
- "round.up": [R("round.g.or"), R("round.rsl")],
3036
  "sel.inputs_nan": [R("a.is_nan"), R("b.is_nan")],
3037
- "sel.inf_zero1": [R("a.is_inf"), R("b.exp_zero")],
3038
- "sel.inf_zero2": [R("b.is_inf"), R("a.exp_zero")],
3039
  "sel.inf_zero": [R("sel.inf_zero1"), R("sel.inf_zero2")],
3040
  "sel.nan": [R("sel.inputs_nan"), R("sel.inf_zero")],
3041
  "sel.not_nan": [R("sel.nan")],
3042
  "sel.inf_in": [R("a.is_inf"), R("b.is_inf")],
3043
- "sel.zero_in": [R("a.exp_zero"), R("b.exp_zero")],
3044
  "sel.inf_or_ovf": [R("sel.inf_in"), R("exp_r.overflow")],
3045
  "sel.not_inf_path": [R("sel.inf_or_ovf")],
3046
  "sel.inf": [R("sel.not_nan"), R("sel.inf_or_ovf")],
3047
- "sel.zero_or_unf": [R("sel.zero_in"), R("exp_r.underflow")],
3048
  "sel.not_zero_unf": [R("sel.zero_or_unf")],
3049
  "sel.zero": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.zero_or_unf")],
3050
  "sel.norm": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.not_zero_unf")],
@@ -3062,7 +3115,15 @@ def infer_float_mul_inputs(gate: str, reg: SignalRegistry, family: str,
3062
  k = int(m.group(1))
3063
  cin = zero if k == 0 else R(f"exp_add.fa{k - 1}.carry_or")
3064
  return _fa_member_inputs(m.group(2), f"{prefix}.exp_add.fa{k}",
3065
- exp_sig(a, k), exp_sig(b, k), cin, reg)
 
 
 
 
 
 
 
 
3066
 
3067
  m = re.match(r"^mant_mul\.acc\.s(\d+)\.fa(\d+)\.(.+)$", suffix)
3068
  if m:
@@ -3078,50 +3139,102 @@ def infer_float_mul_inputs(gate: str, reg: SignalRegistry, family: str,
3078
  return _fa_member_inputs(m.group(3), f"{prefix}.mant_mul.acc.s{t}.fa{k}",
3079
  a_sig, b_sig, cin, reg)
3080
 
3081
- m = re.match(r"^norm\.bit(\d+)\.(not_sel|and_a|and_b|or)$", suffix)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3082
  if m:
3083
  k = int(m.group(1))
3084
  kind = m.group(2)
3085
- msb = P(2 * F + 1)
3086
  if kind == "not_sel":
3087
- return [msb]
3088
  if kind == "and_a":
3089
- return [P(F + k), R(f"norm.bit{k}.not_sel")]
3090
  if kind == "and_b":
3091
- return [P(F + 1 + k), msb]
3092
- return [R(f"norm.bit{k}.and_a"), R(f"norm.bit{k}.and_b")]
3093
-
3094
- m = re.match(r"^exp_r\.fa(\d+)\.(.+)$", suffix)
 
 
3095
  if m:
3096
  k = int(m.group(1))
3097
- a_sig = R(f"exp_add.fa{k}.ha2.sum.layer2") if k <= E else zero
3098
- b_sig = one if (K >> k) & 1 else zero
3099
- cin = P(2 * F + 1) if k == 0 else R(f"exp_r.fa{k - 1}.carry_or")
3100
- return _fa_member_inputs(m.group(2), f"{prefix}.exp_r.fa{k}",
3101
- a_sig, b_sig, cin, reg)
 
 
 
3102
 
3103
- # RNE guard/round selection muxes on the normalize bit.
3104
- m = re.match(r"^round\.(g|r)\.(not_sel|and_a|and_b|or)$", suffix)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3105
  if m:
3106
- nm, kind = m.group(1), m.group(2)
3107
- sel = P(2 * F + 1)
3108
- lo = P(F - 1) if nm == "g" else P(F - 2) # MSB-clear source
3109
- hi = P(F) if nm == "g" else P(F - 1) # MSB-set source
3110
- if kind == "not_sel":
3111
- return [sel]
3112
- if kind == "and_a":
3113
- return [lo, R(f"round.{nm}.not_sel")]
3114
- if kind == "and_b":
3115
- return [hi, sel]
3116
- return [R(f"round.{nm}.and_a"), R(f"round.{nm}.and_b")]
3117
 
3118
- # Fraction round-up incrementer.
3119
  m = re.match(r"^rnd\.bit(\d+)\.(.+)$", suffix)
3120
  if m:
3121
  k = int(m.group(1))
3122
  rest = m.group(2)
3123
  cin = R("round.up") if k == 0 else R(f"rnd.bit{k - 1}.carry")
3124
- f_bit = R(f"norm.bit{k}.or")
3125
  if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
3126
  return [f_bit, cin]
3127
  if rest == "xor.layer2":
@@ -3129,13 +3242,12 @@ def infer_float_mul_inputs(gate: str, reg: SignalRegistry, family: str,
3129
  if rest == "carry":
3130
  return [f_bit, cin]
3131
 
3132
- # Exponent rounding incrementer: exp_r + fraction carry-out.
3133
  m = re.match(r"^exp_round\.bit(\d+)\.(.+)$", suffix)
3134
  if m:
3135
  k = int(m.group(1))
3136
  rest = m.group(2)
3137
  cin = R(f"rnd.bit{F - 1}.carry") if k == 0 else R(f"exp_round.bit{k - 1}.carry")
3138
- e_bit = R(f"exp_r.fa{k}.ha2.sum.layer2")
3139
  if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
3140
  return [e_bit, cin]
3141
  if rest == "xor.layer2":
 
1334
 
1335
  Self-contained circuit; external inputs are the raw operand words
1336
  $a[0..W-1] / $b[0..W-1] (MSB-first). Contract: exact IEEE specials
1337
+ (NaN, infinities, signed zeros), subnormal operands and gradual-underflow
1338
+ subnormal results, round-to-nearest-even for the mantissa.
1339
 
1340
  Datapath: (F+1)x(F+1) partial products accumulated shift-add into the
1341
+ 2F+2-bit product; a leading-zero count and an E+2-bit exponent chain give
1342
+ exp_base = exp_a + exp_b - bias and a signed clamp min(nlz, exp_base); the
1343
+ product is right-shifted by (F+1) - that clamp (one shifter that normalizes
1344
+ normal results, denormalizes subnormal ones, and drives deeply underflowing
1345
+ products to zero), then round-to-nearest-even and a one-hot specials network
1346
+ produce the output word.
 
 
1347
  """
1348
  E, F = exp_bits, frac_bits
1349
  prefix = f"{family}.mul"
 
1352
  add_gate(tensors, f"{prefix}.sign_xor.layer1.nand", [-1.0, -1.0], [1.0])
1353
  add_gate(tensors, f"{prefix}.sign_xor.layer2", [1.0, 1.0], [-2.0])
1354
 
1355
+ # Operand classification. Subnormals (exp==0, frac!=0) are nonzero datapath
1356
+ # operands with implicit bit 0 and effective exponent 1.
1357
  for op in ("a", "b"):
1358
  add_gate(tensors, f"{prefix}.{op}.exp_zero", [-1.0] * E, [0.0])
1359
+ add_gate(tensors, f"{prefix}.{op}.exp_nzero", [1.0] * E, [-1.0])
1360
  add_gate(tensors, f"{prefix}.{op}.exp_max", [1.0] * E, [-float(E)])
1361
  add_gate(tensors, f"{prefix}.{op}.frac_nz", [1.0] * F, [-1.0])
1362
  add_gate(tensors, f"{prefix}.{op}.frac_zero", [-1.0] * F, [0.0])
1363
  add_gate(tensors, f"{prefix}.{op}.is_nan", [1.0, 1.0], [-2.0])
1364
  add_gate(tensors, f"{prefix}.{op}.is_inf", [1.0, 1.0], [-2.0])
1365
+ add_gate(tensors, f"{prefix}.{op}.is_zero", [1.0, 1.0], [-2.0])
1366
+ add_gate(tensors, f"{prefix}.{op}.nonzero", [-1.0], [0.0])
1367
+ add_gate(tensors, f"{prefix}.{op}.eexp_lsb", [1.0, 1.0], [-1.0])
1368
 
1369
  # exp_add: exp_a + exp_b in E+1 bits.
1370
  for bit in range(E + 1):
 
1380
  for bit in range(2 * F + 2):
1381
  add_full_adder(tensors, f"{prefix}.mant_mul.acc.s{stage}.fa{bit}")
1382
 
1383
+ # exp_base = exp_a + exp_b - bias (E+2-bit signed). Right-shift the product
1384
+ # by rshift = (F+1) - min(nlz, exp_base): places the mantissa for normal
1385
+ # results, denormalizes for subnormal ones; a deeply negative exp_base makes
1386
+ # rshift exceed the product width and the result becomes zero.
1387
+ RESM = 2 * F + 2
1388
+ nlzb = 0
1389
+ while (1 << nlzb) <= RESM:
1390
+ nlzb += 1
1391
+ RB = 0
1392
+ while (1 << RB) < RESM:
1393
+ RB += 1
1394
+ for bit in range(E + 2):
1395
+ add_full_adder(tensors, f"{prefix}.expb.fa{bit}")
1396
+ for pos in range(1, RESM):
1397
+ add_gate(tensors, f"{prefix}.lzc.any_higher{pos}", [1.0] * pos, [-1.0])
1398
+ add_gate(tensors, f"{prefix}.lzc.is_highest{pos}.not_higher", [-1.0], [0.0])
1399
+ add_gate(tensors, f"{prefix}.lzc.is_highest{pos}.and", [1.0, 1.0], [-2.0])
1400
+ add_gate(tensors, f"{prefix}.lzc.nz", [1.0] * RESM, [-1.0])
1401
+ add_gate(tensors, f"{prefix}.lzc.not_nz", [-1.0], [0.0])
1402
+ for bbit in range(nlzb):
1403
+ fan = sum(1 for pos in range(1, RESM) if (pos >> bbit) & 1)
1404
+ add_gate(tensors, f"{prefix}.lzc.nlz.bit{bbit}", [1.0] * max(1, fan), [-1.0])
1405
+ for bbit in range(nlzb):
1406
+ add_gate(tensors, f"{prefix}.exp_nnlz.bit{bbit}", [-1.0], [0.0])
1407
+ for k in range(E + 2):
1408
+ add_full_adder(tensors, f"{prefix}.exp_s1.fa{k}") # exp_base - nlz
1409
+ add_full_adder(tensors, f"{prefix}.exp_r.fa{k}") # + 1
1410
+ add_gate(tensors, f"{prefix}.er.zero", [-1.0] * (E + 2), [0.0])
1411
+ add_gate(tensors, f"{prefix}.er.underflow", [1.0, 1.0], [-1.0])
1412
+ add_gate(tensors, f"{prefix}.er.not_underflow", [-1.0], [0.0])
1413
+ for k in range(E + 2):
1414
+ add_gate(tensors, f"{prefix}.exprc.bit{k}", [1.0, 1.0], [-2.0]) # er clamped >= 0
1415
+ for k in range(E + 2): # nsh = min(nlz, exp_base)
1416
+ add_gate(tensors, f"{prefix}.nsh.bit{k}.not_sel", [-1.0], [0.0])
1417
+ add_gate(tensors, f"{prefix}.nsh.bit{k}.and_a", [1.0, 1.0], [-2.0])
1418
+ add_gate(tensors, f"{prefix}.nsh.bit{k}.and_b", [1.0, 1.0], [-2.0])
1419
+ add_gate(tensors, f"{prefix}.nsh.bit{k}.or", [1.0, 1.0], [-1.0])
1420
+ for k in range(E + 2):
1421
+ add_gate(tensors, f"{prefix}.nshc.bit{k}", [-1.0], [0.0]) # ~nsh
1422
+ add_full_adder(tensors, f"{prefix}.rsh.fa{k}") # rsh = F + ~nsh + 1 = F - nsh
1423
+ add_gate(tensors, f"{prefix}.too_deep", [1.0] * (E + 2 - RB), [-1.0])
1424
+ add_gate(tensors, f"{prefix}.not_deep", [-1.0], [0.0])
1425
+ for j in range(RB): # right-barrel by rshift
1426
+ add_gate(tensors, f"{prefix}.rbar.s{j}.drop", [1.0] * (1 << j), [-1.0])
1427
+ add_gate(tensors, f"{prefix}.rbar.s{j}.st_and", [1.0, 1.0], [-2.0])
1428
+ add_gate(tensors, f"{prefix}.rbar.s{j}.sticky", [1.0, 1.0], [-1.0])
1429
+ for k in range(RESM + 1): # product widened by 1 low bit
1430
+ add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.not_sel", [-1.0], [0.0])
1431
+ add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.and_a", [1.0, 1.0], [-2.0])
1432
+ add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.and_b", [1.0, 1.0], [-2.0])
1433
+ add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.or", [1.0, 1.0], [-1.0])
1434
  for k in range(F):
1435
+ add_gate(tensors, f"{prefix}.sig.bit{k}", [1.0, 1.0], [-2.0]) # shifted[k+1] AND not_deep
1436
+ add_gate(tensors, f"{prefix}.round.guard", [1.0, 1.0], [-2.0]) # shifted[0] AND not_deep
1437
+ add_gate(tensors, f"{prefix}.deep_nz", [1.0, 1.0], [-2.0]) # too_deep AND product nonzero
1438
+ add_gate(tensors, f"{prefix}.round.sticky", [1.0, 1.0], [-1.0]) # barrel sticky OR deep_nz
1439
+ add_gate(tensors, f"{prefix}.round.rsl", [1.0, 1.0], [-1.0]) # sticky OR lsb
1440
+ add_gate(tensors, f"{prefix}.round.up", [1.0, 1.0], [-2.0]) # guard AND rsl
 
 
 
 
 
 
 
 
 
 
 
 
1441
  for k in range(F):
1442
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.or", [1.0, 1.0], [-1.0])
1443
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.nand", [-1.0, -1.0], [1.0])
1444
  add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer2", [1.0, 1.0], [-2.0])
1445
  add_gate(tensors, f"{prefix}.rnd.bit{k}.carry", [1.0, 1.0], [-2.0])
 
 
 
 
 
 
1446
  for bit in range(E + 2):
1447
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
1448
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
1449
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
1450
  add_gate(tensors, f"{prefix}.exp_round.bit{bit}.carry", [1.0, 1.0], [-2.0])
 
 
1451
  add_gate(tensors, f"{prefix}.exp_r.zero", [-1.0] * (E + 2), [0.0])
 
1452
  add_gate(tensors, f"{prefix}.exp_r.not_neg", [-1.0], [0.0])
1453
  add_gate(tensors, f"{prefix}.exp_r.and_low", [1.0] * E, [-float(E)])
1454
  add_gate(tensors, f"{prefix}.exp_r.ge_emax", [1.0, 1.0], [-1.0])
 
3021
  one = reg.get_id("#1")
3022
 
3023
  def m_a(k: int) -> int:
3024
+ return R("a.exp_nzero") if k == F else a(W - 1 - k)
3025
 
3026
  def m_b(k: int) -> int:
3027
+ return R("b.exp_nzero") if k == F else b(W - 1 - k)
3028
 
3029
+ def eexp(op, k: int) -> int:
3030
+ w = a if op == "a" else b
3031
+ return R(f"{op}.eexp_lsb") if k == 0 else (w(E - k) if k < E else zero)
3032
 
3033
  def P(k: int) -> int:
3034
  return R(f"mant_mul.acc.s{F - 1}.fa{k}.ha2.sum.layer2")
 
3037
  exp_b_field = [b(1 + i) for i in range(E)]
3038
  frac_a_field = [a(1 + E + i) for i in range(F)]
3039
  frac_b_field = [b(1 + E + i) for i in range(F)]
 
3040
  suffix = gate[len(prefix) + 1:] if gate != prefix else ""
 
3041
  bias = (1 << (E - 1)) - 1
3042
+ RESM = 2 * F + 2
3043
+ nlzb = 0
3044
+ while (1 << nlzb) <= RESM:
3045
+ nlzb += 1
3046
+ RB = 0
3047
+ while (1 << RB) < RESM:
3048
+ RB += 1
3049
+
3050
+ def exp_l(k: int) -> int: # exp_base = exp_a + exp_b - bias
3051
+ return R(f"expb.fa{k}.ha2.sum.layer2") if k < E + 2 else zero
3052
+
3053
+ def shifted(k: int) -> int: # product right-shifted by rsh
3054
+ return R(f"rbar.s{RB - 1}.bit{k}.or")
3055
 
3056
  table = {
3057
  "sign_xor.layer1.or": [a(0), b(0)],
3058
  "sign_xor.layer1.nand": [a(0), b(0)],
3059
  "sign_xor.layer2": [R("sign_xor.layer1.or"), R("sign_xor.layer1.nand")],
3060
+ "a.exp_zero": exp_a_field, "a.exp_nzero": exp_a_field, "a.exp_max": exp_a_field,
3061
  "a.frac_nz": frac_a_field, "a.frac_zero": frac_a_field,
3062
  "a.is_nan": [R("a.exp_max"), R("a.frac_nz")],
3063
  "a.is_inf": [R("a.exp_max"), R("a.frac_zero")],
3064
+ "a.is_zero": [R("a.exp_zero"), R("a.frac_zero")], "a.nonzero": [R("a.is_zero")],
3065
+ "a.eexp_lsb": [a(E), R("a.exp_zero")],
3066
+ "b.exp_zero": exp_b_field, "b.exp_nzero": exp_b_field, "b.exp_max": exp_b_field,
3067
  "b.frac_nz": frac_b_field, "b.frac_zero": frac_b_field,
3068
  "b.is_nan": [R("b.exp_max"), R("b.frac_nz")],
3069
  "b.is_inf": [R("b.exp_max"), R("b.frac_zero")],
3070
+ "b.is_zero": [R("b.exp_zero"), R("b.frac_zero")], "b.nonzero": [R("b.is_zero")],
3071
+ "b.eexp_lsb": [b(E), R("b.exp_zero")],
3072
+ "lzc.nz": [P(k) for k in range(RESM)],
3073
+ "lzc.not_nz": [R("lzc.nz")],
3074
+ "er.zero": [R(f"exp_r.fa{k}.ha2.sum.layer2") for k in range(E + 2)],
3075
+ "er.underflow": [R(f"exp_r.fa{E + 1}.ha2.sum.layer2"), R("er.zero")],
3076
+ "er.not_underflow": [R("er.underflow")],
3077
+ "too_deep": [R(f"rsh.fa{k}.ha2.sum.layer2") for k in range(RB, E + 2)],
3078
+ "not_deep": [R("too_deep")],
3079
+ "deep_nz": [R("too_deep"), R("lzc.nz")],
3080
+ "round.guard": [shifted(0), R("not_deep")],
3081
+ "round.sticky": [R(f"rbar.s{RB - 1}.sticky"), R("deep_nz")],
3082
+ "round.rsl": [R("round.sticky"), R("sig.bit0")],
3083
+ "round.up": [R("round.guard"), R("round.rsl")],
3084
  "exp_r.zero": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E + 2)],
 
3085
  "exp_r.not_neg": [R(f"exp_round.bit{E + 1}.xor.layer2")],
3086
  "exp_r.and_low": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E)],
3087
  "exp_r.ge_emax": [R(f"exp_round.bit{E}.xor.layer2"), R("exp_r.and_low")],
3088
  "exp_r.overflow": [R("exp_r.not_neg"), R("exp_r.ge_emax")],
 
 
 
 
 
3089
  "sel.inputs_nan": [R("a.is_nan"), R("b.is_nan")],
3090
+ "sel.inf_zero1": [R("a.is_inf"), R("b.is_zero")],
3091
+ "sel.inf_zero2": [R("b.is_inf"), R("a.is_zero")],
3092
  "sel.inf_zero": [R("sel.inf_zero1"), R("sel.inf_zero2")],
3093
  "sel.nan": [R("sel.inputs_nan"), R("sel.inf_zero")],
3094
  "sel.not_nan": [R("sel.nan")],
3095
  "sel.inf_in": [R("a.is_inf"), R("b.is_inf")],
3096
+ "sel.zero_in": [R("a.is_zero"), R("b.is_zero")],
3097
  "sel.inf_or_ovf": [R("sel.inf_in"), R("exp_r.overflow")],
3098
  "sel.not_inf_path": [R("sel.inf_or_ovf")],
3099
  "sel.inf": [R("sel.not_nan"), R("sel.inf_or_ovf")],
3100
+ "sel.zero_or_unf": [R("sel.zero_in"), R("sel.zero_in")],
3101
  "sel.not_zero_unf": [R("sel.zero_or_unf")],
3102
  "sel.zero": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.zero_or_unf")],
3103
  "sel.norm": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.not_zero_unf")],
 
3115
  k = int(m.group(1))
3116
  cin = zero if k == 0 else R(f"exp_add.fa{k - 1}.carry_or")
3117
  return _fa_member_inputs(m.group(2), f"{prefix}.exp_add.fa{k}",
3118
+ eexp("a", k), eexp("b", k), cin, reg)
3119
+
3120
+ m = re.match(r"^expb\.fa(\d+)\.(.+)$", suffix) # exp_base = exp_add - bias
3121
+ if m:
3122
+ k = int(m.group(1))
3123
+ a_sig = R(f"exp_add.fa{k}.ha2.sum.layer2") if k <= E else zero
3124
+ b_sig = zero if (bias >> k) & 1 else one
3125
+ cin = one if k == 0 else R(f"expb.fa{k - 1}.carry_or")
3126
+ return _fa_member_inputs(m.group(2), f"{prefix}.expb.fa{k}", a_sig, b_sig, cin, reg)
3127
 
3128
  m = re.match(r"^mant_mul\.acc\.s(\d+)\.fa(\d+)\.(.+)$", suffix)
3129
  if m:
 
3139
  return _fa_member_inputs(m.group(3), f"{prefix}.mant_mul.acc.s{t}.fa{k}",
3140
  a_sig, b_sig, cin, reg)
3141
 
3142
+ m = re.match(r"^lzc\.any_higher(\d+)$", suffix)
3143
+ if m:
3144
+ pos = int(m.group(1))
3145
+ return [P(RESM - 1 - t) for t in range(pos)]
3146
+ m = re.match(r"^lzc\.is_highest(\d+)\.(not_higher|and)$", suffix)
3147
+ if m:
3148
+ pos = int(m.group(1))
3149
+ if m.group(2) == "not_higher":
3150
+ return [R(f"lzc.any_higher{pos}")]
3151
+ return [P(RESM - 1 - pos), R(f"lzc.is_highest{pos}.not_higher")]
3152
+ m = re.match(r"^lzc\.nlz\.bit(\d+)$", suffix)
3153
+ if m:
3154
+ bbit = int(m.group(1))
3155
+ srcs = [R(f"lzc.is_highest{pos}.and") for pos in range(1, RESM) if (pos >> bbit) & 1]
3156
+ return srcs if srcs else [zero]
3157
+ m = re.match(r"^exp_nnlz\.bit(\d+)$", suffix)
3158
+ if m:
3159
+ return [R(f"lzc.nlz.bit{int(m.group(1))}")]
3160
+ m = re.match(r"^exp_s1\.fa(\d+)\.(.+)$", suffix) # exp_base - nlz
3161
+ if m:
3162
+ k = int(m.group(1))
3163
+ b_sig = R(f"exp_nnlz.bit{k}") if k < nlzb else one
3164
+ cin = one if k == 0 else R(f"exp_s1.fa{k - 1}.carry_or")
3165
+ return _fa_member_inputs(m.group(2), f"{prefix}.exp_s1.fa{k}", exp_l(k), b_sig, cin, reg)
3166
+ m = re.match(r"^exp_r\.fa(\d+)\.(.+)$", suffix) # + 1
3167
+ if m:
3168
+ k = int(m.group(1))
3169
+ a_sig = R(f"exp_s1.fa{k}.ha2.sum.layer2")
3170
+ cin = one if k == 0 else R(f"exp_r.fa{k - 1}.carry_or")
3171
+ return _fa_member_inputs(m.group(2), f"{prefix}.exp_r.fa{k}", a_sig, zero, cin, reg)
3172
+ m = re.match(r"^exprc\.bit(\d+)$", suffix) # er clamped to >= 0
3173
+ if m:
3174
+ k = int(m.group(1))
3175
+ return [R(f"exp_r.fa{k}.ha2.sum.layer2"), R("er.not_underflow")]
3176
+ m = re.match(r"^nsh\.bit(\d+)\.(not_sel|and_a|and_b|or)$", suffix) # min(nlz, exp_base)
3177
  if m:
3178
  k = int(m.group(1))
3179
  kind = m.group(2)
3180
+ nlz_bit = R(f"lzc.nlz.bit{k}") if k < nlzb else zero
3181
  if kind == "not_sel":
3182
+ return [R("er.underflow")]
3183
  if kind == "and_a":
3184
+ return [nlz_bit, R(f"nsh.bit{k}.not_sel")]
3185
  if kind == "and_b":
3186
+ return [exp_l(k), R("er.underflow")]
3187
+ return [R(f"nsh.bit{k}.and_a"), R(f"nsh.bit{k}.and_b")]
3188
+ m = re.match(r"^nshc\.bit(\d+)$", suffix) # ~nsh
3189
+ if m:
3190
+ return [R(f"nsh.bit{int(m.group(1))}.or")]
3191
+ m = re.match(r"^rsh\.fa(\d+)\.(.+)$", suffix) # rshift = (F+1) + ~nsh + 1
3192
  if m:
3193
  k = int(m.group(1))
3194
+ a_sig = one if ((F + 1) >> k) & 1 else zero
3195
+ cin = one if k == 0 else R(f"rsh.fa{k - 1}.carry_or")
3196
+ return _fa_member_inputs(m.group(2), f"{prefix}.rsh.fa{k}", a_sig, R(f"nshc.bit{k}"), cin, reg)
3197
+ m = re.match(r"^rbar\.s(\d+)\.(.+)$", suffix) # right-barrel shift by rshift
3198
+ if m:
3199
+ j = int(m.group(1))
3200
+ rest = m.group(2)
3201
+ sel = R(f"rsh.fa{j}.ha2.sum.layer2")
3202
 
3203
+ def rin(k: int) -> int: # widened product Pw = P << 1
3204
+ if k < 0 or k > RESM:
3205
+ return zero
3206
+ if j == 0:
3207
+ return zero if k == 0 else P(k - 1)
3208
+ return R(f"rbar.s{j - 1}.bit{k}.or")
3209
+
3210
+ if rest == "drop":
3211
+ return [rin(k) for k in range(1 << j)]
3212
+ if rest == "st_and":
3213
+ return [sel, R(f"rbar.s{j}.drop")]
3214
+ if rest == "sticky":
3215
+ prev = zero if j == 0 else R(f"rbar.s{j - 1}.sticky")
3216
+ return [prev, R(f"rbar.s{j}.st_and")]
3217
+ mm = re.match(r"^bit(\d+)\.(not_sel|and_a|and_b|or)$", rest)
3218
+ if mm:
3219
+ k = int(mm.group(1))
3220
+ kind = mm.group(2)
3221
+ if kind == "not_sel":
3222
+ return [sel]
3223
+ if kind == "and_a":
3224
+ return [rin(k), R(f"rbar.s{j}.bit{k}.not_sel")]
3225
+ if kind == "and_b":
3226
+ return [rin(k + (1 << j)), sel]
3227
+ return [R(f"rbar.s{j}.bit{k}.and_a"), R(f"rbar.s{j}.bit{k}.and_b")]
3228
+ m = re.match(r"^sig\.bit(\d+)$", suffix) # mantissa frac bit (masked)
3229
  if m:
3230
+ return [shifted(int(m.group(1)) + 1), R("not_deep")]
 
 
 
 
 
 
 
 
 
 
3231
 
 
3232
  m = re.match(r"^rnd\.bit(\d+)\.(.+)$", suffix)
3233
  if m:
3234
  k = int(m.group(1))
3235
  rest = m.group(2)
3236
  cin = R("round.up") if k == 0 else R(f"rnd.bit{k - 1}.carry")
3237
+ f_bit = R(f"sig.bit{k}")
3238
  if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
3239
  return [f_bit, cin]
3240
  if rest == "xor.layer2":
 
3242
  if rest == "carry":
3243
  return [f_bit, cin]
3244
 
 
3245
  m = re.match(r"^exp_round\.bit(\d+)\.(.+)$", suffix)
3246
  if m:
3247
  k = int(m.group(1))
3248
  rest = m.group(2)
3249
  cin = R(f"rnd.bit{F - 1}.carry") if k == 0 else R(f"exp_round.bit{k - 1}.carry")
3250
+ e_bit = R(f"exprc.bit{k}")
3251
  if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
3252
  return [e_bit, cin]
3253
  if rest == "xor.layer2":
src/eval.py CHANGED
@@ -685,8 +685,9 @@ def float_test_words(exp_bits: int, frac_bits: int) -> Tuple[List[int], List[int
685
 
686
  def float_mul_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
687
  """Expected product word under the documented contract: exact IEEE
688
- specials (NaN, infinities, signed zeros), flush-to-zero subnormals,
689
- round-to-nearest-even mantissa. Pure integer arithmetic, so exact."""
 
690
  E, F = exp_bits, frac_bits
691
  emax = (1 << E) - 1
692
  fmask = (1 << F) - 1
@@ -699,35 +700,55 @@ def float_mul_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
699
  b_nan = eb == emax and fb != 0
700
  a_inf = ea == emax and fa == 0
701
  b_inf = eb == emax and fb == 0
702
- a_zero = ea == 0 # flush-to-zero
703
- b_zero = eb == 0
704
- inf_w = (s << (E + F)) | (emax << F)
705
- zero_w = s << (E + F)
706
  if a_nan or b_nan or (a_inf and b_zero) or (b_inf and a_zero):
707
  return qnan
708
  if a_inf or b_inf:
709
- return inf_w
710
  if a_zero or b_zero:
711
- return zero_w
712
- Ma, Mb = (1 << F) | fa, (1 << F) | fb
 
 
 
713
  P = Ma * Mb
714
- exp_r = ea + eb - bias
715
- shift = F + 1 if P >= (1 << (2 * F + 1)) else F
716
- if shift == F + 1:
717
- exp_r += 1
718
- frac = (P >> shift) & fmask
719
- guard = (P >> (shift - 1)) & 1
720
- below = P & ((1 << (shift - 1)) - 1)
721
- if guard and ((frac & 1) or below): # round-to-nearest-even
722
- frac += 1
723
- if frac > fmask:
724
- frac = 0
725
- exp_r += 1
726
- if exp_r >= emax:
727
- return inf_w
728
- if exp_r <= 0:
729
- return zero_w
730
- return (s << (E + F)) | (exp_r << F) | frac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
731
 
732
 
733
  def float_div_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
 
685
 
686
  def float_mul_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
687
  """Expected product word under the documented contract: exact IEEE
688
+ specials (NaN, infinities, signed zeros), subnormal operands and
689
+ gradual-underflow subnormal results, round-to-nearest-even mantissa.
690
+ Pure integer arithmetic, so exact."""
691
  E, F = exp_bits, frac_bits
692
  emax = (1 << E) - 1
693
  fmask = (1 << F) - 1
 
700
  b_nan = eb == emax and fb != 0
701
  a_inf = ea == emax and fa == 0
702
  b_inf = eb == emax and fb == 0
703
+ a_zero = ea == 0 and fa == 0
704
+ b_zero = eb == 0 and fb == 0
 
 
705
  if a_nan or b_nan or (a_inf and b_zero) or (b_inf and a_zero):
706
  return qnan
707
  if a_inf or b_inf:
708
+ return (s << (E + F)) | (emax << F)
709
  if a_zero or b_zero:
710
+ return s << (E + F)
711
+ Ma = ((1 << F) if ea else 0) | fa
712
+ Mb = ((1 << F) if eb else 0) | fb
713
+ eea = ea if ea else 1
714
+ eeb = eb if eb else 1
715
  P = Ma * Mb
716
+ t = P.bit_length() - 1
717
+ er = t + eea + eeb - bias - 2 * F
718
+ if er >= 1:
719
+ drop = t - F
720
+ if drop <= 0:
721
+ mant = P << (-drop)
722
+ guard = sticky = 0
723
+ else:
724
+ mant = P >> drop
725
+ guard = (P >> (drop - 1)) & 1
726
+ sticky = 1 if (P & ((1 << (drop - 1)) - 1)) else 0
727
+ frac = mant & fmask
728
+ if guard and ((frac & 1) or sticky):
729
+ frac += 1
730
+ if frac > fmask:
731
+ frac = 0
732
+ er += 1
733
+ if er >= emax:
734
+ return (s << (E + F)) | (emax << F)
735
+ return (s << (E + F)) | (er << F) | frac
736
+ sh_q = eea + eeb - bias - F - 1 # subnormal: value in quanta
737
+ if sh_q >= 0:
738
+ sig = P << sh_q
739
+ guard = sticky = 0
740
+ else:
741
+ r = -sh_q
742
+ sig = P >> r
743
+ guard = (P >> (r - 1)) & 1
744
+ sticky = 1 if (P & ((1 << (r - 1)) - 1)) else 0
745
+ if guard and ((sig & 1) or sticky):
746
+ sig += 1
747
+ if sig == 0:
748
+ return s << (E + F)
749
+ if sig >= (1 << F):
750
+ return (s << (E + F)) | (1 << F)
751
+ return (s << (E + F)) | sig
752
 
753
 
754
  def float_div_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
tools/build_all.py CHANGED
@@ -59,7 +59,7 @@ def build_variant(bits: int, profile: str) -> Path:
59
  "--model", str(out),
60
  "all",
61
  ]
62
- rc, log = run(cmd, timeout=900)
63
  if rc != 0:
64
  raise RuntimeError(f"build failed for bits={bits} profile={profile}:\n{log[-1500:]}")
65
  return out
 
59
  "--model", str(out),
60
  "all",
61
  ]
62
+ rc, log = run(cmd, timeout=2400)
63
  if rc != 0:
64
  raise RuntimeError(f"build failed for bits={bits} profile={profile}:\n{log[-1500:]}")
65
  return out
variants/neural_alu16.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:e92fb3263f1948b0cd938f78594ce2baca3b053ad7939e64667a5ae8e6e182e3
3
- size 25822959
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:802a94ce8fe13fb1a65948d129b1a7ce867854d12a7e6c9ea29ad07cbf80101c
3
+ size 26669131
variants/neural_alu32.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2fcbf8a56e08e0d6f72ec61c68868484ff1038b85785ce57f83719c5c43e05ed
3
- size 24208884
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7d356eacda47b4d7854ddf6cf2ef1959099874e2a52f189f3bbf079112a4ce9d
3
+ size 25056244
variants/neural_alu8.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:d4e40b7c4dbf79ddcd6feca6db9ac853fbfea65b13ee84ec268118f68ed858f3
3
- size 24208884
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1b20bb8b51f6461b377ef7075d143fc722d373cc1f8a788ed784bbb38926d69d
3
+ size 25056244
variants/neural_computer16.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:5a50dfd96e816f5dfecbf9742ba47dc7dc85b0b731d77b7e9559a99416076450
3
- size 34340029
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:af69d406922aa5bd6951fc26107e926a3952fe6500c9bb8764dc372719dc3015
3
+ size 35185717
variants/neural_computer16_reduced.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:e94b82694608f25c51025589607a1367bfa4f1a386ce49e439e410c943c98a2b
3
- size 26528605
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c905b9f7dc4777b30c5f48b055ed285b1fc33b12d93a476f7423427b5e815fc1
3
+ size 27374453
variants/neural_computer16_registers.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:da356d6e85d0ca1f8974da875443bfaa44fe2ecd04e99fbaf8b76deee3708de8
3
- size 25909241
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1efb427160154a95592968ddeb2c9bb9ef52317abc2ac918308a690759fd8c47
3
+ size 26755145
variants/neural_computer16_scratchpad.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:532d6b74bc92a29964f913a6e0ac1ccdaceba9493c1756777917eba27bf70da1
3
- size 25993225
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:225e933c57d6367695138523e76c069941895ad459621b7d52c8ed25739201a5
3
+ size 26839997
variants/neural_computer16_small.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:abaef8566344b04e4fd2337f3e1f42a20c75ea3d4086fa3929b4ecd2cb189efb
3
- size 26113273
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9b23b977f92f953d9f85f4aeec991163f325f2e881871ec567c8292a3315122e
3
+ size 26959213
variants/neural_computer32.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f3168c466f9fc791c09b76e1c61d92290db6c2e4861a9f3a918538a5e5739f1b
3
- size 32744930
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9340602703da2e7563954a45a2febb1d8ed026ac861b493883add2d5311f1f9d
3
+ size 33592582
variants/neural_computer32_reduced.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:77c6058877d8f45bce5b4f9d1de23fab27778f40e61664b14af8da7f40bc425a
3
- size 24933450
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9fa760a30def5486195c584adc51816bf289496c8d5faaadb728a17bed0201d5
3
+ size 25781462
variants/neural_computer32_registers.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8f0f9d4a406245d90f7af61efeb06d278622d1d6e1f092352e42570c5d5dec22
3
- size 24314842
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:15bf955559b534d3fd6243b45f89d42ae6d12a8784464536dc08ec745befbc84
3
+ size 25162246
variants/neural_computer32_scratchpad.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:23954f1ed95013c22fb0615b51f067af577d70d73d2272e65dac340fe8cfa6c6
3
- size 24398894
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:495bca1533a313103fb30eaff2400899ccabf4911a4c08543e6d66252febf498
3
+ size 25246246
variants/neural_computer32_small.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:541486f8f9d4c97fc15d1b570fbe4755b86caa427f298497210caa64b701086c
3
- size 24518134
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:38d52839bac1d351804c76403dc5f51bf9d2bf22eaa5a7d3f8fac25dc9f2a84e
3
+ size 25365434
variants/neural_computer8.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:a96383445eb0444762581d2367f7f267cd5c4df11ed134418e6bacb411ebb191
3
- size 32716722
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:af719c6b6499b85dba19ba425dcb15c9a06c19f6cbb8ed160bfe78484dea5b1a
3
+ size 33564518
variants/neural_computer8_reduced.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:05cb6b712995dcf03e5c255549acae4164648deac2a3eb0e9020610d006a4de9
3
- size 24905274
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e4a3ffff1d0d89ed5f7b5cb1a5bd21b06a89efa834e5daebe7296f19bd750c44
3
+ size 25752570
variants/neural_computer8_registers.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:aab74497c840464b01468cd11b2b6306ab560160a9884a1600104a8557b9c979
3
- size 24285846
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9287c670af87dc6e7682d670d9d671bcf5d021065c7fdc77a0c3336e8f45ace7
3
+ size 25134066
variants/neural_computer8_scratchpad.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:0bfe7fe7d52b329188f0715fc16c54b862f125979fbe4a3baf0361236a43b2ff
3
- size 24370694
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d468d051f2b58c8b2cfb360be2022a67f344cfc8d3f51fee51dc02ebb3384c7a
3
+ size 25218118
variants/neural_computer8_small.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8dec1874af2d8fffe46aa710d9c73922cfb0188c460ca1595af5d6a84d3c01e4
3
- size 24489934
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6ec97c8709bfa2f5916849776cf65b2f0dcbd771b45a2c099e39dca7087e8846
3
+ size 25337262