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 +2 -2
- src/build.py +201 -89
- src/eval.py +47 -26
- tools/build_all.py +1 -1
- variants/neural_alu16.safetensors +2 -2
- variants/neural_alu32.safetensors +2 -2
- variants/neural_alu8.safetensors +2 -2
- variants/neural_computer16.safetensors +2 -2
- variants/neural_computer16_reduced.safetensors +2 -2
- variants/neural_computer16_registers.safetensors +2 -2
- variants/neural_computer16_scratchpad.safetensors +2 -2
- variants/neural_computer16_small.safetensors +2 -2
- variants/neural_computer32.safetensors +2 -2
- variants/neural_computer32_reduced.safetensors +2 -2
- variants/neural_computer32_registers.safetensors +2 -2
- variants/neural_computer32_scratchpad.safetensors +2 -2
- variants/neural_computer32_small.safetensors +2 -2
- variants/neural_computer8.safetensors +2 -2
- variants/neural_computer8_reduced.safetensors +2 -2
- variants/neural_computer8_registers.safetensors +2 -2
- variants/neural_computer8_scratchpad.safetensors +2 -2
- variants/neural_computer8_small.safetensors +2 -2
neural_computer.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 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),
|
| 1338 |
-
|
| 1339 |
|
| 1340 |
Datapath: (F+1)x(F+1) partial products accumulated shift-add into the
|
| 1341 |
-
2F+2-bit product
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 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
|
|
|
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1381 |
for k in range(F):
|
| 1382 |
-
add_gate(tensors, f"{prefix}.
|
| 1383 |
-
|
| 1384 |
-
|
| 1385 |
-
|
| 1386 |
-
|
| 1387 |
-
|
| 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
|
| 2993 |
|
| 2994 |
def m_b(k: int) -> int:
|
| 2995 |
-
return
|
| 2996 |
|
| 2997 |
-
def
|
| 2998 |
-
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
"
|
|
|
|
|
|
|
| 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.
|
| 3038 |
-
"sel.inf_zero2": [R("b.is_inf"), R("a.
|
| 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.
|
| 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("
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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"^
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3082 |
if m:
|
| 3083 |
k = int(m.group(1))
|
| 3084 |
kind = m.group(2)
|
| 3085 |
-
|
| 3086 |
if kind == "not_sel":
|
| 3087 |
-
return [
|
| 3088 |
if kind == "and_a":
|
| 3089 |
-
return [
|
| 3090 |
if kind == "and_b":
|
| 3091 |
-
return [
|
| 3092 |
-
return [R(f"
|
| 3093 |
-
|
| 3094 |
-
|
|
|
|
|
|
|
| 3095 |
if m:
|
| 3096 |
k = int(m.group(1))
|
| 3097 |
-
a_sig =
|
| 3098 |
-
|
| 3099 |
-
|
| 3100 |
-
|
| 3101 |
-
|
|
|
|
|
|
|
|
|
|
| 3102 |
|
| 3103 |
-
|
| 3104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3105 |
if m:
|
| 3106 |
-
|
| 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"
|
| 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"
|
| 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),
|
| 689 |
-
round-to-nearest-even mantissa.
|
|
|
|
| 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
|
| 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
|
| 710 |
if a_zero or b_zero:
|
| 711 |
-
return
|
| 712 |
-
Ma
|
|
|
|
|
|
|
|
|
|
| 713 |
P = Ma * Mb
|
| 714 |
-
|
| 715 |
-
|
| 716 |
-
if
|
| 717 |
-
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
|
| 725 |
-
|
| 726 |
-
|
| 727 |
-
|
| 728 |
-
|
| 729 |
-
|
| 730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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=
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 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:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6ec97c8709bfa2f5916849776cf65b2f0dcbd771b45a2c099e39dca7087e8846
|
| 3 |
+
size 25337262
|