phanerozoic commited on
Commit
be0ccd2
Β·
verified Β·
1 Parent(s): be2d8cf

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +147 -0
  2. config.json +9 -0
  3. model.py +63 -0
  4. model.safetensors +3 -0
README.md ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - arithmetic
9
+ ---
10
+
11
+ # threshold-ripplecarry4bit
12
+
13
+ Adds two 4-bit numbers with carry-in. Four cascaded full adders in the classic ripple-carry architecture.
14
+
15
+ ## Circuit
16
+
17
+ ```
18
+ a0 b0 cin a1 b1 a2 b2 a3 b3
19
+ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
20
+ β””β”€β”€β”Όβ”€β”€β”˜ β””β”€β”€β”Όβ”€β”€β”˜ β””β”€β”€β”Όβ”€β”€β”˜ β””β”€β”€β”Όβ”€β”€β”˜
21
+ β–Ό β–Ό β–Ό β–Ό
22
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”
23
+ β”‚ FA0 │───c0───│ FA1 │──c1──│ FA2 │──c2──│ FA3 │───cout
24
+ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜
25
+ β”‚ β”‚ β”‚ β”‚
26
+ β–Ό β–Ό β–Ό β–Ό
27
+ s0 s1 s2 s3
28
+
29
+
30
+ Input: (a3 a2 a1 a0) + (b3 b2 b1 b0) + cin
31
+ Output: (cout s3 s2 s1 s0)
32
+ ```
33
+
34
+ The carry ripples through each full adder sequentially, hence "ripple-carry."
35
+
36
+ ## Full Adder Structure (each FA)
37
+
38
+ ```
39
+ a b
40
+ β”‚ β”‚
41
+ β””β”€β”€β”€β”¬β”€β”€β”€β”˜
42
+ β–Ό
43
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
44
+ β”‚ HA1 β”‚ Half adder 1
45
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
46
+ β”‚ β”‚
47
+ s1 c1
48
+ β”‚ \
49
+ β”‚ cin \
50
+ β””β”€β”€β”¬β”€β”€β”˜ \
51
+ β–Ό \
52
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” \
53
+ β”‚ HA2 β”‚ β”‚
54
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
55
+ β”‚ β”‚ β”‚
56
+ sum c2 β”‚
57
+ β”‚ β”‚
58
+ β””β”€β”€β”¬β”€β”€β”€β”˜
59
+ β–Ό
60
+ β”Œβ”€β”€β”€β”€β”€β”€β”
61
+ β”‚ OR β”‚
62
+ β””β”€β”€β”€β”€β”€β”€β”˜
63
+ β”‚
64
+ β–Ό
65
+ cout
66
+ ```
67
+
68
+ ## Example
69
+
70
+ ```
71
+ 1111 (15)
72
+ + 0001 ( 1)
73
+ ──────
74
+ 10000 (16)
75
+ ```
76
+
77
+ 15 + 1 = 16, which overflows 4 bits. The result is s=[0,0,0,0] with cout=1.
78
+
79
+ ## Architecture
80
+
81
+ | Component | Per FA | Total (4 FAs) |
82
+ |-----------|--------|---------------|
83
+ | Neurons | 9 | 36 |
84
+ | Parameters | 27 | 108 |
85
+ | Layers | 4 | 16 |
86
+
87
+ ## Inputs/Outputs
88
+
89
+ | Name | Bits | Description |
90
+ |------|------|-------------|
91
+ | a | a3..a0 | First 4-bit number (LSB = a0) |
92
+ | b | b3..b0 | Second 4-bit number (LSB = b0) |
93
+ | cin | 1 | Carry in |
94
+ | s | s3..s0 | 4-bit sum (LSB = s0) |
95
+ | cout | 1 | Carry out |
96
+
97
+ ## Critical Path
98
+
99
+ The worst-case delay is when a carry must propagate through all 4 full adders:
100
+
101
+ ```
102
+ cin β†’ FA0.cout β†’ FA1.cout β†’ FA2.cout β†’ FA3.cout
103
+ ```
104
+
105
+ This is 4 Γ— 4 = 16 layers deep. Carry-lookahead would reduce this but requires more complex circuitry.
106
+
107
+ ## Usage
108
+
109
+ ```python
110
+ from safetensors.torch import load_file
111
+
112
+ w = load_file('model.safetensors')
113
+
114
+ def ripple_carry_4bit(a, b, cin):
115
+ """a, b: 4-bit lists [a0,a1,a2,a3] (LSB first)"""
116
+ # See model.py for full implementation
117
+ pass
118
+
119
+ # Example: 7 + 5 = 12
120
+ a = [1, 1, 1, 0] # 7 in LSB-first
121
+ b = [1, 0, 1, 0] # 5 in LSB-first
122
+ sums, cout = ripple_carry_4bit(a, b, 0)
123
+ # sums = [0, 0, 1, 1], cout = 0 β†’ 12
124
+ ```
125
+
126
+ ## Scaling
127
+
128
+ | Bits | Full Adders | Neurons | Parameters | Max Depth |
129
+ |------|-------------|---------|------------|-----------|
130
+ | 2 | 2 | 18 | 54 | 8 |
131
+ | 4 | 4 | 36 | 108 | 16 |
132
+ | 8 | 8 | 72 | 216 | 32 |
133
+ | n | n | 9n | 27n | 4n |
134
+
135
+ ## Files
136
+
137
+ ```
138
+ threshold-ripplecarry4bit/
139
+ β”œβ”€β”€ model.safetensors
140
+ β”œβ”€β”€ model.py
141
+ β”œβ”€β”€ config.json
142
+ └── README.md
143
+ ```
144
+
145
+ ## License
146
+
147
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-ripplecarry4bit",
3
+ "description": "4-bit ripple carry adder as threshold circuit",
4
+ "inputs": 9,
5
+ "outputs": 5,
6
+ "neurons": 36,
7
+ "layers": 16,
8
+ "parameters": 108
9
+ }
model.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import load_file
3
+
4
+ def load_model(path='model.safetensors'):
5
+ return load_file(path)
6
+
7
+ def full_adder(a, b, cin, w, prefix):
8
+ """Single full adder: a + b + cin = (sum, cout)"""
9
+ inp = torch.tensor([float(a), float(b)])
10
+
11
+ # HA1: a + b
12
+ or_out = (inp * w[f'{prefix}.ha1.sum.layer1.or.weight']).sum() + w[f'{prefix}.ha1.sum.layer1.or.bias'] >= 0
13
+ nand_out = (inp * w[f'{prefix}.ha1.sum.layer1.nand.weight']).sum() + w[f'{prefix}.ha1.sum.layer1.nand.bias'] >= 0
14
+ l1 = torch.tensor([float(or_out), float(nand_out)])
15
+ s1 = float((l1 * w[f'{prefix}.ha1.sum.layer2.weight']).sum() + w[f'{prefix}.ha1.sum.layer2.bias'] >= 0)
16
+ c1 = float((inp * w[f'{prefix}.ha1.carry.weight']).sum() + w[f'{prefix}.ha1.carry.bias'] >= 0)
17
+
18
+ # HA2: s1 + cin
19
+ inp2 = torch.tensor([s1, float(cin)])
20
+ or_out2 = (inp2 * w[f'{prefix}.ha2.sum.layer1.or.weight']).sum() + w[f'{prefix}.ha2.sum.layer1.or.bias'] >= 0
21
+ nand_out2 = (inp2 * w[f'{prefix}.ha2.sum.layer1.nand.weight']).sum() + w[f'{prefix}.ha2.sum.layer1.nand.bias'] >= 0
22
+ l2 = torch.tensor([float(or_out2), float(nand_out2)])
23
+ s = int((l2 * w[f'{prefix}.ha2.sum.layer2.weight']).sum() + w[f'{prefix}.ha2.sum.layer2.bias'] >= 0)
24
+ c2 = float((inp2 * w[f'{prefix}.ha2.carry.weight']).sum() + w[f'{prefix}.ha2.carry.bias'] >= 0)
25
+
26
+ # Carry OR
27
+ cout = int((torch.tensor([c1, c2]) * w[f'{prefix}.carry_or.weight']).sum() + w[f'{prefix}.carry_or.bias'] >= 0)
28
+ return s, cout
29
+
30
+ def ripple_carry_4bit(a, b, cin, weights):
31
+ """4-bit ripple carry adder.
32
+ a, b: lists of 4 bits each (LSB first)
33
+ cin: carry in
34
+ Returns: (sums, cout) where sums is 4-bit list (LSB first)
35
+ """
36
+ carries = [cin]
37
+ sums = []
38
+ for i in range(4):
39
+ s, c = full_adder(a[i], b[i], carries[i], weights, f'fa{i}')
40
+ sums.append(s)
41
+ carries.append(c)
42
+ return sums, carries[4]
43
+
44
+ if __name__ == '__main__':
45
+ w = load_model()
46
+ print('4-bit Ripple Carry Adder')
47
+ print('Testing all combinations would be 2^9 = 512 cases.')
48
+ print('Sample tests:')
49
+ tests = [
50
+ ([0,0,0,0], [0,0,0,0], 0, 0),
51
+ ([1,0,0,0], [1,0,0,0], 0, 2),
52
+ ([1,1,1,1], [1,0,0,0], 0, 16),
53
+ ([1,1,1,1], [1,1,1,1], 0, 30),
54
+ ([0,1,0,1], [0,1,0,1], 0, 20),
55
+ ([1,1,0,0], [1,1,0,0], 0, 6),
56
+ ]
57
+ for a, b, cin, expected in tests:
58
+ sums, cout = ripple_carry_4bit(a, b, cin, w)
59
+ result = sum(bit << i for i, bit in enumerate(sums)) + (cout << 4)
60
+ a_val = sum(bit << i for i, bit in enumerate(a))
61
+ b_val = sum(bit << i for i, bit in enumerate(b))
62
+ status = "OK" if result == expected else "FAIL"
63
+ print(f'{a_val:2d} + {b_val:2d} + {cin} = {result:2d} {status}')
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c0caca2c52b6bad0505982754a8378100b17648df967f9fe8adf58db6448c94
3
+ size 6168