CharlesCNorton commited on
Commit ·
32215c3
1
Parent(s): c953041
float div: full IEEE subnormal support (pre-normalize both operands, then right-shift the aligned quotient by max(0,1-er) for gradual underflow); oracle validated bit-exact against numpy; all float variants rebuilt. add/mul/div subnormals now complete.
Browse files- neural_computer.safetensors +2 -2
- src/build.py +235 -52
- src/eval.py +41 -23
- 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:c358cad0b5e5fd8cf83720eeb42a399047409d374932a9dc6ec3ebda754933bf
|
| 3 |
+
size 34601074
|
src/build.py
CHANGED
|
@@ -1492,19 +1492,16 @@ def add_float_div(tensors: Dict[str, torch.Tensor], family: str,
|
|
| 1492 |
Self-contained circuit; external inputs are the raw operand words
|
| 1493 |
$a[0..W-1] / $b[0..W-1] (MSB-first). Contract: exact IEEE specials
|
| 1494 |
(NaN, infinities, signed zeros, x/0 -> inf, 0/0 and inf/inf -> NaN),
|
| 1495 |
-
|
| 1496 |
-
for the mantissa.
|
| 1497 |
-
|
| 1498 |
-
Datapath:
|
| 1499 |
-
|
| 1500 |
-
|
| 1501 |
-
|
| 1502 |
-
|
| 1503 |
-
|
| 1504 |
-
|
| 1505 |
-
|
| 1506 |
-
Rounding: round-to-nearest-even (RNE); underflow flushes to zero,
|
| 1507 |
-
specials exact.
|
| 1508 |
"""
|
| 1509 |
E, F = exp_bits, frac_bits
|
| 1510 |
prefix = f"{family}.div"
|
|
@@ -1516,11 +1513,40 @@ def add_float_div(tensors: Dict[str, torch.Tensor], family: str,
|
|
| 1516 |
|
| 1517 |
for op in ("a", "b"):
|
| 1518 |
add_gate(tensors, f"{prefix}.{op}.exp_zero", [-1.0] * E, [0.0])
|
|
|
|
| 1519 |
add_gate(tensors, f"{prefix}.{op}.exp_max", [1.0] * E, [-float(E)])
|
| 1520 |
add_gate(tensors, f"{prefix}.{op}.frac_nz", [1.0] * F, [-1.0])
|
| 1521 |
add_gate(tensors, f"{prefix}.{op}.frac_zero", [-1.0] * F, [0.0])
|
| 1522 |
add_gate(tensors, f"{prefix}.{op}.is_nan", [1.0, 1.0], [-2.0])
|
| 1523 |
add_gate(tensors, f"{prefix}.{op}.is_inf", [1.0, 1.0], [-2.0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1524 |
|
| 1525 |
# Restoring division stages: per stage a bit-cascade GE comparator, the
|
| 1526 |
# quotient-bit OR (shifted-out top bit forces GE), a conditional
|
|
@@ -1560,7 +1586,44 @@ def add_float_div(tensors: Dict[str, torch.Tensor], family: str,
|
|
| 1560 |
add_gate(tensors, f"{prefix}.round.g.or", [1.0, 1.0], [-1.0])
|
| 1561 |
add_gate(tensors, f"{prefix}.round.rem_nz", [1.0] * (F + 1), [-1.0])
|
| 1562 |
add_gate(tensors, f"{prefix}.round.q_extra", [1.0, 1.0], [-2.0])
|
| 1563 |
-
add_gate(tensors, f"{prefix}.round.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1564 |
add_gate(tensors, f"{prefix}.round.rsl", [1.0, 1.0], [-1.0])
|
| 1565 |
add_gate(tensors, f"{prefix}.round.up", [1.0, 1.0], [-2.0])
|
| 1566 |
for k in range(F):
|
|
@@ -1568,24 +1631,12 @@ def add_float_div(tensors: Dict[str, torch.Tensor], family: str,
|
|
| 1568 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 1569 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 1570 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.carry", [1.0, 1.0], [-2.0])
|
| 1571 |
-
|
| 1572 |
-
# exp_r = exp_a - exp_b + bias - 1 + q0 in E+2-bit two's complement:
|
| 1573 |
-
# chain s1 = exp_a + ~exp_b (cin = q0), then exp_r = s1 + bias (cin = 0).
|
| 1574 |
-
for bit in range(E):
|
| 1575 |
-
add_gate(tensors, f"{prefix}.exp_nb.bit{bit}", [-1.0], [0.0])
|
| 1576 |
-
for bit in range(E + 2):
|
| 1577 |
-
add_full_adder(tensors, f"{prefix}.exp_s1.fa{bit}")
|
| 1578 |
-
add_full_adder(tensors, f"{prefix}.exp_r.fa{bit}")
|
| 1579 |
-
|
| 1580 |
-
# exp_final = exp_r + rounding carry-out (E+2-bit incrementer).
|
| 1581 |
for bit in range(E + 2):
|
| 1582 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 1583 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 1584 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 1585 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.carry", [1.0, 1.0], [-2.0])
|
| 1586 |
-
|
| 1587 |
add_gate(tensors, f"{prefix}.exp_r.zero", [-1.0] * (E + 2), [0.0])
|
| 1588 |
-
add_gate(tensors, f"{prefix}.exp_r.underflow", [1.0, 1.0], [-1.0])
|
| 1589 |
add_gate(tensors, f"{prefix}.exp_r.not_neg", [-1.0], [0.0])
|
| 1590 |
add_gate(tensors, f"{prefix}.exp_r.and_low", [1.0] * E, [-float(E)])
|
| 1591 |
add_gate(tensors, f"{prefix}.exp_r.ge_emax", [1.0, 1.0], [-1.0])
|
|
@@ -3304,11 +3355,40 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3304 |
zero = reg.get_id("#0")
|
| 3305 |
one = reg.get_id("#1")
|
| 3306 |
|
| 3307 |
-
|
| 3308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3309 |
|
| 3310 |
-
def
|
| 3311 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3312 |
|
| 3313 |
def rem_prev(stage: int, k: int) -> int:
|
| 3314 |
return R(f"mant_div.stage{stage - 1}.mux.bit{k}.or")
|
|
@@ -3337,16 +3417,24 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3337 |
"sign_xor.layer1.or": [a(0), b(0)],
|
| 3338 |
"sign_xor.layer1.nand": [a(0), b(0)],
|
| 3339 |
"sign_xor.layer2": [R("sign_xor.layer1.or"), R("sign_xor.layer1.nand")],
|
| 3340 |
-
"a.exp_zero": exp_a_field, "a.exp_max": exp_a_field,
|
| 3341 |
"a.frac_nz": frac_a_field, "a.frac_zero": frac_a_field,
|
| 3342 |
"a.is_nan": [R("a.exp_max"), R("a.frac_nz")],
|
| 3343 |
"a.is_inf": [R("a.exp_max"), R("a.frac_zero")],
|
| 3344 |
-
"
|
|
|
|
|
|
|
| 3345 |
"b.frac_nz": frac_b_field, "b.frac_zero": frac_b_field,
|
| 3346 |
"b.is_nan": [R("b.exp_max"), R("b.frac_nz")],
|
| 3347 |
"b.is_inf": [R("b.exp_max"), R("b.frac_zero")],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3348 |
"exp_r.zero": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E + 2)],
|
| 3349 |
-
"exp_r.underflow": [R(f"exp_round.bit{E + 1}.xor.layer2"), R("exp_r.zero")],
|
| 3350 |
"exp_r.not_neg": [R(f"exp_round.bit{E + 1}.xor.layer2")],
|
| 3351 |
"exp_r.and_low": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E)],
|
| 3352 |
"exp_r.ge_emax": [R(f"exp_round.bit{E}.xor.layer2"), R("exp_r.and_low")],
|
|
@@ -3357,21 +3445,23 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3357 |
"round.g.or": [R("round.g.and_a"), R("round.g.and_b")],
|
| 3358 |
"round.rem_nz": [R(f"mant_div.stage{F + 2}.mux.bit{k}.or") for k in range(F + 1)],
|
| 3359 |
"round.q_extra": [R("mant_div.stage0.q"), R(f"mant_div.stage{F + 2}.q")],
|
| 3360 |
-
"round.
|
| 3361 |
-
"round.
|
| 3362 |
-
"round.
|
|
|
|
|
|
|
| 3363 |
"sel.inputs_nan": [R("a.is_nan"), R("b.is_nan")],
|
| 3364 |
-
"sel.zero_zero": [R("a.
|
| 3365 |
"sel.inf_inf": [R("a.is_inf"), R("b.is_inf")],
|
| 3366 |
"sel.nan_cases": [R("sel.zero_zero"), R("sel.inf_inf")],
|
| 3367 |
"sel.nan": [R("sel.inputs_nan"), R("sel.nan_cases")],
|
| 3368 |
"sel.not_nan": [R("sel.nan")],
|
| 3369 |
-
"sel.inf_in": [R("a.is_inf"), R("b.
|
| 3370 |
-
"sel.zero_in": [R("a.
|
| 3371 |
"sel.inf_or_ovf": [R("sel.inf_in"), R("exp_r.overflow")],
|
| 3372 |
"sel.not_inf_path": [R("sel.inf_or_ovf")],
|
| 3373 |
"sel.inf": [R("sel.not_nan"), R("sel.inf_or_ovf")],
|
| 3374 |
-
"sel.zero_or_unf": [R("sel.zero_in"), R("
|
| 3375 |
"sel.not_zero_unf": [R("sel.zero_or_unf")],
|
| 3376 |
"sel.zero": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.zero_or_unf")],
|
| 3377 |
"sel.norm": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.not_zero_unf")],
|
|
@@ -3380,27 +3470,120 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3380 |
if suffix in table:
|
| 3381 |
return table[suffix]
|
| 3382 |
|
| 3383 |
-
m = re.match(r"^
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3384 |
if m:
|
| 3385 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3386 |
|
| 3387 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3388 |
if m:
|
| 3389 |
k = int(m.group(1))
|
| 3390 |
-
a_sig = a(E - k) if k < E else zero
|
| 3391 |
-
b_sig = R(f"exp_nb.bit{k}") if k < E else one
|
| 3392 |
cin = q(0) if k == 0 else R(f"exp_s1.fa{k - 1}.carry_or")
|
| 3393 |
return _fa_member_inputs(m.group(2), f"{prefix}.exp_s1.fa{k}",
|
| 3394 |
-
|
| 3395 |
-
|
| 3396 |
-
m = re.match(r"^exp_r\.fa(\d+)\.(.+)$", suffix)
|
| 3397 |
if m:
|
| 3398 |
k = int(m.group(1))
|
| 3399 |
a_sig = R(f"exp_s1.fa{k}.ha2.sum.layer2")
|
| 3400 |
b_sig = one if (bias >> k) & 1 else zero
|
| 3401 |
cin = zero if k == 0 else R(f"exp_r.fa{k - 1}.carry_or")
|
| 3402 |
-
return _fa_member_inputs(m.group(2), f"{prefix}.exp_r.fa{k}",
|
| 3403 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3404 |
|
| 3405 |
m = re.match(r"^mant_div\.stage(\d+)\.(.+)$", suffix)
|
| 3406 |
if m:
|
|
@@ -3491,7 +3674,7 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3491 |
k = int(m.group(1))
|
| 3492 |
rest = m.group(2)
|
| 3493 |
cin = R("round.up") if k == 0 else R(f"rnd.bit{k - 1}.carry")
|
| 3494 |
-
f_bit = R(f"
|
| 3495 |
if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
|
| 3496 |
return [f_bit, cin]
|
| 3497 |
if rest == "xor.layer2":
|
|
@@ -3504,7 +3687,7 @@ def infer_float_div_inputs(gate: str, reg: SignalRegistry, family: str,
|
|
| 3504 |
k = int(m.group(1))
|
| 3505 |
rest = m.group(2)
|
| 3506 |
cin = R(f"rnd.bit{F - 1}.carry") if k == 0 else R(f"exp_round.bit{k - 1}.carry")
|
| 3507 |
-
e_bit = R(f"
|
| 3508 |
if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
|
| 3509 |
return [e_bit, cin]
|
| 3510 |
if rest == "xor.layer2":
|
|
|
|
| 1492 |
Self-contained circuit; external inputs are the raw operand words
|
| 1493 |
$a[0..W-1] / $b[0..W-1] (MSB-first). Contract: exact IEEE specials
|
| 1494 |
(NaN, infinities, signed zeros, x/0 -> inf, 0/0 and inf/inf -> NaN),
|
| 1495 |
+
subnormal operands and gradual-underflow subnormal results,
|
| 1496 |
+
round-to-nearest-even for the mantissa.
|
| 1497 |
+
|
| 1498 |
+
Datapath: each operand mantissa is pre-normalized (a leading-zero count
|
| 1499 |
+
drives a left-barrel so the leading 1 sits at bit F, and na = eexp - lz);
|
| 1500 |
+
F+3 restoring-division stages produce the quotient; a one-bit normalize mux
|
| 1501 |
+
aligns it on the integer quotient bit; two E+2-bit exponent chains give
|
| 1502 |
+
er = na - nb + bias - 1 + q0; the aligned mantissa frame is right-shifted by
|
| 1503 |
+
max(0, 1 - er) to denormalize subnormal quotients; then round-to-nearest-even
|
| 1504 |
+
and a one-hot specials network produce the output word.
|
|
|
|
|
|
|
|
|
|
| 1505 |
"""
|
| 1506 |
E, F = exp_bits, frac_bits
|
| 1507 |
prefix = f"{family}.div"
|
|
|
|
| 1513 |
|
| 1514 |
for op in ("a", "b"):
|
| 1515 |
add_gate(tensors, f"{prefix}.{op}.exp_zero", [-1.0] * E, [0.0])
|
| 1516 |
+
add_gate(tensors, f"{prefix}.{op}.exp_nzero", [1.0] * E, [-1.0])
|
| 1517 |
add_gate(tensors, f"{prefix}.{op}.exp_max", [1.0] * E, [-float(E)])
|
| 1518 |
add_gate(tensors, f"{prefix}.{op}.frac_nz", [1.0] * F, [-1.0])
|
| 1519 |
add_gate(tensors, f"{prefix}.{op}.frac_zero", [-1.0] * F, [0.0])
|
| 1520 |
add_gate(tensors, f"{prefix}.{op}.is_nan", [1.0, 1.0], [-2.0])
|
| 1521 |
add_gate(tensors, f"{prefix}.{op}.is_inf", [1.0, 1.0], [-2.0])
|
| 1522 |
+
add_gate(tensors, f"{prefix}.{op}.is_zero", [1.0, 1.0], [-2.0])
|
| 1523 |
+
add_gate(tensors, f"{prefix}.{op}.nonzero", [-1.0], [0.0])
|
| 1524 |
+
add_gate(tensors, f"{prefix}.{op}.eexp_lsb", [1.0, 1.0], [-1.0])
|
| 1525 |
+
|
| 1526 |
+
# Pre-normalize each operand mantissa: a leading-zero count over the F+1-bit
|
| 1527 |
+
# mantissa drives a left-barrel so the leading 1 sits at bit F; na = eexp - lz.
|
| 1528 |
+
ML = F + 1
|
| 1529 |
+
mlzb = 0
|
| 1530 |
+
while (1 << mlzb) <= ML:
|
| 1531 |
+
mlzb += 1
|
| 1532 |
+
for op in ("a", "b"):
|
| 1533 |
+
for pos in range(1, ML):
|
| 1534 |
+
add_gate(tensors, f"{prefix}.{op}.pn.any_higher{pos}", [1.0] * pos, [-1.0])
|
| 1535 |
+
add_gate(tensors, f"{prefix}.{op}.pn.is_highest{pos}.not_higher", [-1.0], [0.0])
|
| 1536 |
+
add_gate(tensors, f"{prefix}.{op}.pn.is_highest{pos}.and", [1.0, 1.0], [-2.0])
|
| 1537 |
+
for bbit in range(mlzb):
|
| 1538 |
+
fan = sum(1 for pos in range(1, ML) if (pos >> bbit) & 1)
|
| 1539 |
+
add_gate(tensors, f"{prefix}.{op}.pn.lz.bit{bbit}", [1.0] * max(1, fan), [-1.0])
|
| 1540 |
+
for bbit in range(mlzb):
|
| 1541 |
+
for k in range(ML):
|
| 1542 |
+
add_gate(tensors, f"{prefix}.{op}.pn.s{bbit}.bit{k}.not_sel", [-1.0], [0.0])
|
| 1543 |
+
add_gate(tensors, f"{prefix}.{op}.pn.s{bbit}.bit{k}.and_a", [1.0, 1.0], [-2.0])
|
| 1544 |
+
add_gate(tensors, f"{prefix}.{op}.pn.s{bbit}.bit{k}.and_b", [1.0, 1.0], [-2.0])
|
| 1545 |
+
add_gate(tensors, f"{prefix}.{op}.pn.s{bbit}.bit{k}.or", [1.0, 1.0], [-1.0])
|
| 1546 |
+
for bbit in range(mlzb):
|
| 1547 |
+
add_gate(tensors, f"{prefix}.{op}.nlz.bit{bbit}", [-1.0], [0.0])
|
| 1548 |
+
for bit in range(E + 2):
|
| 1549 |
+
add_full_adder(tensors, f"{prefix}.{op}.neff.fa{bit}")
|
| 1550 |
|
| 1551 |
# Restoring division stages: per stage a bit-cascade GE comparator, the
|
| 1552 |
# quotient-bit OR (shifted-out top bit forces GE), a conditional
|
|
|
|
| 1586 |
add_gate(tensors, f"{prefix}.round.g.or", [1.0, 1.0], [-1.0])
|
| 1587 |
add_gate(tensors, f"{prefix}.round.rem_nz", [1.0] * (F + 1), [-1.0])
|
| 1588 |
add_gate(tensors, f"{prefix}.round.q_extra", [1.0, 1.0], [-2.0])
|
| 1589 |
+
add_gate(tensors, f"{prefix}.round.sticky_orig", [1.0, 1.0], [-1.0]) # rem_nz OR q_extra
|
| 1590 |
+
|
| 1591 |
+
# exp_r = na - nb + bias - 1 + q0 (E+2-bit two's complement) using the
|
| 1592 |
+
# pre-normalized effective exponents na = a.neff, nb = b.neff.
|
| 1593 |
+
for bit in range(E + 2):
|
| 1594 |
+
add_gate(tensors, f"{prefix}.exp_nb.bit{bit}", [-1.0], [0.0]) # ~nb
|
| 1595 |
+
for bit in range(E + 2):
|
| 1596 |
+
add_full_adder(tensors, f"{prefix}.exp_s1.fa{bit}") # na + ~nb + q0
|
| 1597 |
+
add_full_adder(tensors, f"{prefix}.exp_r.fa{bit}") # + bias
|
| 1598 |
+
|
| 1599 |
+
# Gradual underflow: right-shift the aligned mantissa frame MF (bit 0 guard,
|
| 1600 |
+
# bits 1..F frac, bit F+1 implicit 1) by rsh = max(0, 1 - er).
|
| 1601 |
+
RBd = 0
|
| 1602 |
+
while (1 << RBd) < (F + 2):
|
| 1603 |
+
RBd += 1
|
| 1604 |
+
add_gate(tensors, f"{prefix}.er.zero", [-1.0] * (E + 2), [0.0])
|
| 1605 |
+
add_gate(tensors, f"{prefix}.er.underflow", [1.0, 1.0], [-1.0])
|
| 1606 |
+
add_gate(tensors, f"{prefix}.er.not_underflow", [-1.0], [0.0])
|
| 1607 |
+
for k in range(E + 2):
|
| 1608 |
+
add_gate(tensors, f"{prefix}.exprc.bit{k}", [1.0, 1.0], [-2.0]) # er clamped >= 0
|
| 1609 |
+
add_gate(tensors, f"{prefix}.ernot.bit{k}", [-1.0], [0.0]) # ~er
|
| 1610 |
+
add_full_adder(tensors, f"{prefix}.subv.fa{k}") # 1 - er
|
| 1611 |
+
add_gate(tensors, f"{prefix}.rsh.bit{k}", [1.0, 1.0], [-2.0]) # (1-er) AND underflow
|
| 1612 |
+
add_gate(tensors, f"{prefix}.too_deep", [1.0] * (E + 2 - RBd), [-1.0])
|
| 1613 |
+
add_gate(tensors, f"{prefix}.not_deep", [-1.0], [0.0])
|
| 1614 |
+
for j in range(RBd):
|
| 1615 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.drop", [1.0] * (1 << j), [-1.0])
|
| 1616 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.st_and", [1.0, 1.0], [-2.0])
|
| 1617 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.sticky", [1.0, 1.0], [-1.0])
|
| 1618 |
+
for k in range(F + 2):
|
| 1619 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.not_sel", [-1.0], [0.0])
|
| 1620 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.and_a", [1.0, 1.0], [-2.0])
|
| 1621 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.and_b", [1.0, 1.0], [-2.0])
|
| 1622 |
+
add_gate(tensors, f"{prefix}.rbar.s{j}.bit{k}.or", [1.0, 1.0], [-1.0])
|
| 1623 |
+
for k in range(F):
|
| 1624 |
+
add_gate(tensors, f"{prefix}.sig.bit{k}", [1.0, 1.0], [-2.0]) # shifted[k+1] AND not_deep
|
| 1625 |
+
add_gate(tensors, f"{prefix}.round.guard", [1.0, 1.0], [-2.0]) # shifted[0] AND not_deep
|
| 1626 |
+
add_gate(tensors, f"{prefix}.round.sticky", [1.0, 1.0, 1.0], [-1.0]) # barrel OR orig OR too_deep
|
| 1627 |
add_gate(tensors, f"{prefix}.round.rsl", [1.0, 1.0], [-1.0])
|
| 1628 |
add_gate(tensors, f"{prefix}.round.up", [1.0, 1.0], [-2.0])
|
| 1629 |
for k in range(F):
|
|
|
|
| 1631 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 1632 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 1633 |
add_gate(tensors, f"{prefix}.rnd.bit{k}.carry", [1.0, 1.0], [-2.0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1634 |
for bit in range(E + 2):
|
| 1635 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 1636 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 1637 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 1638 |
add_gate(tensors, f"{prefix}.exp_round.bit{bit}.carry", [1.0, 1.0], [-2.0])
|
|
|
|
| 1639 |
add_gate(tensors, f"{prefix}.exp_r.zero", [-1.0] * (E + 2), [0.0])
|
|
|
|
| 1640 |
add_gate(tensors, f"{prefix}.exp_r.not_neg", [-1.0], [0.0])
|
| 1641 |
add_gate(tensors, f"{prefix}.exp_r.and_low", [1.0] * E, [-float(E)])
|
| 1642 |
add_gate(tensors, f"{prefix}.exp_r.ge_emax", [1.0, 1.0], [-1.0])
|
|
|
|
| 3355 |
zero = reg.get_id("#0")
|
| 3356 |
one = reg.get_id("#1")
|
| 3357 |
|
| 3358 |
+
ML = F + 1
|
| 3359 |
+
mlzb = 0
|
| 3360 |
+
while (1 << mlzb) <= ML:
|
| 3361 |
+
mlzb += 1
|
| 3362 |
+
RBd = 0
|
| 3363 |
+
while (1 << RBd) < (F + 2):
|
| 3364 |
+
RBd += 1
|
| 3365 |
|
| 3366 |
+
def m_raw(op: str, k: int) -> int: # raw mantissa (implicit = exp!=0)
|
| 3367 |
+
w = a if op == "a" else b
|
| 3368 |
+
return R(f"{op}.exp_nzero") if k == F else w(W - 1 - k)
|
| 3369 |
+
|
| 3370 |
+
def m_a(k: int) -> int: # pre-normalized dividend
|
| 3371 |
+
return R(f"a.pn.s{mlzb - 1}.bit{k}.or")
|
| 3372 |
+
|
| 3373 |
+
def m_b(k: int) -> int: # pre-normalized divisor
|
| 3374 |
+
return R(f"b.pn.s{mlzb - 1}.bit{k}.or")
|
| 3375 |
+
|
| 3376 |
+
def eexp(op: str, k: int) -> int:
|
| 3377 |
+
w = a if op == "a" else b
|
| 3378 |
+
return R(f"{op}.eexp_lsb") if k == 0 else (w(E - k) if k < E else zero)
|
| 3379 |
+
|
| 3380 |
+
def na(op: str, k: int) -> int: # effective exponent na = eexp - lz
|
| 3381 |
+
return R(f"{op}.neff.fa{k}.ha2.sum.layer2") if k < E + 2 else zero
|
| 3382 |
+
|
| 3383 |
+
def MF(k: int) -> int: # aligned mantissa frame
|
| 3384 |
+
if k == 0:
|
| 3385 |
+
return R("round.g.or") # guard
|
| 3386 |
+
if k <= F:
|
| 3387 |
+
return R(f"norm.bit{k - 1}.or") # frac[k-1]
|
| 3388 |
+
return one # implicit
|
| 3389 |
+
|
| 3390 |
+
def shifted(k: int) -> int: # frame right-shifted by rsh
|
| 3391 |
+
return R(f"rbar.s{RBd - 1}.bit{k}.or")
|
| 3392 |
|
| 3393 |
def rem_prev(stage: int, k: int) -> int:
|
| 3394 |
return R(f"mant_div.stage{stage - 1}.mux.bit{k}.or")
|
|
|
|
| 3417 |
"sign_xor.layer1.or": [a(0), b(0)],
|
| 3418 |
"sign_xor.layer1.nand": [a(0), b(0)],
|
| 3419 |
"sign_xor.layer2": [R("sign_xor.layer1.or"), R("sign_xor.layer1.nand")],
|
| 3420 |
+
"a.exp_zero": exp_a_field, "a.exp_nzero": exp_a_field, "a.exp_max": exp_a_field,
|
| 3421 |
"a.frac_nz": frac_a_field, "a.frac_zero": frac_a_field,
|
| 3422 |
"a.is_nan": [R("a.exp_max"), R("a.frac_nz")],
|
| 3423 |
"a.is_inf": [R("a.exp_max"), R("a.frac_zero")],
|
| 3424 |
+
"a.is_zero": [R("a.exp_zero"), R("a.frac_zero")], "a.nonzero": [R("a.is_zero")],
|
| 3425 |
+
"a.eexp_lsb": [a(E), R("a.exp_zero")],
|
| 3426 |
+
"b.exp_zero": exp_b_field, "b.exp_nzero": exp_b_field, "b.exp_max": exp_b_field,
|
| 3427 |
"b.frac_nz": frac_b_field, "b.frac_zero": frac_b_field,
|
| 3428 |
"b.is_nan": [R("b.exp_max"), R("b.frac_nz")],
|
| 3429 |
"b.is_inf": [R("b.exp_max"), R("b.frac_zero")],
|
| 3430 |
+
"b.is_zero": [R("b.exp_zero"), R("b.frac_zero")], "b.nonzero": [R("b.is_zero")],
|
| 3431 |
+
"b.eexp_lsb": [b(E), R("b.exp_zero")],
|
| 3432 |
+
"er.zero": [R(f"exp_r.fa{k}.ha2.sum.layer2") for k in range(E + 2)],
|
| 3433 |
+
"er.underflow": [R(f"exp_r.fa{E + 1}.ha2.sum.layer2"), R("er.zero")],
|
| 3434 |
+
"er.not_underflow": [R("er.underflow")],
|
| 3435 |
+
"too_deep": [R(f"rsh.bit{k}") for k in range(RBd, E + 2)],
|
| 3436 |
+
"not_deep": [R("too_deep")],
|
| 3437 |
"exp_r.zero": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E + 2)],
|
|
|
|
| 3438 |
"exp_r.not_neg": [R(f"exp_round.bit{E + 1}.xor.layer2")],
|
| 3439 |
"exp_r.and_low": [R(f"exp_round.bit{k}.xor.layer2") for k in range(E)],
|
| 3440 |
"exp_r.ge_emax": [R(f"exp_round.bit{E}.xor.layer2"), R("exp_r.and_low")],
|
|
|
|
| 3445 |
"round.g.or": [R("round.g.and_a"), R("round.g.and_b")],
|
| 3446 |
"round.rem_nz": [R(f"mant_div.stage{F + 2}.mux.bit{k}.or") for k in range(F + 1)],
|
| 3447 |
"round.q_extra": [R("mant_div.stage0.q"), R(f"mant_div.stage{F + 2}.q")],
|
| 3448 |
+
"round.sticky_orig": [R("round.rem_nz"), R("round.q_extra")],
|
| 3449 |
+
"round.guard": [shifted(0), R("not_deep")],
|
| 3450 |
+
"round.sticky": [R(f"rbar.s{RBd - 1}.sticky"), R("round.sticky_orig"), R("too_deep")],
|
| 3451 |
+
"round.rsl": [R("round.sticky"), R("sig.bit0")],
|
| 3452 |
+
"round.up": [R("round.guard"), R("round.rsl")],
|
| 3453 |
"sel.inputs_nan": [R("a.is_nan"), R("b.is_nan")],
|
| 3454 |
+
"sel.zero_zero": [R("a.is_zero"), R("b.is_zero")],
|
| 3455 |
"sel.inf_inf": [R("a.is_inf"), R("b.is_inf")],
|
| 3456 |
"sel.nan_cases": [R("sel.zero_zero"), R("sel.inf_inf")],
|
| 3457 |
"sel.nan": [R("sel.inputs_nan"), R("sel.nan_cases")],
|
| 3458 |
"sel.not_nan": [R("sel.nan")],
|
| 3459 |
+
"sel.inf_in": [R("a.is_inf"), R("b.is_zero")],
|
| 3460 |
+
"sel.zero_in": [R("a.is_zero"), R("b.is_inf")],
|
| 3461 |
"sel.inf_or_ovf": [R("sel.inf_in"), R("exp_r.overflow")],
|
| 3462 |
"sel.not_inf_path": [R("sel.inf_or_ovf")],
|
| 3463 |
"sel.inf": [R("sel.not_nan"), R("sel.inf_or_ovf")],
|
| 3464 |
+
"sel.zero_or_unf": [R("sel.zero_in"), R("sel.zero_in")],
|
| 3465 |
"sel.not_zero_unf": [R("sel.zero_or_unf")],
|
| 3466 |
"sel.zero": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.zero_or_unf")],
|
| 3467 |
"sel.norm": [R("sel.not_nan"), R("sel.not_inf_path"), R("sel.not_zero_unf")],
|
|
|
|
| 3470 |
if suffix in table:
|
| 3471 |
return table[suffix]
|
| 3472 |
|
| 3473 |
+
m = re.match(r"^([ab])\.pn\.any_higher(\d+)$", suffix) # pre-normalize: LZC
|
| 3474 |
+
if m:
|
| 3475 |
+
op = m.group(1)
|
| 3476 |
+
pos = int(m.group(2))
|
| 3477 |
+
return [m_raw(op, ML - 1 - t) for t in range(pos)]
|
| 3478 |
+
m = re.match(r"^([ab])\.pn\.is_highest(\d+)\.(not_higher|and)$", suffix)
|
| 3479 |
if m:
|
| 3480 |
+
op = m.group(1)
|
| 3481 |
+
pos = int(m.group(2))
|
| 3482 |
+
if m.group(3) == "not_higher":
|
| 3483 |
+
return [R(f"{op}.pn.any_higher{pos}")]
|
| 3484 |
+
return [m_raw(op, ML - 1 - pos), R(f"{op}.pn.is_highest{pos}.not_higher")]
|
| 3485 |
+
m = re.match(r"^([ab])\.pn\.lz\.bit(\d+)$", suffix)
|
| 3486 |
+
if m:
|
| 3487 |
+
op = m.group(1)
|
| 3488 |
+
bbit = int(m.group(2))
|
| 3489 |
+
srcs = [R(f"{op}.pn.is_highest{pos}.and") for pos in range(1, ML) if (pos >> bbit) & 1]
|
| 3490 |
+
return srcs if srcs else [zero]
|
| 3491 |
+
m = re.match(r"^([ab])\.pn\.s(\d+)\.bit(\d+)\.(not_sel|and_a|and_b|or)$", suffix) # left-barrel
|
| 3492 |
+
if m:
|
| 3493 |
+
op = m.group(1)
|
| 3494 |
+
bbit = int(m.group(2))
|
| 3495 |
+
k = int(m.group(3))
|
| 3496 |
+
kind = m.group(4)
|
| 3497 |
+
sel = R(f"{op}.pn.lz.bit{bbit}")
|
| 3498 |
+
|
| 3499 |
+
def lin(kk: int) -> int:
|
| 3500 |
+
if kk < 0 or kk >= ML:
|
| 3501 |
+
return zero
|
| 3502 |
+
return m_raw(op, kk) if bbit == 0 else R(f"{op}.pn.s{bbit - 1}.bit{kk}.or")
|
| 3503 |
|
| 3504 |
+
if kind == "not_sel":
|
| 3505 |
+
return [sel]
|
| 3506 |
+
if kind == "and_a":
|
| 3507 |
+
return [lin(k), R(f"{op}.pn.s{bbit}.bit{k}.not_sel")]
|
| 3508 |
+
if kind == "and_b":
|
| 3509 |
+
return [lin(k - (1 << bbit)), sel]
|
| 3510 |
+
return [R(f"{op}.pn.s{bbit}.bit{k}.and_a"), R(f"{op}.pn.s{bbit}.bit{k}.and_b")]
|
| 3511 |
+
m = re.match(r"^([ab])\.nlz\.bit(\d+)$", suffix)
|
| 3512 |
+
if m:
|
| 3513 |
+
return [R(f"{m.group(1)}.pn.lz.bit{int(m.group(2))}")]
|
| 3514 |
+
m = re.match(r"^([ab])\.neff\.fa(\d+)\.(.+)$", suffix) # na = eexp - lz
|
| 3515 |
+
if m:
|
| 3516 |
+
op = m.group(1)
|
| 3517 |
+
k = int(m.group(2))
|
| 3518 |
+
b_sig = R(f"{op}.nlz.bit{k}") if k < mlzb else one
|
| 3519 |
+
cin = one if k == 0 else R(f"{op}.neff.fa{k - 1}.carry_or")
|
| 3520 |
+
return _fa_member_inputs(m.group(3), f"{prefix}.{op}.neff.fa{k}", eexp(op, k), b_sig, cin, reg)
|
| 3521 |
+
|
| 3522 |
+
m = re.match(r"^exp_nb\.bit(\d+)$", suffix) # ~nb
|
| 3523 |
+
if m:
|
| 3524 |
+
return [na("b", int(m.group(1)))]
|
| 3525 |
+
m = re.match(r"^exp_s1\.fa(\d+)\.(.+)$", suffix) # na + ~nb + q0
|
| 3526 |
if m:
|
| 3527 |
k = int(m.group(1))
|
|
|
|
|
|
|
| 3528 |
cin = q(0) if k == 0 else R(f"exp_s1.fa{k - 1}.carry_or")
|
| 3529 |
return _fa_member_inputs(m.group(2), f"{prefix}.exp_s1.fa{k}",
|
| 3530 |
+
na("a", k), R(f"exp_nb.bit{k}"), cin, reg)
|
| 3531 |
+
m = re.match(r"^exp_r\.fa(\d+)\.(.+)$", suffix) # + bias
|
|
|
|
| 3532 |
if m:
|
| 3533 |
k = int(m.group(1))
|
| 3534 |
a_sig = R(f"exp_s1.fa{k}.ha2.sum.layer2")
|
| 3535 |
b_sig = one if (bias >> k) & 1 else zero
|
| 3536 |
cin = zero if k == 0 else R(f"exp_r.fa{k - 1}.carry_or")
|
| 3537 |
+
return _fa_member_inputs(m.group(2), f"{prefix}.exp_r.fa{k}", a_sig, b_sig, cin, reg)
|
| 3538 |
+
m = re.match(r"^exprc\.bit(\d+)$", suffix) # er clamped >= 0
|
| 3539 |
+
if m:
|
| 3540 |
+
k = int(m.group(1))
|
| 3541 |
+
return [R(f"exp_r.fa{k}.ha2.sum.layer2"), R("er.not_underflow")]
|
| 3542 |
+
m = re.match(r"^ernot\.bit(\d+)$", suffix) # ~er
|
| 3543 |
+
if m:
|
| 3544 |
+
return [R(f"exp_r.fa{int(m.group(1))}.ha2.sum.layer2")]
|
| 3545 |
+
m = re.match(r"^subv\.fa(\d+)\.(.+)$", suffix) # 1 - er
|
| 3546 |
+
if m:
|
| 3547 |
+
k = int(m.group(1))
|
| 3548 |
+
a_sig = one if (1 >> k) & 1 else zero
|
| 3549 |
+
cin = one if k == 0 else R(f"subv.fa{k - 1}.carry_or")
|
| 3550 |
+
return _fa_member_inputs(m.group(2), f"{prefix}.subv.fa{k}", a_sig, R(f"ernot.bit{k}"), cin, reg)
|
| 3551 |
+
m = re.match(r"^rsh\.bit(\d+)$", suffix) # rsh = (1-er) AND underflow
|
| 3552 |
+
if m:
|
| 3553 |
+
k = int(m.group(1))
|
| 3554 |
+
return [R(f"subv.fa{k}.ha2.sum.layer2"), R("er.underflow")]
|
| 3555 |
+
m = re.match(r"^rbar\.s(\d+)\.(.+)$", suffix) # right-barrel on MF by rsh
|
| 3556 |
+
if m:
|
| 3557 |
+
j = int(m.group(1))
|
| 3558 |
+
rest = m.group(2)
|
| 3559 |
+
sel = R(f"rsh.bit{j}")
|
| 3560 |
+
|
| 3561 |
+
def rin(k: int) -> int:
|
| 3562 |
+
if k < 0 or k > F + 1:
|
| 3563 |
+
return zero
|
| 3564 |
+
return MF(k) if j == 0 else R(f"rbar.s{j - 1}.bit{k}.or")
|
| 3565 |
+
|
| 3566 |
+
if rest == "drop":
|
| 3567 |
+
return [rin(k) for k in range(1 << j)]
|
| 3568 |
+
if rest == "st_and":
|
| 3569 |
+
return [sel, R(f"rbar.s{j}.drop")]
|
| 3570 |
+
if rest == "sticky":
|
| 3571 |
+
prev = zero if j == 0 else R(f"rbar.s{j - 1}.sticky")
|
| 3572 |
+
return [prev, R(f"rbar.s{j}.st_and")]
|
| 3573 |
+
mm = re.match(r"^bit(\d+)\.(not_sel|and_a|and_b|or)$", rest)
|
| 3574 |
+
if mm:
|
| 3575 |
+
k = int(mm.group(1))
|
| 3576 |
+
kind = mm.group(2)
|
| 3577 |
+
if kind == "not_sel":
|
| 3578 |
+
return [sel]
|
| 3579 |
+
if kind == "and_a":
|
| 3580 |
+
return [rin(k), R(f"rbar.s{j}.bit{k}.not_sel")]
|
| 3581 |
+
if kind == "and_b":
|
| 3582 |
+
return [rin(k + (1 << j)), sel]
|
| 3583 |
+
return [R(f"rbar.s{j}.bit{k}.and_a"), R(f"rbar.s{j}.bit{k}.and_b")]
|
| 3584 |
+
m = re.match(r"^sig\.bit(\d+)$", suffix) # mantissa frac bit (masked)
|
| 3585 |
+
if m:
|
| 3586 |
+
return [shifted(int(m.group(1)) + 1), R("not_deep")]
|
| 3587 |
|
| 3588 |
m = re.match(r"^mant_div\.stage(\d+)\.(.+)$", suffix)
|
| 3589 |
if m:
|
|
|
|
| 3674 |
k = int(m.group(1))
|
| 3675 |
rest = m.group(2)
|
| 3676 |
cin = R("round.up") if k == 0 else R(f"rnd.bit{k - 1}.carry")
|
| 3677 |
+
f_bit = R(f"sig.bit{k}")
|
| 3678 |
if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
|
| 3679 |
return [f_bit, cin]
|
| 3680 |
if rest == "xor.layer2":
|
|
|
|
| 3687 |
k = int(m.group(1))
|
| 3688 |
rest = m.group(2)
|
| 3689 |
cin = R(f"rnd.bit{F - 1}.carry") if k == 0 else R(f"exp_round.bit{k - 1}.carry")
|
| 3690 |
+
e_bit = R(f"exprc.bit{k}")
|
| 3691 |
if rest == "xor.layer1.or" or rest == "xor.layer1.nand":
|
| 3692 |
return [e_bit, cin]
|
| 3693 |
if rest == "xor.layer2":
|
src/eval.py
CHANGED
|
@@ -754,7 +754,8 @@ def float_mul_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
|
| 754 |
def float_div_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
| 755 |
"""Expected quotient word under the documented contract: exact IEEE
|
| 756 |
specials (NaN, infinities, x/0 -> inf, 0/0 and inf/inf -> NaN, signed
|
| 757 |
-
zeros),
|
|
|
|
| 758 |
E, F = exp_bits, frac_bits
|
| 759 |
emax = (1 << E) - 1
|
| 760 |
fmask = (1 << F) - 1
|
|
@@ -767,35 +768,52 @@ def float_div_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
|
| 767 |
b_nan = eb == emax and fb != 0
|
| 768 |
a_inf = ea == emax and fa == 0
|
| 769 |
b_inf = eb == emax and fb == 0
|
| 770 |
-
a_zero = ea == 0
|
| 771 |
-
b_zero = eb == 0
|
| 772 |
-
inf_w = (s << (E + F)) | (emax << F)
|
| 773 |
-
zero_w = s << (E + F)
|
| 774 |
if a_nan or b_nan or (a_zero and b_zero) or (a_inf and b_inf):
|
| 775 |
return qnan
|
| 776 |
if a_inf or b_zero:
|
| 777 |
-
return
|
| 778 |
if a_zero or b_inf:
|
| 779 |
-
return
|
| 780 |
-
Ma
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 781 |
q0 = 1 if Ma >= Mb else 0
|
| 782 |
-
|
| 783 |
-
num = Ma << (F + 2 - q0)
|
| 784 |
Q = num // Mb
|
| 785 |
rem = num % Mb
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
frac
|
| 791 |
-
|
| 792 |
-
frac
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
return
|
| 798 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 799 |
|
| 800 |
|
| 801 |
def float_add_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
|
|
|
| 754 |
def float_div_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
| 755 |
"""Expected quotient word under the documented contract: exact IEEE
|
| 756 |
specials (NaN, infinities, x/0 -> inf, 0/0 and inf/inf -> NaN, signed
|
| 757 |
+
zeros), subnormal operands and gradual-underflow subnormal results,
|
| 758 |
+
round-to-nearest-even mantissa."""
|
| 759 |
E, F = exp_bits, frac_bits
|
| 760 |
emax = (1 << E) - 1
|
| 761 |
fmask = (1 << F) - 1
|
|
|
|
| 768 |
b_nan = eb == emax and fb != 0
|
| 769 |
a_inf = ea == emax and fa == 0
|
| 770 |
b_inf = eb == emax and fb == 0
|
| 771 |
+
a_zero = ea == 0 and fa == 0
|
| 772 |
+
b_zero = eb == 0 and fb == 0
|
|
|
|
|
|
|
| 773 |
if a_nan or b_nan or (a_zero and b_zero) or (a_inf and b_inf):
|
| 774 |
return qnan
|
| 775 |
if a_inf or b_zero:
|
| 776 |
+
return (s << (E + F)) | (emax << F)
|
| 777 |
if a_zero or b_inf:
|
| 778 |
+
return s << (E + F)
|
| 779 |
+
Ma = ((1 << F) if ea else 0) | fa
|
| 780 |
+
Mb = ((1 << F) if eb else 0) | fb
|
| 781 |
+
eea = ea if ea else 1
|
| 782 |
+
eeb = eb if eb else 1
|
| 783 |
+
ta = Ma.bit_length() - 1 # pre-normalize both mantissas
|
| 784 |
+
tb = Mb.bit_length() - 1
|
| 785 |
+
na = eea - (F - ta)
|
| 786 |
+
nb = eeb - (F - tb)
|
| 787 |
+
Ma <<= (F - ta)
|
| 788 |
+
Mb <<= (F - tb)
|
| 789 |
q0 = 1 if Ma >= Mb else 0
|
| 790 |
+
er = na - nb + bias - 1 + q0
|
| 791 |
+
num = Ma << (F + 2 - q0)
|
| 792 |
Q = num // Mb
|
| 793 |
rem = num % Mb
|
| 794 |
+
if er >= 1:
|
| 795 |
+
frac = (Q >> 1) & fmask
|
| 796 |
+
guard = Q & 1
|
| 797 |
+
sticky = 1 if rem else 0
|
| 798 |
+
if guard and ((frac & 1) or sticky):
|
| 799 |
+
frac += 1
|
| 800 |
+
if frac > fmask:
|
| 801 |
+
frac = 0
|
| 802 |
+
er += 1
|
| 803 |
+
if er >= emax:
|
| 804 |
+
return (s << (E + F)) | (emax << F)
|
| 805 |
+
return (s << (E + F)) | (er << F) | frac
|
| 806 |
+
rsh = (1 - er) + 1 # gradual underflow
|
| 807 |
+
sig = Q >> rsh
|
| 808 |
+
guard = (Q >> (rsh - 1)) & 1
|
| 809 |
+
sticky = 1 if ((Q & ((1 << (rsh - 1)) - 1)) or rem) else 0
|
| 810 |
+
if guard and ((sig & 1) or sticky):
|
| 811 |
+
sig += 1
|
| 812 |
+
if sig == 0:
|
| 813 |
+
return s << (E + F)
|
| 814 |
+
if sig >= (1 << F):
|
| 815 |
+
return (s << (E + F)) | (1 << F)
|
| 816 |
+
return (s << (E + F)) | sig
|
| 817 |
|
| 818 |
|
| 819 |
def float_add_oracle(aw: int, bw: int, exp_bits: int, frac_bits: int) -> int:
|
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:5f446db437a0de918305a96edfaa5e43871ccf04d4ff01af6dc4a0b0f5d9b299
|
| 3 |
+
size 27677671
|
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:d35d7c3801b45c4a34af02097f8e10389cb6eadb88df2962de913db0b455e2f5
|
| 3 |
+
size 26064500
|
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:ffcddf4c5081404b7d3010e705c40b13e4058973ea97b57f734e36f522a656ed
|
| 3 |
+
size 26064500
|
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:7b945aabc345ec0313643493b2667b5aac4b034ab4aa878ddb89da8d39c1e198
|
| 3 |
+
size 36194449
|
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:58f883b503cb40a6e9cd3fb0629fcce99de438fa4b52720fcdba12a024dc2ce5
|
| 3 |
+
size 28382973
|
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:b9f7ad572ba0136d068bab7edfafe9e2aa383e1a6fe1e1e291fb972cff589c20
|
| 3 |
+
size 27764633
|
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:aa7c9630864d48014acc971035034943d377f959839a889b871263d8af3636eb
|
| 3 |
+
size 27848613
|
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:71ede38e63607b4cda4e366db1bef813a48eb473f13aa0b4c563a72c1b244d94
|
| 3 |
+
size 27967749
|
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:c358cad0b5e5fd8cf83720eeb42a399047409d374932a9dc6ec3ebda754933bf
|
| 3 |
+
size 34601074
|
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:7e72369c1d4839e176a28b1cac8d89082698254af54c81af82bc6391f50b1c68
|
| 3 |
+
size 26789662
|
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:065f85b710beb30882dc8dc76e0f5b00a50c0cbb7c98bbf786d236be56216678
|
| 3 |
+
size 26170374
|
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:ce74d1fb55c4e43902664788da52d612722fef4f434b5c7391a41a469c9106bc
|
| 3 |
+
size 26254306
|
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:74614887741b0aab81644a23aec52b4315cc4cd8661030467b834d9d554c862f
|
| 3 |
+
size 26374348
|
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:93aa28025be1610259c6605c0c0b645b26e4d9e4a3ff7482183e7b71c1825585
|
| 3 |
+
size 34572926
|
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:63c11df1459c3ae2f87437528f4af6a1e2b1a39cc4474fa6e800e83922beb8cf
|
| 3 |
+
size 26761486
|
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:1b315ef217223e48cd1967b723ac417da290c27fb86f450496f1fb77eb8270b8
|
| 3 |
+
size 26142278
|
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:c493262272216ee4207c76e37dc11a96320828918c352e60f8dedda4513fe9a2
|
| 3 |
+
size 26226042
|
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:1ebf7e275a87aa80033af987cede32e85aa35b4bb926d50df334a5e972149812
|
| 3 |
+
size 26345338
|