Upload folder using huggingface_hub
Browse files- README.md +147 -0
- config.json +9 -0
- model.py +63 -0
- 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
|