CharlesCNorton commited on
Commit
8337959
·
1 Parent(s): 2e204e8

4x4 binary multiplier

Browse files
Files changed (4) hide show
  1. README.md +86 -0
  2. config.json +9 -0
  3. create_safetensors.py +137 -0
  4. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - arithmetic
9
+ - multiplier
10
+ ---
11
+
12
+ # threshold-multiplier4x4
13
+
14
+ 4x4 binary multiplier as threshold circuit. Multiplies two 4-bit unsigned integers to produce an 8-bit product.
15
+
16
+ ## Circuit
17
+
18
+ ```
19
+ A[3:0] ──┐
20
+ ├──► 4x4 MUL ──► P[7:0]
21
+ B[3:0] ──┘
22
+
23
+ P = A × B
24
+ Range: 0-15 × 0-15 = 0-225
25
+ ```
26
+
27
+ ## Architecture
28
+
29
+ ```
30
+ Partial Products (16 AND gates):
31
+ b3 b2 b1 b0
32
+ × a3 a2 a1 a0
33
+ ─────────────────────────
34
+ a0b3 a0b2 a0b1 a0b0
35
+ a1b3 a1b2 a1b1 a1b0
36
+ a2b3 a2b2 a2b1 a2b0
37
+ + a3b3 a3b2 a3b1 a3b0
38
+ ─────────────────────────────────────
39
+ p7 p6 p5 p4 p3 p2 p1 p0
40
+ ```
41
+
42
+ | Component | Count | Neurons |
43
+ |-----------|-------|---------|
44
+ | AND (partial products) | 16 | 16 |
45
+ | Half Adders | 4 | 16 |
46
+ | Full Adders | 8 | 56 |
47
+
48
+ **Total: 88 neurons, 368 parameters, 6 layers**
49
+
50
+ ## Adder Tree Structure
51
+
52
+ ```
53
+ Column 1: HA(pp10, pp01) → p1, c1
54
+ Column 2: FA(pp20, pp11, pp02) → s, c
55
+ HA(s, c1) → p2, c
56
+ Column 3: FA(pp30, pp21, pp12) → s, c
57
+ FA(s, pp03, c) → s', c'
58
+ HA(s', c) → p3, c
59
+ Column 4-6: Similar carry-propagate structure
60
+ Column 7: Final carry → p7
61
+ ```
62
+
63
+ ## Usage
64
+
65
+ ```python
66
+ from safetensors.torch import load_file
67
+
68
+ w = load_file('model.safetensors')
69
+
70
+ # Verify: 15 × 15 = 225
71
+ # All 256 input combinations tested
72
+ ```
73
+
74
+ ## Files
75
+
76
+ ```
77
+ threshold-multiplier4x4/
78
+ ├── model.safetensors
79
+ ├── create_safetensors.py
80
+ ├── config.json
81
+ └── README.md
82
+ ```
83
+
84
+ ## License
85
+
86
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-multiplier4x4",
3
+ "description": "4x4 binary multiplier as threshold circuit",
4
+ "inputs": 8,
5
+ "outputs": 8,
6
+ "neurons": 88,
7
+ "layers": 6,
8
+ "parameters": 368
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # 4x4 binary multiplier
7
+ # Inputs: a3,a2,a1,a0, b3,b2,b1,b0 (8 inputs)
8
+ # Outputs: p7,p6,p5,p4,p3,p2,p1,p0 (8 outputs)
9
+
10
+ # Partial products: pp[i][j] = a[i] AND b[j]
11
+ # Column c gets all pp[i][j] where i+j = c
12
+
13
+ def add_and_gate(name, a_idx, b_idx, total_inputs):
14
+ w = [0.0] * total_inputs
15
+ w[a_idx] = 1.0
16
+ w[b_idx] = 1.0
17
+ weights[f'{name}.weight'] = torch.tensor([w], dtype=torch.float32)
18
+ weights[f'{name}.bias'] = torch.tensor([-2.0], dtype=torch.float32)
19
+
20
+ def add_xor_gate(name, total_inputs):
21
+ weights[f'{name}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
22
+ weights[f'{name}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
23
+ weights[f'{name}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
24
+ weights[f'{name}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
25
+ weights[f'{name}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
26
+ weights[f'{name}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
27
+
28
+ def add_ha(name):
29
+ add_xor_gate(f'{name}.sum', 2)
30
+ weights[f'{name}.carry.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
31
+ weights[f'{name}.carry.bias'] = torch.tensor([-2.0], dtype=torch.float32)
32
+
33
+ def add_fa(name):
34
+ add_xor_gate(f'{name}.xor1', 2)
35
+ add_xor_gate(f'{name}.sum', 2)
36
+ weights[f'{name}.maj.weight'] = torch.tensor([[1.0, 1.0, 1.0]], dtype=torch.float32)
37
+ weights[f'{name}.maj.bias'] = torch.tensor([-2.0], dtype=torch.float32)
38
+
39
+ # Input indices: a3=0, a2=1, a1=2, a0=3, b3=4, b2=5, b1=6, b0=7
40
+
41
+ # Layer 1: 16 AND gates for partial products
42
+ for i in range(4):
43
+ for j in range(4):
44
+ a_idx = 3 - i
45
+ b_idx = 7 - j
46
+ add_and_gate(f'pp{i}{j}', a_idx, b_idx, 8)
47
+
48
+ # Adder structure for summing partial products
49
+ add_ha('ha_c1')
50
+ add_fa('fa_c2_0')
51
+ add_ha('ha_c2_1')
52
+ add_fa('fa_c3_0')
53
+ add_fa('fa_c3_1')
54
+ add_ha('ha_c3_2')
55
+ add_fa('fa_c4_0')
56
+ add_fa('fa_c4_1')
57
+ add_ha('ha_c4_2')
58
+ add_fa('fa_c5_0')
59
+ add_fa('fa_c5_1')
60
+ add_fa('fa_c6')
61
+
62
+ save_file(weights, 'model.safetensors')
63
+
64
+ def eval_and(a, b):
65
+ return int(a + b >= 2)
66
+
67
+ def eval_xor(a, b):
68
+ or_out = int(a + b >= 1)
69
+ nand_out = int(-a - b + 1 >= 0)
70
+ return int(or_out + nand_out >= 2)
71
+
72
+ def eval_ha(a, b):
73
+ s = eval_xor(a, b)
74
+ c = eval_and(a, b)
75
+ return s, c
76
+
77
+ def eval_fa(a, b, cin):
78
+ x1 = eval_xor(a, b)
79
+ s = eval_xor(x1, cin)
80
+ c = int(a + b + cin >= 2)
81
+ return s, c
82
+
83
+ def multiply_4x4(a3, a2, a1, a0, b3, b2, b1, b0):
84
+ pp = [[eval_and([a0,a1,a2,a3][i], [b0,b1,b2,b3][j]) for j in range(4)] for i in range(4)]
85
+
86
+ p0 = pp[0][0]
87
+
88
+ s1, c1 = eval_ha(pp[1][0], pp[0][1])
89
+ p1 = s1
90
+
91
+ s2_0, c2_0 = eval_fa(pp[2][0], pp[1][1], pp[0][2])
92
+ s2_1, c2_1 = eval_ha(s2_0, c1)
93
+ p2 = s2_1
94
+
95
+ s3_0, c3_0 = eval_fa(pp[3][0], pp[2][1], pp[1][2])
96
+ s3_1, c3_1 = eval_fa(s3_0, pp[0][3], c2_0)
97
+ s3_2, c3_2 = eval_ha(s3_1, c2_1)
98
+ p3 = s3_2
99
+
100
+ s4_0, c4_0 = eval_fa(pp[3][1], pp[2][2], pp[1][3])
101
+ s4_1, c4_1 = eval_fa(s4_0, c3_0, c3_1)
102
+ s4_2, c4_2 = eval_ha(s4_1, c3_2)
103
+ p4 = s4_2
104
+
105
+ s5_0, c5_0 = eval_fa(pp[3][2], pp[2][3], c4_0)
106
+ s5_1, c5_1 = eval_fa(s5_0, c4_1, c4_2)
107
+ p5 = s5_1
108
+
109
+ s6, c6 = eval_fa(pp[3][3], c5_0, c5_1)
110
+ p6 = s6
111
+
112
+ p7 = c6
113
+
114
+ return p0, p1, p2, p3, p4, p5, p6, p7
115
+
116
+ print("Verifying 4x4 multiplier...")
117
+ errors = 0
118
+ for a in range(16):
119
+ for b in range(16):
120
+ a3, a2, a1, a0 = (a>>3)&1, (a>>2)&1, (a>>1)&1, a&1
121
+ b3, b2, b1, b0 = (b>>3)&1, (b>>2)&1, (b>>1)&1, b&1
122
+ p = multiply_4x4(a3, a2, a1, a0, b3, b2, b1, b0)
123
+ result = sum(p[i] << i for i in range(8))
124
+ expected = a * b
125
+ if result != expected:
126
+ errors += 1
127
+ if errors <= 5:
128
+ print(f"ERROR: {a} * {b} = {result}, expected {expected}")
129
+
130
+ if errors == 0:
131
+ print("All 256 test cases passed!")
132
+ else:
133
+ print(f"FAILED: {errors} errors")
134
+
135
+ mag = sum(t.abs().sum().item() for t in weights.values())
136
+ print(f"Magnitude: {mag:.0f}")
137
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
model.safetensors ADDED
Binary file (14.8 kB). View file