CharlesCNorton
commited on
Commit
·
ef2f3c3
1
Parent(s):
fa97c7c
Add INC, DEC, NEG, ROL, ROR, stack ops, barrel shifter, priority encoder
Browse filesNew circuits:
- INC/DEC: half adder chain with carry/borrow (72 gates)
- NEG: NOT + INC (40 gates)
- ROL/ROR: rotate with carry wraparound (16 gates)
- PUSH/POP/RET: SP increment/decrement + address buffers (144 gates)
- Barrel shifter: 3-stage log shifter (96 gates)
- Priority encoder: find highest set bit (28 gates)
Tensors: 10,399 -> 11,581
Parameters: 8,288,256 -> 8,290,134
Fitness: 1.000000
- README.md +3 -3
- build.py +362 -1
- neural_computer.safetensors +2 -2
README.md
CHANGED
|
@@ -17,8 +17,8 @@ tags:
|
|
| 17 |
Every logic gate is a threshold neuron: `output = 1 if (Σ wᵢxᵢ + b) ≥ 0 else 0`
|
| 18 |
|
| 19 |
```
|
| 20 |
-
Tensors:
|
| 21 |
-
Parameters: 8,
|
| 22 |
```
|
| 23 |
|
| 24 |
---
|
|
@@ -477,7 +477,7 @@ The interface generalizes to **all** 65,536 8-bit additions once trained—no me
|
|
| 477 |
|
| 478 |
| File | Description |
|
| 479 |
|------|-------------|
|
| 480 |
-
| `neural_computer.safetensors` |
|
| 481 |
| `threshold_cpu.py` | CPU state, reference cycle, threshold runtime |
|
| 482 |
| `eval.py` | Unified evaluation suite (5,884 tests, GPU-batched) |
|
| 483 |
| `build.py` | Build tools for memory, ALU, and .inputs tensors |
|
|
|
|
| 17 |
Every logic gate is a threshold neuron: `output = 1 if (Σ wᵢxᵢ + b) ≥ 0 else 0`
|
| 18 |
|
| 19 |
```
|
| 20 |
+
Tensors: 11,581
|
| 21 |
+
Parameters: 8,290,134
|
| 22 |
```
|
| 23 |
|
| 24 |
---
|
|
|
|
| 477 |
|
| 478 |
| File | Description |
|
| 479 |
|------|-------------|
|
| 480 |
+
| `neural_computer.safetensors` | 11,581 tensors, 8,290,134 parameters |
|
| 481 |
| `threshold_cpu.py` | CPU state, reference cycle, threshold runtime |
|
| 482 |
| `eval.py` | Unified evaluation suite (5,884 tests, GPU-batched) |
|
| 483 |
| `build.py` | Build tools for memory, ALU, and .inputs tensors |
|
build.py
CHANGED
|
@@ -301,6 +301,170 @@ def add_div(tensors: Dict[str, torch.Tensor]) -> None:
|
|
| 301 |
add_gate(tensors, f"alu.alu8bit.div.stage{stage}.mux.bit{bit}.or", [1.0, 1.0], [-1.0])
|
| 302 |
|
| 303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 304 |
def add_comparators(tensors: Dict[str, torch.Tensor]) -> None:
|
| 305 |
"""Add 8-bit comparator circuits (GT, LT, GE, LE, EQ).
|
| 306 |
|
|
@@ -647,6 +811,79 @@ def infer_alu_inputs(gate: str, reg: SignalRegistry) -> List[int]:
|
|
| 647 |
if '.or' in gate:
|
| 648 |
return [reg.register(f"{prefix}.mux.bit{bit}.and_a"), reg.register(f"{prefix}.mux.bit{bit}.and_b")]
|
| 649 |
return [reg.get_id(f"$a[{i}]") for i in range(8)] + [reg.get_id(f"$b[{i}]") for i in range(8)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 650 |
if '.and' in gate or '.or' in gate or '.xor' in gate:
|
| 651 |
m = re.search(r'bit(\d+)', gate)
|
| 652 |
if m:
|
|
@@ -757,9 +994,64 @@ def infer_combinational_inputs(gate: str, reg: SignalRegistry) -> List[int]:
|
|
| 757 |
if '.or' in gate:
|
| 758 |
return [reg.register(f"combinational.regmux4to1.bit{bit}.and{i}") for i in range(4)]
|
| 759 |
return []
|
| 760 |
-
if 'barrelshifter' in gate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 761 |
for i in range(8):
|
| 762 |
reg.register(f"$x[{i}]")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 763 |
return [reg.get_id(f"$x[{i}]") for i in range(8)]
|
| 764 |
return []
|
| 765 |
|
|
@@ -814,6 +1106,35 @@ def infer_inputs_for_gate(gate: str, reg: SignalRegistry, tensors: Dict[str, tor
|
|
| 814 |
return infer_control_jump_inputs(gate, prefix, reg)
|
| 815 |
if any(b in gate for b in ['fetch', 'load', 'store', 'mem_addr']):
|
| 816 |
return infer_buffer_inputs(gate, reg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 817 |
return [reg.register("$ctrl")]
|
| 818 |
if gate.startswith('memory.'):
|
| 819 |
return infer_memory_inputs(gate, reg)
|
|
@@ -931,9 +1252,13 @@ def cmd_alu(args) -> None:
|
|
| 931 |
drop_prefixes(tensors, [
|
| 932 |
"alu.alu8bit.shl.", "alu.alu8bit.shr.",
|
| 933 |
"alu.alu8bit.mul.", "alu.alu8bit.div.",
|
|
|
|
|
|
|
| 934 |
"arithmetic.greaterthan8bit.", "arithmetic.lessthan8bit.",
|
| 935 |
"arithmetic.greaterorequal8bit.", "arithmetic.lessorequal8bit.",
|
| 936 |
"arithmetic.equality8bit.",
|
|
|
|
|
|
|
| 937 |
])
|
| 938 |
print(f" Now {len(tensors)} tensors")
|
| 939 |
print("\nGenerating SHL/SHR circuits...")
|
|
@@ -954,6 +1279,42 @@ def cmd_alu(args) -> None:
|
|
| 954 |
print(" Added DIV (8 stages x comparison + mux)")
|
| 955 |
except ValueError as e:
|
| 956 |
print(f" DIV already exists: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 957 |
print("\nGenerating comparator circuits...")
|
| 958 |
try:
|
| 959 |
add_comparators(tensors)
|
|
|
|
| 301 |
add_gate(tensors, f"alu.alu8bit.div.stage{stage}.mux.bit{bit}.or", [1.0, 1.0], [-1.0])
|
| 302 |
|
| 303 |
|
| 304 |
+
def add_inc_dec(tensors: Dict[str, torch.Tensor]) -> None:
|
| 305 |
+
"""Add INC and DEC circuits.
|
| 306 |
+
|
| 307 |
+
INC: A + 1 using half adders with carry chain
|
| 308 |
+
DEC: A - 1 using borrow chain (A + 255, two's complement of 1)
|
| 309 |
+
|
| 310 |
+
For INC, we add 1 to the LSB and propagate carry.
|
| 311 |
+
For DEC, we add 0xFF (two's complement of 1) or use borrow logic.
|
| 312 |
+
"""
|
| 313 |
+
# INC: half adder chain starting with carry_in = 1
|
| 314 |
+
# bit 7 (LSB): XOR with 1, carry = bit[7]
|
| 315 |
+
# bit 6: XOR with carry, new_carry = bit[6] AND old_carry
|
| 316 |
+
# ...
|
| 317 |
+
for bit in range(8):
|
| 318 |
+
# XOR for sum (two-layer)
|
| 319 |
+
add_gate(tensors, f"alu.alu8bit.inc.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 320 |
+
add_gate(tensors, f"alu.alu8bit.inc.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 321 |
+
add_gate(tensors, f"alu.alu8bit.inc.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 322 |
+
# AND for carry propagation
|
| 323 |
+
add_gate(tensors, f"alu.alu8bit.inc.bit{bit}.carry", [1.0, 1.0], [-2.0])
|
| 324 |
+
|
| 325 |
+
# DEC: similar but with borrow logic
|
| 326 |
+
# Equivalent to adding 0xFF with carry_in = 0
|
| 327 |
+
# Or: NOT each bit, propagate borrow
|
| 328 |
+
for bit in range(8):
|
| 329 |
+
# XOR for difference
|
| 330 |
+
add_gate(tensors, f"alu.alu8bit.dec.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 331 |
+
add_gate(tensors, f"alu.alu8bit.dec.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 332 |
+
add_gate(tensors, f"alu.alu8bit.dec.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 333 |
+
# Borrow: NOT(A) AND borrow_in, equivalent to (NOT A) when borrow_in=1
|
| 334 |
+
add_gate(tensors, f"alu.alu8bit.dec.bit{bit}.not_a", [-1.0], [0.0])
|
| 335 |
+
add_gate(tensors, f"alu.alu8bit.dec.bit{bit}.borrow", [1.0, 1.0], [-2.0])
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
def add_neg(tensors: Dict[str, torch.Tensor]) -> None:
|
| 339 |
+
"""Add NEG circuit (two's complement negation).
|
| 340 |
+
|
| 341 |
+
NEG(A) = NOT(A) + 1 = ~A + 1
|
| 342 |
+
|
| 343 |
+
Structure: NOT gates followed by INC-style adder.
|
| 344 |
+
"""
|
| 345 |
+
for bit in range(8):
|
| 346 |
+
# NOT gate for each bit
|
| 347 |
+
add_gate(tensors, f"alu.alu8bit.neg.not.bit{bit}", [-1.0], [0.0])
|
| 348 |
+
# Then add 1 using half adder chain
|
| 349 |
+
add_gate(tensors, f"alu.alu8bit.neg.inc.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 350 |
+
add_gate(tensors, f"alu.alu8bit.neg.inc.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 351 |
+
add_gate(tensors, f"alu.alu8bit.neg.inc.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 352 |
+
add_gate(tensors, f"alu.alu8bit.neg.inc.bit{bit}.carry", [1.0, 1.0], [-2.0])
|
| 353 |
+
|
| 354 |
+
|
| 355 |
+
def add_rol_ror(tensors: Dict[str, torch.Tensor]) -> None:
|
| 356 |
+
"""Add ROL and ROR circuits (rotate left/right).
|
| 357 |
+
|
| 358 |
+
ROL: out[i] = in[i+1] for i<7, out[7] = in[0] (MSB wraps to LSB)
|
| 359 |
+
ROR: out[0] = in[7], out[i] = in[i-1] for i>0 (LSB wraps to MSB)
|
| 360 |
+
|
| 361 |
+
Identity gates with circular wiring.
|
| 362 |
+
"""
|
| 363 |
+
# ROL: rotate left (toward MSB)
|
| 364 |
+
for bit in range(8):
|
| 365 |
+
src = (bit + 1) % 8 # Circular: bit 7 gets bit 0
|
| 366 |
+
add_gate(tensors, f"alu.alu8bit.rol.bit{bit}", [2.0], [-1.0])
|
| 367 |
+
|
| 368 |
+
# ROR: rotate right (toward LSB)
|
| 369 |
+
for bit in range(8):
|
| 370 |
+
src = (bit - 1) % 8 # Circular: bit 0 gets bit 7
|
| 371 |
+
add_gate(tensors, f"alu.alu8bit.ror.bit{bit}", [2.0], [-1.0])
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def add_stack_ops(tensors: Dict[str, torch.Tensor]) -> None:
|
| 375 |
+
"""Add RET, PUSH, POP circuit components.
|
| 376 |
+
|
| 377 |
+
These are higher-level operations that use memory read/write.
|
| 378 |
+
We create the control logic gates.
|
| 379 |
+
|
| 380 |
+
RET: Pop return address from stack, jump to it
|
| 381 |
+
PUSH: Decrement SP, write value to [SP]
|
| 382 |
+
POP: Read value from [SP], increment SP
|
| 383 |
+
"""
|
| 384 |
+
# SP decrement for PUSH (16-bit)
|
| 385 |
+
for bit in range(16):
|
| 386 |
+
add_gate(tensors, f"control.push.sp_dec.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 387 |
+
add_gate(tensors, f"control.push.sp_dec.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 388 |
+
add_gate(tensors, f"control.push.sp_dec.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 389 |
+
add_gate(tensors, f"control.push.sp_dec.bit{bit}.borrow", [1.0, 1.0], [-2.0])
|
| 390 |
+
|
| 391 |
+
# SP increment for POP (16-bit)
|
| 392 |
+
for bit in range(16):
|
| 393 |
+
add_gate(tensors, f"control.pop.sp_inc.bit{bit}.xor.layer1.or", [1.0, 1.0], [-1.0])
|
| 394 |
+
add_gate(tensors, f"control.pop.sp_inc.bit{bit}.xor.layer1.nand", [-1.0, -1.0], [1.0])
|
| 395 |
+
add_gate(tensors, f"control.pop.sp_inc.bit{bit}.xor.layer2", [1.0, 1.0], [-2.0])
|
| 396 |
+
add_gate(tensors, f"control.pop.sp_inc.bit{bit}.carry", [1.0, 1.0], [-2.0])
|
| 397 |
+
|
| 398 |
+
# RET uses POP twice (for 16-bit address) then jumps
|
| 399 |
+
# Buffer gates for return address
|
| 400 |
+
for bit in range(16):
|
| 401 |
+
add_gate(tensors, f"control.ret.addr.bit{bit}", [2.0], [-1.0])
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def add_barrel_shifter(tensors: Dict[str, torch.Tensor]) -> None:
|
| 405 |
+
"""Add barrel shifter circuit.
|
| 406 |
+
|
| 407 |
+
Shifts input by 0-7 positions based on 3-bit shift amount.
|
| 408 |
+
Uses layers of 2:1 muxes controlled by shift amount bits.
|
| 409 |
+
|
| 410 |
+
Layer 0: shift by 0 or 1 (controlled by shift[2], LSB)
|
| 411 |
+
Layer 1: shift by 0 or 2 (controlled by shift[1])
|
| 412 |
+
Layer 2: shift by 0 or 4 (controlled by shift[0], MSB)
|
| 413 |
+
"""
|
| 414 |
+
# 3 layers of muxes, 8 bits each
|
| 415 |
+
for layer in range(3):
|
| 416 |
+
shift_amount = 1 << (2 - layer) # 4, 2, 1 for layers 0, 1, 2
|
| 417 |
+
for bit in range(8):
|
| 418 |
+
# 2:1 mux: if sel then shifted else original
|
| 419 |
+
# NOT for inverting select
|
| 420 |
+
add_gate(tensors, f"combinational.barrelshifter.layer{layer}.bit{bit}.not_sel", [-1.0], [0.0])
|
| 421 |
+
# AND gates
|
| 422 |
+
add_gate(tensors, f"combinational.barrelshifter.layer{layer}.bit{bit}.and_a", [1.0, 1.0], [-2.0])
|
| 423 |
+
add_gate(tensors, f"combinational.barrelshifter.layer{layer}.bit{bit}.and_b", [1.0, 1.0], [-2.0])
|
| 424 |
+
# OR gate
|
| 425 |
+
add_gate(tensors, f"combinational.barrelshifter.layer{layer}.bit{bit}.or", [1.0, 1.0], [-1.0])
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
def add_priority_encoder(tensors: Dict[str, torch.Tensor]) -> None:
|
| 429 |
+
"""Add priority encoder circuit.
|
| 430 |
+
|
| 431 |
+
Finds the position of the highest set bit (0-7).
|
| 432 |
+
Output is 3-bit index + valid flag.
|
| 433 |
+
|
| 434 |
+
Uses cascaded comparisons: check bit 7 first, then 6, etc.
|
| 435 |
+
"""
|
| 436 |
+
# Check each bit position (8 OR gates to detect any bit set at or above position)
|
| 437 |
+
for pos in range(8):
|
| 438 |
+
# OR of bits pos through 7
|
| 439 |
+
num_inputs = 8 - pos
|
| 440 |
+
weights = [1.0] * num_inputs
|
| 441 |
+
add_gate(tensors, f"combinational.priorityencoder.any_ge{pos}",
|
| 442 |
+
weights, [-1.0])
|
| 443 |
+
|
| 444 |
+
# Priority logic: pos N is highest if bit N is set AND no higher bit is set
|
| 445 |
+
for pos in range(8):
|
| 446 |
+
# bit[pos] AND NOT(any bit > pos)
|
| 447 |
+
add_gate(tensors, f"combinational.priorityencoder.is_highest{pos}.not_higher", [-1.0], [0.0])
|
| 448 |
+
add_gate(tensors, f"combinational.priorityencoder.is_highest{pos}.and", [1.0, 1.0], [-2.0])
|
| 449 |
+
|
| 450 |
+
# Encode position to 3-bit output
|
| 451 |
+
# out[0] (LSB): positions 1,3,5,7
|
| 452 |
+
# out[1]: positions 2,3,6,7
|
| 453 |
+
# out[2] (MSB): positions 4,5,6,7
|
| 454 |
+
for out_bit in range(3):
|
| 455 |
+
weights = []
|
| 456 |
+
for pos in range(8):
|
| 457 |
+
if (pos >> out_bit) & 1:
|
| 458 |
+
weights.append(1.0)
|
| 459 |
+
if weights:
|
| 460 |
+
add_gate(tensors, f"combinational.priorityencoder.out{out_bit}",
|
| 461 |
+
weights, [-1.0])
|
| 462 |
+
|
| 463 |
+
# Valid flag: any bit set
|
| 464 |
+
add_gate(tensors, f"combinational.priorityencoder.valid",
|
| 465 |
+
[1.0] * 8, [-1.0])
|
| 466 |
+
|
| 467 |
+
|
| 468 |
def add_comparators(tensors: Dict[str, torch.Tensor]) -> None:
|
| 469 |
"""Add 8-bit comparator circuits (GT, LT, GE, LE, EQ).
|
| 470 |
|
|
|
|
| 811 |
if '.or' in gate:
|
| 812 |
return [reg.register(f"{prefix}.mux.bit{bit}.and_a"), reg.register(f"{prefix}.mux.bit{bit}.and_b")]
|
| 813 |
return [reg.get_id(f"$a[{i}]") for i in range(8)] + [reg.get_id(f"$b[{i}]") for i in range(8)]
|
| 814 |
+
if '.inc.bit' in gate:
|
| 815 |
+
m = re.search(r'bit(\d+)', gate)
|
| 816 |
+
if m:
|
| 817 |
+
bit = int(m.group(1))
|
| 818 |
+
prefix = f"alu.alu8bit.inc.bit{bit}"
|
| 819 |
+
if 'layer1' in gate:
|
| 820 |
+
if bit == 7:
|
| 821 |
+
return [reg.get_id(f"$a[{bit}]"), reg.get_id("#1")]
|
| 822 |
+
else:
|
| 823 |
+
return [reg.get_id(f"$a[{bit}]"), reg.register(f"alu.alu8bit.inc.bit{bit+1}.carry")]
|
| 824 |
+
if 'layer2' in gate:
|
| 825 |
+
return [reg.register(f"{prefix}.xor.layer1.or"), reg.register(f"{prefix}.xor.layer1.nand")]
|
| 826 |
+
if '.carry' in gate:
|
| 827 |
+
if bit == 7:
|
| 828 |
+
return [reg.get_id(f"$a[{bit}]"), reg.get_id("#1")]
|
| 829 |
+
else:
|
| 830 |
+
return [reg.get_id(f"$a[{bit}]"), reg.register(f"alu.alu8bit.inc.bit{bit+1}.carry")]
|
| 831 |
+
return [reg.get_id(f"$a[{i}]") for i in range(8)]
|
| 832 |
+
if '.dec.bit' in gate:
|
| 833 |
+
m = re.search(r'bit(\d+)', gate)
|
| 834 |
+
if m:
|
| 835 |
+
bit = int(m.group(1))
|
| 836 |
+
prefix = f"alu.alu8bit.dec.bit{bit}"
|
| 837 |
+
if '.not_a' in gate:
|
| 838 |
+
return [reg.get_id(f"$a[{bit}]")]
|
| 839 |
+
if 'layer1' in gate:
|
| 840 |
+
if bit == 7:
|
| 841 |
+
return [reg.get_id(f"$a[{bit}]"), reg.get_id("#1")]
|
| 842 |
+
else:
|
| 843 |
+
return [reg.get_id(f"$a[{bit}]"), reg.register(f"alu.alu8bit.dec.bit{bit+1}.borrow")]
|
| 844 |
+
if 'layer2' in gate:
|
| 845 |
+
return [reg.register(f"{prefix}.xor.layer1.or"), reg.register(f"{prefix}.xor.layer1.nand")]
|
| 846 |
+
if '.borrow' in gate:
|
| 847 |
+
if bit == 7:
|
| 848 |
+
return [reg.register(f"{prefix}.not_a"), reg.get_id("#1")]
|
| 849 |
+
else:
|
| 850 |
+
return [reg.register(f"{prefix}.not_a"), reg.register(f"alu.alu8bit.dec.bit{bit+1}.borrow")]
|
| 851 |
+
return [reg.get_id(f"$a[{i}]") for i in range(8)]
|
| 852 |
+
if '.neg.' in gate:
|
| 853 |
+
m = re.search(r'bit(\d+)', gate)
|
| 854 |
+
if m:
|
| 855 |
+
bit = int(m.group(1))
|
| 856 |
+
if '.not.bit' in gate:
|
| 857 |
+
return [reg.get_id(f"$a[{bit}]")]
|
| 858 |
+
prefix = f"alu.alu8bit.neg.inc.bit{bit}"
|
| 859 |
+
not_bit = f"alu.alu8bit.neg.not.bit{bit}"
|
| 860 |
+
if 'layer1' in gate:
|
| 861 |
+
if bit == 7:
|
| 862 |
+
return [reg.register(not_bit), reg.get_id("#1")]
|
| 863 |
+
else:
|
| 864 |
+
return [reg.register(not_bit), reg.register(f"alu.alu8bit.neg.inc.bit{bit+1}.carry")]
|
| 865 |
+
if 'layer2' in gate:
|
| 866 |
+
return [reg.register(f"{prefix}.xor.layer1.or"), reg.register(f"{prefix}.xor.layer1.nand")]
|
| 867 |
+
if '.carry' in gate:
|
| 868 |
+
if bit == 7:
|
| 869 |
+
return [reg.register(not_bit), reg.get_id("#1")]
|
| 870 |
+
else:
|
| 871 |
+
return [reg.register(not_bit), reg.register(f"alu.alu8bit.neg.inc.bit{bit+1}.carry")]
|
| 872 |
+
return [reg.get_id(f"$a[{i}]") for i in range(8)]
|
| 873 |
+
if '.rol.bit' in gate:
|
| 874 |
+
m = re.search(r'bit(\d+)', gate)
|
| 875 |
+
if m:
|
| 876 |
+
bit = int(m.group(1))
|
| 877 |
+
src = (bit + 1) % 8
|
| 878 |
+
return [reg.get_id(f"$a[{src}]")]
|
| 879 |
+
return [reg.get_id(f"$a[{i}]") for i in range(8)]
|
| 880 |
+
if '.ror.bit' in gate:
|
| 881 |
+
m = re.search(r'bit(\d+)', gate)
|
| 882 |
+
if m:
|
| 883 |
+
bit = int(m.group(1))
|
| 884 |
+
src = (bit - 1) % 8
|
| 885 |
+
return [reg.get_id(f"$a[{src}]")]
|
| 886 |
+
return [reg.get_id(f"$a[{i}]") for i in range(8)]
|
| 887 |
if '.and' in gate or '.or' in gate or '.xor' in gate:
|
| 888 |
m = re.search(r'bit(\d+)', gate)
|
| 889 |
if m:
|
|
|
|
| 994 |
if '.or' in gate:
|
| 995 |
return [reg.register(f"combinational.regmux4to1.bit{bit}.and{i}") for i in range(4)]
|
| 996 |
return []
|
| 997 |
+
if 'barrelshifter' in gate:
|
| 998 |
+
for i in range(8):
|
| 999 |
+
reg.register(f"$x[{i}]")
|
| 1000 |
+
for i in range(3):
|
| 1001 |
+
reg.register(f"$shift[{i}]")
|
| 1002 |
+
m = re.search(r'layer(\d+)\.bit(\d+)', gate)
|
| 1003 |
+
if m:
|
| 1004 |
+
layer, bit = int(m.group(1)), int(m.group(2))
|
| 1005 |
+
shift_amount = 1 << (2 - layer)
|
| 1006 |
+
prefix = f"combinational.barrelshifter.layer{layer}.bit{bit}"
|
| 1007 |
+
if '.not_sel' in gate:
|
| 1008 |
+
return [reg.get_id(f"$shift[{2 - layer}]")]
|
| 1009 |
+
if '.and_a' in gate:
|
| 1010 |
+
if layer == 0:
|
| 1011 |
+
return [reg.get_id(f"$x[{bit}]"), reg.register(f"{prefix}.not_sel")]
|
| 1012 |
+
else:
|
| 1013 |
+
prev_prefix = f"combinational.barrelshifter.layer{layer-1}.bit{bit}"
|
| 1014 |
+
return [reg.register(f"{prev_prefix}.or"), reg.register(f"{prefix}.not_sel")]
|
| 1015 |
+
if '.and_b' in gate:
|
| 1016 |
+
src = (bit + shift_amount) % 8
|
| 1017 |
+
if layer == 0:
|
| 1018 |
+
return [reg.get_id(f"$x[{src}]"), reg.get_id(f"$shift[{2 - layer}]")]
|
| 1019 |
+
else:
|
| 1020 |
+
prev_prefix = f"combinational.barrelshifter.layer{layer-1}.bit{src}"
|
| 1021 |
+
return [reg.register(f"{prev_prefix}.or"), reg.get_id(f"$shift[{2 - layer}]")]
|
| 1022 |
+
if '.or' in gate:
|
| 1023 |
+
return [reg.register(f"{prefix}.and_a"), reg.register(f"{prefix}.and_b")]
|
| 1024 |
+
return [reg.get_id(f"$x[{i}]") for i in range(8)]
|
| 1025 |
+
if 'priorityencoder' in gate:
|
| 1026 |
for i in range(8):
|
| 1027 |
reg.register(f"$x[{i}]")
|
| 1028 |
+
if '.any_ge' in gate:
|
| 1029 |
+
m = re.search(r'any_ge(\d+)', gate)
|
| 1030 |
+
if m:
|
| 1031 |
+
pos = int(m.group(1))
|
| 1032 |
+
return [reg.get_id(f"$x[{i}]") for i in range(pos, 8)]
|
| 1033 |
+
if '.is_highest' in gate:
|
| 1034 |
+
m = re.search(r'is_highest(\d+)', gate)
|
| 1035 |
+
if m:
|
| 1036 |
+
pos = int(m.group(1))
|
| 1037 |
+
if '.not_higher' in gate:
|
| 1038 |
+
if pos == 0:
|
| 1039 |
+
return [reg.get_id("#0")]
|
| 1040 |
+
else:
|
| 1041 |
+
return [reg.register(f"combinational.priorityencoder.any_ge{pos-1}")]
|
| 1042 |
+
if '.and' in gate:
|
| 1043 |
+
return [reg.get_id(f"$x[{pos}]"), reg.register(f"combinational.priorityencoder.is_highest{pos}.not_higher")]
|
| 1044 |
+
if '.out' in gate:
|
| 1045 |
+
m = re.search(r'out(\d+)', gate)
|
| 1046 |
+
if m:
|
| 1047 |
+
out_bit = int(m.group(1))
|
| 1048 |
+
inputs = []
|
| 1049 |
+
for pos in range(8):
|
| 1050 |
+
if (pos >> out_bit) & 1:
|
| 1051 |
+
inputs.append(reg.register(f"combinational.priorityencoder.is_highest{pos}.and"))
|
| 1052 |
+
return inputs
|
| 1053 |
+
if '.valid' in gate:
|
| 1054 |
+
return [reg.get_id(f"$x[{i}]") for i in range(8)]
|
| 1055 |
return [reg.get_id(f"$x[{i}]") for i in range(8)]
|
| 1056 |
return []
|
| 1057 |
|
|
|
|
| 1106 |
return infer_control_jump_inputs(gate, prefix, reg)
|
| 1107 |
if any(b in gate for b in ['fetch', 'load', 'store', 'mem_addr']):
|
| 1108 |
return infer_buffer_inputs(gate, reg)
|
| 1109 |
+
if 'push.sp_dec' in gate or 'pop.sp_inc' in gate:
|
| 1110 |
+
for i in range(16):
|
| 1111 |
+
reg.register(f"$sp[{i}]")
|
| 1112 |
+
m = re.search(r'bit(\d+)', gate)
|
| 1113 |
+
if m:
|
| 1114 |
+
bit = int(m.group(1))
|
| 1115 |
+
op = 'push.sp_dec' if 'push' in gate else 'pop.sp_inc'
|
| 1116 |
+
prefix = f"control.{op}.bit{bit}"
|
| 1117 |
+
if 'layer1' in gate:
|
| 1118 |
+
if bit == 15:
|
| 1119 |
+
return [reg.get_id(f"$sp[{bit}]"), reg.get_id("#1")]
|
| 1120 |
+
else:
|
| 1121 |
+
carry_name = 'borrow' if 'push' in gate else 'carry'
|
| 1122 |
+
return [reg.get_id(f"$sp[{bit}]"), reg.register(f"control.{op}.bit{bit+1}.{carry_name}")]
|
| 1123 |
+
if 'layer2' in gate:
|
| 1124 |
+
return [reg.register(f"{prefix}.xor.layer1.or"), reg.register(f"{prefix}.xor.layer1.nand")]
|
| 1125 |
+
if '.borrow' in gate or '.carry' in gate:
|
| 1126 |
+
if bit == 15:
|
| 1127 |
+
return [reg.get_id(f"$sp[{bit}]"), reg.get_id("#1")]
|
| 1128 |
+
else:
|
| 1129 |
+
carry_name = 'borrow' if 'push' in gate else 'carry'
|
| 1130 |
+
return [reg.get_id(f"$sp[{bit}]"), reg.register(f"control.{op}.bit{bit+1}.{carry_name}")]
|
| 1131 |
+
return [reg.get_id(f"$sp[{i}]") for i in range(16)]
|
| 1132 |
+
if 'ret.addr' in gate:
|
| 1133 |
+
m = re.search(r'bit(\d+)', gate)
|
| 1134 |
+
if m:
|
| 1135 |
+
bit = int(m.group(1))
|
| 1136 |
+
return [reg.register(f"$ret_addr[{bit}]")]
|
| 1137 |
+
return [reg.register(f"$ret_addr[{i}]") for i in range(16)]
|
| 1138 |
return [reg.register("$ctrl")]
|
| 1139 |
if gate.startswith('memory.'):
|
| 1140 |
return infer_memory_inputs(gate, reg)
|
|
|
|
| 1252 |
drop_prefixes(tensors, [
|
| 1253 |
"alu.alu8bit.shl.", "alu.alu8bit.shr.",
|
| 1254 |
"alu.alu8bit.mul.", "alu.alu8bit.div.",
|
| 1255 |
+
"alu.alu8bit.inc.", "alu.alu8bit.dec.",
|
| 1256 |
+
"alu.alu8bit.neg.", "alu.alu8bit.rol.", "alu.alu8bit.ror.",
|
| 1257 |
"arithmetic.greaterthan8bit.", "arithmetic.lessthan8bit.",
|
| 1258 |
"arithmetic.greaterorequal8bit.", "arithmetic.lessorequal8bit.",
|
| 1259 |
"arithmetic.equality8bit.",
|
| 1260 |
+
"control.push.", "control.pop.", "control.ret.",
|
| 1261 |
+
"combinational.barrelshifter.", "combinational.priorityencoder.",
|
| 1262 |
])
|
| 1263 |
print(f" Now {len(tensors)} tensors")
|
| 1264 |
print("\nGenerating SHL/SHR circuits...")
|
|
|
|
| 1279 |
print(" Added DIV (8 stages x comparison + mux)")
|
| 1280 |
except ValueError as e:
|
| 1281 |
print(f" DIV already exists: {e}")
|
| 1282 |
+
print("\nGenerating INC/DEC circuits...")
|
| 1283 |
+
try:
|
| 1284 |
+
add_inc_dec(tensors)
|
| 1285 |
+
print(" Added INC (32 gates), DEC (40 gates)")
|
| 1286 |
+
except ValueError as e:
|
| 1287 |
+
print(f" INC/DEC already exist: {e}")
|
| 1288 |
+
print("\nGenerating NEG circuit...")
|
| 1289 |
+
try:
|
| 1290 |
+
add_neg(tensors)
|
| 1291 |
+
print(" Added NEG (40 gates)")
|
| 1292 |
+
except ValueError as e:
|
| 1293 |
+
print(f" NEG already exists: {e}")
|
| 1294 |
+
print("\nGenerating ROL/ROR circuits...")
|
| 1295 |
+
try:
|
| 1296 |
+
add_rol_ror(tensors)
|
| 1297 |
+
print(" Added ROL (8 gates), ROR (8 gates)")
|
| 1298 |
+
except ValueError as e:
|
| 1299 |
+
print(f" ROL/ROR already exist: {e}")
|
| 1300 |
+
print("\nGenerating stack operation circuits...")
|
| 1301 |
+
try:
|
| 1302 |
+
add_stack_ops(tensors)
|
| 1303 |
+
print(" Added PUSH/POP/RET (144 gates)")
|
| 1304 |
+
except ValueError as e:
|
| 1305 |
+
print(f" Stack ops already exist: {e}")
|
| 1306 |
+
print("\nGenerating barrel shifter...")
|
| 1307 |
+
try:
|
| 1308 |
+
add_barrel_shifter(tensors)
|
| 1309 |
+
print(" Added barrel shifter (96 gates)")
|
| 1310 |
+
except ValueError as e:
|
| 1311 |
+
print(f" Barrel shifter already exists: {e}")
|
| 1312 |
+
print("\nGenerating priority encoder...")
|
| 1313 |
+
try:
|
| 1314 |
+
add_priority_encoder(tensors)
|
| 1315 |
+
print(" Added priority encoder (28 gates)")
|
| 1316 |
+
except ValueError as e:
|
| 1317 |
+
print(f" Priority encoder already exists: {e}")
|
| 1318 |
print("\nGenerating comparator circuits...")
|
| 1319 |
try:
|
| 1320 |
add_comparators(tensors)
|
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:d8f97c127018647da3a788ee40cbe498ee583d2031bbec04e9347894b1fb5c19
|
| 3 |
+
size 34491396
|