CharlesCNorton commited on
Commit
0e2b1c9
·
1 Parent(s): a278d74
Files changed (4) hide show
  1. README.md +90 -0
  2. config.json +9 -0
  3. create_safetensors.py +156 -0
  4. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - arithmetic
9
+ - alu
10
+ ---
11
+
12
+ # threshold-alu4bit
13
+
14
+ 4-bit Arithmetic Logic Unit as threshold circuit. Performs arithmetic and bitwise operations on two 4-bit operands.
15
+
16
+ ## Circuit
17
+
18
+ ```
19
+ A[3:0] ──┐
20
+ B[3:0] ──┼──► ALU ──┬──► R[3:0] (result)
21
+ op[1:0] ──┘ ├──► Cout (carry out)
22
+ └──► Zero (zero flag)
23
+ ```
24
+
25
+ ## Operations
26
+
27
+ | op | Operation | Description |
28
+ |----|-----------|-------------|
29
+ | 00 | ADD | R = A + B |
30
+ | 01 | SUB | R = A - B (2's complement) |
31
+ | 10 | AND | R = A & B |
32
+ | 11 | XOR | R = A ^ B |
33
+
34
+ ## Flags
35
+
36
+ - **Cout**: Carry out from addition, borrow (inverted) from subtraction
37
+ - **Zero**: Set when result is 0
38
+
39
+ ## Architecture
40
+
41
+ | Component | Count | Neurons |
42
+ |-----------|-------|---------|
43
+ | Full Adders | 4 | 28 |
44
+ | B XOR (for SUB) | 4 | 12 |
45
+ | Bitwise AND | 4 | 4 |
46
+ | Bitwise XOR | 4 | 12 |
47
+ | Output MUX4 | 4 | 20 |
48
+ | Zero detect | 1 | 1 |
49
+ | Cout MUX | 1 | 5 |
50
+
51
+ **Total: 82 neurons, 282 parameters, 5 layers**
52
+
53
+ ## How Subtraction Works
54
+
55
+ ```
56
+ A - B = A + (~B) + 1 (2's complement)
57
+
58
+ When op=01:
59
+ - B bits are XORed with 1 (inverted)
60
+ - Carry-in is set to 1
61
+ - Result is A - B
62
+ ```
63
+
64
+ ## Usage
65
+
66
+ ```python
67
+ from safetensors.torch import load_file
68
+
69
+ w = load_file('model.safetensors')
70
+
71
+ # Examples:
72
+ # op=0: 5 + 3 = 8, cout=0, zero=0
73
+ # op=1: 5 - 3 = 2, cout=1, zero=0
74
+ # op=2: 5 & 3 = 1, cout=0, zero=0
75
+ # op=3: 5 ^ 3 = 6, cout=0, zero=0
76
+ ```
77
+
78
+ ## Files
79
+
80
+ ```
81
+ threshold-alu4bit/
82
+ ├── model.safetensors
83
+ ├── create_safetensors.py
84
+ ├── config.json
85
+ └── README.md
86
+ ```
87
+
88
+ ## License
89
+
90
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-alu4bit",
3
+ "description": "4-bit ALU with ADD, SUB, AND, XOR operations",
4
+ "inputs": 10,
5
+ "outputs": 6,
6
+ "neurons": 82,
7
+ "layers": 5,
8
+ "parameters": 282
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # 4-bit ALU
7
+ # Inputs: a3,a2,a1,a0, b3,b2,b1,b0, op1,op0 (10 inputs)
8
+ # Outputs: r3,r2,r1,r0, cout, zero (6 outputs)
9
+ #
10
+ # Operations:
11
+ # 00: ADD (A + B)
12
+ # 01: SUB (A - B, using 2's complement)
13
+ # 10: AND (A & B)
14
+ # 11: XOR (A ^ B)
15
+
16
+ def add_xor(name):
17
+ weights[f'{name}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
18
+ weights[f'{name}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
19
+ weights[f'{name}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
20
+ weights[f'{name}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
21
+ weights[f'{name}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
22
+ weights[f'{name}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
23
+
24
+ def add_fa(name):
25
+ add_xor(f'{name}.xor1')
26
+ add_xor(f'{name}.sum')
27
+ weights[f'{name}.carry.weight'] = torch.tensor([[1.0, 1.0, 1.0]], dtype=torch.float32)
28
+ weights[f'{name}.carry.bias'] = torch.tensor([-2.0], dtype=torch.float32)
29
+
30
+ def add_and(name, n=2):
31
+ weights[f'{name}.weight'] = torch.tensor([[1.0] * n], dtype=torch.float32)
32
+ weights[f'{name}.bias'] = torch.tensor([-float(n)], dtype=torch.float32)
33
+
34
+ def add_or(name, n=2):
35
+ weights[f'{name}.weight'] = torch.tensor([[1.0] * n], dtype=torch.float32)
36
+ weights[f'{name}.bias'] = torch.tensor([-1.0], dtype=torch.float32)
37
+
38
+ def add_mux4(name):
39
+ for sel in range(4):
40
+ s1 = (sel >> 1) & 1
41
+ s0 = sel & 1
42
+ w_s1 = 1.0 if s1 else -1.0
43
+ w_s0 = 1.0 if s0 else -1.0
44
+ bias = -(1 + bin(sel).count('1'))
45
+ weights[f'{name}.sel{sel}.weight'] = torch.tensor([[1.0, w_s1, w_s0]], dtype=torch.float32)
46
+ weights[f'{name}.sel{sel}.bias'] = torch.tensor([bias], dtype=torch.float32)
47
+ weights[f'{name}.or.weight'] = torch.tensor([[1.0, 1.0, 1.0, 1.0]], dtype=torch.float32)
48
+ weights[f'{name}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
49
+
50
+ # Adder/Subtractor (4 FAs)
51
+ for i in range(4):
52
+ add_fa(f'addsub.fa{i}')
53
+
54
+ # B XOR for subtraction (complement B when subtracting)
55
+ for i in range(4):
56
+ add_xor(f'bxor{i}')
57
+
58
+ # Bitwise AND
59
+ for i in range(4):
60
+ add_and(f'band{i}')
61
+
62
+ # Bitwise XOR
63
+ for i in range(4):
64
+ add_xor(f'bxor_op{i}')
65
+
66
+ # Output MUX for each bit (select from 4 operations)
67
+ for i in range(4):
68
+ add_mux4(f'mux{i}')
69
+
70
+ # Zero flag: NOR of all result bits
71
+ weights['zero.weight'] = torch.tensor([[-1.0, -1.0, -1.0, -1.0]], dtype=torch.float32)
72
+ weights['zero.bias'] = torch.tensor([0.0], dtype=torch.float32)
73
+
74
+ # Cout MUX (only valid for ADD/SUB)
75
+ add_mux4('cout_mux')
76
+
77
+ save_file(weights, 'model.safetensors')
78
+
79
+ def eval_xor(a, b):
80
+ return int((a or b) and not (a and b))
81
+
82
+ def eval_fa(a, b, cin):
83
+ s = eval_xor(eval_xor(a, b), cin)
84
+ c = int(a + b + cin >= 2)
85
+ return s, c
86
+
87
+ def alu_4bit(a, b, op):
88
+ a_bits = [(a >> i) & 1 for i in range(4)]
89
+ b_bits = [(b >> i) & 1 for i in range(4)]
90
+ op1, op0 = (op >> 1) & 1, op & 1
91
+
92
+ sub_mode = (op == 1)
93
+ b_mod = [eval_xor(b_bits[i], sub_mode) for i in range(4)]
94
+ cin = sub_mode
95
+
96
+ add_result = []
97
+ c = cin
98
+ for i in range(4):
99
+ s, c = eval_fa(a_bits[i], b_mod[i], c)
100
+ add_result.append(s)
101
+ cout = c
102
+
103
+ and_result = [a_bits[i] and b_bits[i] for i in range(4)]
104
+ xor_result = [eval_xor(a_bits[i], b_bits[i]) for i in range(4)]
105
+
106
+ if op == 0:
107
+ r = add_result
108
+ cout_final = cout
109
+ elif op == 1:
110
+ r = add_result
111
+ cout_final = cout
112
+ elif op == 2:
113
+ r = and_result
114
+ cout_final = 0
115
+ else:
116
+ r = xor_result
117
+ cout_final = 0
118
+
119
+ result = sum(r[i] << i for i in range(4))
120
+ zero = 1 if result == 0 else 0
121
+
122
+ return result, cout_final, zero
123
+
124
+ print("Verifying 4-bit ALU...")
125
+ errors = 0
126
+ for a in range(16):
127
+ for b in range(16):
128
+ for op in range(4):
129
+ r, cout, zero = alu_4bit(a, b, op)
130
+ if op == 0:
131
+ expected = (a + b) & 0xF
132
+ exp_cout = 1 if (a + b) > 15 else 0
133
+ elif op == 1:
134
+ expected = (a - b) & 0xF
135
+ exp_cout = 1 if a >= b else 0
136
+ elif op == 2:
137
+ expected = a & b
138
+ exp_cout = 0
139
+ else:
140
+ expected = a ^ b
141
+ exp_cout = 0
142
+ exp_zero = 1 if expected == 0 else 0
143
+
144
+ if r != expected or zero != exp_zero:
145
+ errors += 1
146
+ if errors <= 5:
147
+ print(f"ERROR: op={op}, A={a}, B={b}: got {r}, expected {expected}")
148
+
149
+ if errors == 0:
150
+ print("All 1024 test cases passed!")
151
+ else:
152
+ print(f"FAILED: {errors} errors")
153
+
154
+ mag = sum(t.abs().sum().item() for t in weights.values())
155
+ print(f"Magnitude: {mag:.0f}")
156
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
model.safetensors ADDED
Binary file (13.5 kB). View file