CharlesCNorton commited on
Commit
ef2f3c3
·
1 Parent(s): fa97c7c

Add INC, DEC, NEG, ROL, ROR, stack ops, barrel shifter, priority encoder

Browse files

New 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

Files changed (3) hide show
  1. README.md +3 -3
  2. build.py +362 -1
  3. 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: 10,399
21
- Parameters: 8,288,256
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` | 10,399 tensors, 8,288,256 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 |
 
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 or 'priorityencoder' 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:68c76f0ec6822e071d2532c4ca40a216d959d5344e617990371bbc856134c4a0
3
- size 34342684
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d8f97c127018647da3a788ee40cbe498ee583d2031bbec04e9347894b1fb5c19
3
+ size 34491396