potnn 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. potnn-1.0.0/LICENSE +72 -0
  2. potnn-1.0.0/PKG-INFO +260 -0
  3. potnn-1.0.0/README.md +225 -0
  4. potnn-1.0.0/potnn/__init__.py +86 -0
  5. potnn-1.0.0/potnn/codegen/__init__.py +20 -0
  6. potnn-1.0.0/potnn/codegen/bit2.py +263 -0
  7. potnn-1.0.0/potnn/codegen/fp130.py +269 -0
  8. potnn-1.0.0/potnn/codegen/header.py +460 -0
  9. potnn-1.0.0/potnn/codegen/level5.py +393 -0
  10. potnn-1.0.0/potnn/codegen/scale.py +184 -0
  11. potnn-1.0.0/potnn/codegen/ternary.py +354 -0
  12. potnn-1.0.0/potnn/codegen/unroll.py +616 -0
  13. potnn-1.0.0/potnn/config.py +112 -0
  14. potnn-1.0.0/potnn/export.py +2196 -0
  15. potnn-1.0.0/potnn/fuse.py +167 -0
  16. potnn-1.0.0/potnn/modules/__init__.py +11 -0
  17. potnn-1.0.0/potnn/modules/add.py +114 -0
  18. potnn-1.0.0/potnn/modules/avgpool.py +173 -0
  19. potnn-1.0.0/potnn/modules/base.py +225 -0
  20. potnn-1.0.0/potnn/modules/conv.py +203 -0
  21. potnn-1.0.0/potnn/modules/conv1d.py +317 -0
  22. potnn-1.0.0/potnn/modules/depthwise.py +216 -0
  23. potnn-1.0.0/potnn/modules/linear.py +199 -0
  24. potnn-1.0.0/potnn/quantize/__init__.py +35 -0
  25. potnn-1.0.0/potnn/quantize/calibration.py +233 -0
  26. potnn-1.0.0/potnn/quantize/integer_ops.py +207 -0
  27. potnn-1.0.0/potnn/quantize/integer_sim.py +225 -0
  28. potnn-1.0.0/potnn/quantize/pot.py +455 -0
  29. potnn-1.0.0/potnn/quantize/qat.py +356 -0
  30. potnn-1.0.0/potnn/utils/__init__.py +13 -0
  31. potnn-1.0.0/potnn/utils/allocation.py +240 -0
  32. potnn-1.0.0/potnn/utils/memory.py +158 -0
  33. potnn-1.0.0/potnn/wrapper.py +304 -0
  34. potnn-1.0.0/potnn.egg-info/PKG-INFO +260 -0
  35. potnn-1.0.0/potnn.egg-info/SOURCES.txt +38 -0
  36. potnn-1.0.0/potnn.egg-info/dependency_links.txt +1 -0
  37. potnn-1.0.0/potnn.egg-info/requires.txt +2 -0
  38. potnn-1.0.0/potnn.egg-info/top_level.txt +1 -0
  39. potnn-1.0.0/setup.cfg +4 -0
  40. potnn-1.0.0/setup.py +31 -0
potnn-1.0.0/LICENSE ADDED
@@ -0,0 +1,72 @@
1
+ PoT-NN Dual License
2
+ ====================
3
+
4
+ This software is available under a dual license model:
5
+
6
+ 1. GNU General Public License v3.0 (GPL-3.0) - For open source use
7
+ 2. Commercial License - For proprietary/closed-source use
8
+
9
+ --------------------------------------------------------------------------------
10
+
11
+ OPTION 1: GPL-3.0 (Open Source)
12
+ --------------------------------
13
+
14
+ Copyright (c) 2026 PoT-NN Developers
15
+
16
+ This program is free software: you can redistribute it and/or modify
17
+ it under the terms of the GNU General Public License as published by
18
+ the Free Software Foundation, either version 3 of the License, or
19
+ (at your option) any later version.
20
+
21
+ This program is distributed in the hope that it will be useful,
22
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ GNU General Public License for more details.
25
+
26
+ You should have received a copy of the GNU General Public License
27
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
28
+
29
+ **Summary of GPL-3.0 Requirements:**
30
+ - You must disclose your source code if you distribute the software
31
+ - Derivative works must also be licensed under GPL-3.0
32
+ - You must include the original copyright notice
33
+ - Changes to the code must be documented
34
+
35
+ --------------------------------------------------------------------------------
36
+
37
+ OPTION 2: Commercial License
38
+ -----------------------------
39
+
40
+ For companies and individuals who wish to use PoT-NN in proprietary products
41
+ without the obligations of the GPL license, a commercial license is available.
42
+
43
+ **Commercial License Benefits:**
44
+ - Use in closed-source products
45
+ - No requirement to disclose your source code
46
+ - No copyleft obligations
47
+ - Priority support available
48
+
49
+ **To obtain a commercial license, please contact:**
50
+ - Email: [YOUR_EMAIL@example.com]
51
+ - Website: [YOUR_WEBSITE]
52
+
53
+ --------------------------------------------------------------------------------
54
+
55
+ Which License Applies to You?
56
+ ------------------------------
57
+
58
+ - **Open Source Projects**: If your project is open source and will be
59
+ distributed under GPL-3.0 or a compatible license, you can use PoT-NN
60
+ for free under the GPL-3.0 license.
61
+
62
+ - **Commercial/Proprietary Use**: If you want to use PoT-NN in a proprietary
63
+ product without releasing your source code, you need a commercial license.
64
+
65
+ - **Internal Use**: If you're only using PoT-NN internally and not distributing
66
+ it, GPL-3.0 does not require you to release your source code. However, if
67
+ you want dedicated support or prefer clear legal terms, consider a
68
+ commercial license.
69
+
70
+ --------------------------------------------------------------------------------
71
+
72
+ Full GPL-3.0 License Text: https://www.gnu.org/licenses/gpl-3.0.txt
potnn-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: potnn
3
+ Version: 1.0.0
4
+ Summary: Multiplication-free neural networks for ultra-low-power MCUs
5
+ Home-page: https://github.com/scienthoon/potnn
6
+ Author: Scienthoon
7
+ Author-email: scienthoon@gmail.com
8
+ License: GPL-3.0
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Topic :: Software Development :: Embedded Systems
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: torch>=2.0.0
23
+ Requires-Dist: numpy
24
+ Dynamic: author
25
+ Dynamic: author-email
26
+ Dynamic: classifier
27
+ Dynamic: description
28
+ Dynamic: description-content-type
29
+ Dynamic: home-page
30
+ Dynamic: license
31
+ Dynamic: license-file
32
+ Dynamic: requires-dist
33
+ Dynamic: requires-python
34
+ Dynamic: summary
35
+
36
+ # PoT-NN: Multiplication-Free Neural Networks for Ultra-Low-Power MCUs
37
+
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
40
+ [![PyTorch](https://img.shields.io/badge/PyTorch-2.0+-ee4c2c.svg)](https://pytorch.org/)
41
+
42
+ **PoT-NN** is a quantization framework that enables **deep learning inference without multiplication**.
43
+ Run neural networks on ultra-low-cost MCUs without hardware multipliers (CH32V003, PY32F003, etc.).
44
+
45
+ > ๐Ÿ‡ฐ๐Ÿ‡ท [ํ•œ๊ตญ์–ด ๋ฌธ์„œ](README_ko.md)
46
+
47
+ ## ๐ŸŽฏ Key Features
48
+
49
+ | Feature | Description |
50
+ |---------|-------------|
51
+ | **Multiplication-Free** | All weights quantized to powers-of-two, using only `<<`, `>>`, `+` operations |
52
+ | **Integer-Only Inference** | No floating-point operations, only `int8`/`int32` arithmetic |
53
+ | **5 Encoding Modes** | Choose between accuracy vs. memory tradeoff |
54
+ | **Auto C Export** | Generates standalone C header files with zero dependencies |
55
+ | **Bit-Exact Matching** | Guaranteed 100% match between Python simulation and C code |
56
+
57
+ ## ๐Ÿ“ฆ Installation
58
+
59
+ ```bash
60
+ git clone https://github.com/YOUR_USERNAME/potnn.git
61
+ cd potnn
62
+ pip install -e .
63
+ ```
64
+
65
+ ## ๐Ÿš€ Quick Start
66
+
67
+ ### Method 1: One-Line Training (Recommended)
68
+
69
+ ```python
70
+ import torch
71
+ import torch.nn as nn
72
+ import potnn
73
+ from potnn import PoTConv2d, PoTLinear
74
+
75
+ # 1. Define model using PoT layers
76
+ class TinyNet(nn.Module):
77
+ def __init__(self):
78
+ super().__init__()
79
+ self.conv1 = PoTConv2d(1, 8, kernel_size=3, padding=1)
80
+ self.conv2 = PoTConv2d(8, 16, kernel_size=3, padding=1)
81
+ self.pool = nn.AdaptiveAvgPool2d(1) # Auto-replaced with PoTGlobalAvgPool
82
+ self.fc = PoTLinear(16, 10)
83
+
84
+ def forward(self, x):
85
+ x = torch.relu(self.conv1(x))
86
+ x = nn.functional.max_pool2d(x, 2)
87
+ x = torch.relu(self.conv2(x))
88
+ x = self.pool(x).view(x.size(0), -1)
89
+ return self.fc(x)
90
+
91
+ model = TinyNet()
92
+
93
+ # 2. Configure
94
+ config = potnn.Config(
95
+ flash=16384, # Target MCU Flash (bytes)
96
+ ram=2048, # Target MCU RAM (bytes)
97
+ mean=0.1307, # Dataset mean
98
+ std=0.3081, # Dataset std
99
+ input_h=16, input_w=16, input_channels=1,
100
+ )
101
+
102
+ # 3. Train (Float โ†’ Calibrate โ†’ QAT โ†’ Integer Sim)
103
+ model = potnn.train(model, train_loader, test_loader, config,
104
+ float_epochs=15, qat_epochs=50)
105
+
106
+ # 4. Export to C
107
+ potnn.export(model, "model.h", config)
108
+ ```
109
+
110
+ ### Method 2: Manual Pipeline
111
+
112
+ ```python
113
+ import potnn
114
+
115
+ # Step 1: Train float model (standard PyTorch training)
116
+ train_float(model, train_loader, epochs=15)
117
+
118
+ # Step 2: Fuse BatchNorm into Conv (if any)
119
+ potnn.fuse_batchnorm(model)
120
+
121
+ # Step 3: Calibrate activation scales
122
+ potnn.calibrate(model, train_loader, config)
123
+
124
+ # Step 4: Prepare for QAT
125
+ potnn.prepare_qat(model, config)
126
+
127
+ # Step 5: QAT training
128
+ train_qat(model, train_loader, epochs=50)
129
+
130
+ # Step 6: Enable integer simulation (C-compatible)
131
+ potnn.enable_integer_sim(model, input_std=config.std, input_mean=config.mean)
132
+
133
+ # Step 7: Export
134
+ potnn.export(model, "model.h", config)
135
+ ```
136
+
137
+ ## ๐Ÿ“Š Encoding Modes
138
+
139
+ Choose encoding based on accuracy vs. memory tradeoff:
140
+
141
+ | Encoding | Levels | Values | Bits/Weight | Best For |
142
+ |----------|--------|--------|-------------|----------|
143
+ | `unroll` | 17 | 0, ยฑ1, ยฑ2, ยฑ4, ..., ยฑ128 | Code-unrolled | Highest accuracy |
144
+ | `fp130` | 16 | ยฑ1, ยฑ2, ยฑ4, ..., ยฑ128 | 4-bit | Dense layers |
145
+ | `5level` | 5 | -8, -1, 0, +1, +8 | 4-bit (skip) | Balanced |
146
+ | `2bit` | 4 | -2, -1, +1, +2 | 2-bit | Smallest memory |
147
+ | `ternary` | 3 | -1, 0, +1 | 2-bit (RLE) | Sparse models |
148
+
149
+ ### Per-Layer Encoding
150
+
151
+ ```python
152
+ config = potnn.Config(
153
+ flash=16384, ram=2048,
154
+ layer_encodings={
155
+ 'conv1': 'unroll', # First layer: max accuracy
156
+ 'conv2': '5level', # Middle layer
157
+ 'fc': 'unroll', # Last layer: max accuracy
158
+ },
159
+ default_encoding='5level'
160
+ )
161
+ ```
162
+
163
+ ### Encoding Details
164
+
165
+ #### `unroll` (Default)
166
+ - Weights embedded directly as shift-add operations
167
+ - Zero weights omitted entirely (sparse-friendly)
168
+ - Largest code size, highest accuracy
169
+
170
+ #### `fp130` (FP1.3.0 Format)
171
+ - 4-bit packing: `[sign(1)][exp(3)]`
172
+ - No zero (zeros replaced with ยฑ1)
173
+ - Good for dense layers
174
+
175
+ #### `5level` (Skip Encoding)
176
+ - 4-bit packing: `[skip(2)][sign(1)][mag(1)]`
177
+ - Skip field compresses consecutive zeros (0-3)
178
+ - **Constraint**: Max 3 consecutive zeros (4th+ replaced with +1)
179
+
180
+ #### `2bit`
181
+ - 2-bit packing: `[sign(1)][shift(1)]`
182
+ - Smallest memory (16 weights per uint32)
183
+ - No zero (zeros replaced with ยฑ1)
184
+
185
+ #### `ternary` (Triple-Run)
186
+ - 2-bit codes with run-length encoding
187
+ - `11` code = repeat previous value 2 more times
188
+ - Best for very sparse models
189
+
190
+ ## ๐Ÿ“ Supported Layers
191
+
192
+ | Layer | Class | Notes |
193
+ |-------|-------|-------|
194
+ | Conv2D | `PoTConv2d` | All standard parameters supported |
195
+ | Conv1D | `PoTConv1d` | For time series |
196
+ | Depthwise | `PoTDepthwiseConv2d` | MobileNet-style |
197
+ | Linear | `PoTLinear` | Fully connected |
198
+ | GAP | Auto-replaced | `nn.AdaptiveAvgPool2d(1)` โ†’ `PoTGlobalAvgPool` |
199
+ | Add | `PoTAdd` | For residual connections |
200
+ | BatchNorm | Auto-fused | Merged into preceding Conv/Linear |
201
+
202
+ ## โš™๏ธ API Reference
203
+
204
+ ### `potnn.Config`
205
+
206
+ | Parameter | Type | Required | Description |
207
+ |-----------|------|----------|-------------|
208
+ | `flash` | int | โœ… | Flash memory budget (bytes) |
209
+ | `ram` | int | โœ… | RAM budget (bytes) |
210
+ | `mean` | float/list | โŒ | Dataset mean (single or per-channel) |
211
+ | `std` | float/list | โŒ | Dataset std |
212
+ | `input_h`, `input_w` | int | โŒ | Input dimensions (default: 16ร—16) |
213
+ | `input_channels` | int | โŒ | Input channels (default: 1) |
214
+ | `layer_encodings` | dict | โŒ | Per-layer encoding override |
215
+ | `default_encoding` | str | โŒ | Default encoding (default: 'unroll') |
216
+
217
+ ### Key Functions
218
+
219
+ ```python
220
+ potnn.train(model, train_loader, test_loader, config, ...) # Full pipeline
221
+ potnn.calibrate(model, data_loader, config) # Calibrate scales
222
+ potnn.prepare_qat(model, config) # Enable QAT mode
223
+ potnn.enable_integer_sim(model, input_std, input_mean) # C-compatible mode
224
+ potnn.export(model, output_path, config) # Generate C code
225
+ potnn.fuse_batchnorm(model) # Fuse BN layers
226
+ ```
227
+
228
+ ## ๐Ÿงช Verified Results
229
+
230
+ - **Bit-Exact Matching**: Python integer simulation matches C output 100%
231
+ - **MNIST**: 97%+ accuracy with 12KB binary
232
+ - **100-Model Stress Test**: Verified across random architectures
233
+
234
+ ## ๐Ÿ“ License
235
+
236
+ **Dual License**: GPL-3.0 + Commercial
237
+
238
+ | Use Case | License |
239
+ |----------|---------|
240
+ | Open Source Projects | GPL-3.0 (Free) |
241
+ | Proprietary/Commercial | Commercial License (Contact us) |
242
+
243
+ See [LICENSE](LICENSE) for details.
244
+
245
+ ## ๐Ÿ™ Contributing
246
+
247
+ This project was created by a solo developer without formal CS education.
248
+ There may be bugs, inefficiencies, or areas for improvement.
249
+
250
+ **Any contributions are greatly appreciated!**
251
+ - ๐Ÿ› Bug reports
252
+ - ๐Ÿ’ก Feature suggestions
253
+ - ๐Ÿ”ง Pull requests
254
+ - ๐Ÿ“– Documentation improvements
255
+
256
+ If you find issues or have ideas, please open an issue or PR. Thank you!
257
+
258
+ ---
259
+
260
+ **Made with โค๏ธ for ultra-low-power AI**
potnn-1.0.0/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # PoT-NN: Multiplication-Free Neural Networks for Ultra-Low-Power MCUs
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
5
+ [![PyTorch](https://img.shields.io/badge/PyTorch-2.0+-ee4c2c.svg)](https://pytorch.org/)
6
+
7
+ **PoT-NN** is a quantization framework that enables **deep learning inference without multiplication**.
8
+ Run neural networks on ultra-low-cost MCUs without hardware multipliers (CH32V003, PY32F003, etc.).
9
+
10
+ > ๐Ÿ‡ฐ๐Ÿ‡ท [ํ•œ๊ตญ์–ด ๋ฌธ์„œ](README_ko.md)
11
+
12
+ ## ๐ŸŽฏ Key Features
13
+
14
+ | Feature | Description |
15
+ |---------|-------------|
16
+ | **Multiplication-Free** | All weights quantized to powers-of-two, using only `<<`, `>>`, `+` operations |
17
+ | **Integer-Only Inference** | No floating-point operations, only `int8`/`int32` arithmetic |
18
+ | **5 Encoding Modes** | Choose between accuracy vs. memory tradeoff |
19
+ | **Auto C Export** | Generates standalone C header files with zero dependencies |
20
+ | **Bit-Exact Matching** | Guaranteed 100% match between Python simulation and C code |
21
+
22
+ ## ๐Ÿ“ฆ Installation
23
+
24
+ ```bash
25
+ git clone https://github.com/YOUR_USERNAME/potnn.git
26
+ cd potnn
27
+ pip install -e .
28
+ ```
29
+
30
+ ## ๐Ÿš€ Quick Start
31
+
32
+ ### Method 1: One-Line Training (Recommended)
33
+
34
+ ```python
35
+ import torch
36
+ import torch.nn as nn
37
+ import potnn
38
+ from potnn import PoTConv2d, PoTLinear
39
+
40
+ # 1. Define model using PoT layers
41
+ class TinyNet(nn.Module):
42
+ def __init__(self):
43
+ super().__init__()
44
+ self.conv1 = PoTConv2d(1, 8, kernel_size=3, padding=1)
45
+ self.conv2 = PoTConv2d(8, 16, kernel_size=3, padding=1)
46
+ self.pool = nn.AdaptiveAvgPool2d(1) # Auto-replaced with PoTGlobalAvgPool
47
+ self.fc = PoTLinear(16, 10)
48
+
49
+ def forward(self, x):
50
+ x = torch.relu(self.conv1(x))
51
+ x = nn.functional.max_pool2d(x, 2)
52
+ x = torch.relu(self.conv2(x))
53
+ x = self.pool(x).view(x.size(0), -1)
54
+ return self.fc(x)
55
+
56
+ model = TinyNet()
57
+
58
+ # 2. Configure
59
+ config = potnn.Config(
60
+ flash=16384, # Target MCU Flash (bytes)
61
+ ram=2048, # Target MCU RAM (bytes)
62
+ mean=0.1307, # Dataset mean
63
+ std=0.3081, # Dataset std
64
+ input_h=16, input_w=16, input_channels=1,
65
+ )
66
+
67
+ # 3. Train (Float โ†’ Calibrate โ†’ QAT โ†’ Integer Sim)
68
+ model = potnn.train(model, train_loader, test_loader, config,
69
+ float_epochs=15, qat_epochs=50)
70
+
71
+ # 4. Export to C
72
+ potnn.export(model, "model.h", config)
73
+ ```
74
+
75
+ ### Method 2: Manual Pipeline
76
+
77
+ ```python
78
+ import potnn
79
+
80
+ # Step 1: Train float model (standard PyTorch training)
81
+ train_float(model, train_loader, epochs=15)
82
+
83
+ # Step 2: Fuse BatchNorm into Conv (if any)
84
+ potnn.fuse_batchnorm(model)
85
+
86
+ # Step 3: Calibrate activation scales
87
+ potnn.calibrate(model, train_loader, config)
88
+
89
+ # Step 4: Prepare for QAT
90
+ potnn.prepare_qat(model, config)
91
+
92
+ # Step 5: QAT training
93
+ train_qat(model, train_loader, epochs=50)
94
+
95
+ # Step 6: Enable integer simulation (C-compatible)
96
+ potnn.enable_integer_sim(model, input_std=config.std, input_mean=config.mean)
97
+
98
+ # Step 7: Export
99
+ potnn.export(model, "model.h", config)
100
+ ```
101
+
102
+ ## ๐Ÿ“Š Encoding Modes
103
+
104
+ Choose encoding based on accuracy vs. memory tradeoff:
105
+
106
+ | Encoding | Levels | Values | Bits/Weight | Best For |
107
+ |----------|--------|--------|-------------|----------|
108
+ | `unroll` | 17 | 0, ยฑ1, ยฑ2, ยฑ4, ..., ยฑ128 | Code-unrolled | Highest accuracy |
109
+ | `fp130` | 16 | ยฑ1, ยฑ2, ยฑ4, ..., ยฑ128 | 4-bit | Dense layers |
110
+ | `5level` | 5 | -8, -1, 0, +1, +8 | 4-bit (skip) | Balanced |
111
+ | `2bit` | 4 | -2, -1, +1, +2 | 2-bit | Smallest memory |
112
+ | `ternary` | 3 | -1, 0, +1 | 2-bit (RLE) | Sparse models |
113
+
114
+ ### Per-Layer Encoding
115
+
116
+ ```python
117
+ config = potnn.Config(
118
+ flash=16384, ram=2048,
119
+ layer_encodings={
120
+ 'conv1': 'unroll', # First layer: max accuracy
121
+ 'conv2': '5level', # Middle layer
122
+ 'fc': 'unroll', # Last layer: max accuracy
123
+ },
124
+ default_encoding='5level'
125
+ )
126
+ ```
127
+
128
+ ### Encoding Details
129
+
130
+ #### `unroll` (Default)
131
+ - Weights embedded directly as shift-add operations
132
+ - Zero weights omitted entirely (sparse-friendly)
133
+ - Largest code size, highest accuracy
134
+
135
+ #### `fp130` (FP1.3.0 Format)
136
+ - 4-bit packing: `[sign(1)][exp(3)]`
137
+ - No zero (zeros replaced with ยฑ1)
138
+ - Good for dense layers
139
+
140
+ #### `5level` (Skip Encoding)
141
+ - 4-bit packing: `[skip(2)][sign(1)][mag(1)]`
142
+ - Skip field compresses consecutive zeros (0-3)
143
+ - **Constraint**: Max 3 consecutive zeros (4th+ replaced with +1)
144
+
145
+ #### `2bit`
146
+ - 2-bit packing: `[sign(1)][shift(1)]`
147
+ - Smallest memory (16 weights per uint32)
148
+ - No zero (zeros replaced with ยฑ1)
149
+
150
+ #### `ternary` (Triple-Run)
151
+ - 2-bit codes with run-length encoding
152
+ - `11` code = repeat previous value 2 more times
153
+ - Best for very sparse models
154
+
155
+ ## ๐Ÿ“ Supported Layers
156
+
157
+ | Layer | Class | Notes |
158
+ |-------|-------|-------|
159
+ | Conv2D | `PoTConv2d` | All standard parameters supported |
160
+ | Conv1D | `PoTConv1d` | For time series |
161
+ | Depthwise | `PoTDepthwiseConv2d` | MobileNet-style |
162
+ | Linear | `PoTLinear` | Fully connected |
163
+ | GAP | Auto-replaced | `nn.AdaptiveAvgPool2d(1)` โ†’ `PoTGlobalAvgPool` |
164
+ | Add | `PoTAdd` | For residual connections |
165
+ | BatchNorm | Auto-fused | Merged into preceding Conv/Linear |
166
+
167
+ ## โš™๏ธ API Reference
168
+
169
+ ### `potnn.Config`
170
+
171
+ | Parameter | Type | Required | Description |
172
+ |-----------|------|----------|-------------|
173
+ | `flash` | int | โœ… | Flash memory budget (bytes) |
174
+ | `ram` | int | โœ… | RAM budget (bytes) |
175
+ | `mean` | float/list | โŒ | Dataset mean (single or per-channel) |
176
+ | `std` | float/list | โŒ | Dataset std |
177
+ | `input_h`, `input_w` | int | โŒ | Input dimensions (default: 16ร—16) |
178
+ | `input_channels` | int | โŒ | Input channels (default: 1) |
179
+ | `layer_encodings` | dict | โŒ | Per-layer encoding override |
180
+ | `default_encoding` | str | โŒ | Default encoding (default: 'unroll') |
181
+
182
+ ### Key Functions
183
+
184
+ ```python
185
+ potnn.train(model, train_loader, test_loader, config, ...) # Full pipeline
186
+ potnn.calibrate(model, data_loader, config) # Calibrate scales
187
+ potnn.prepare_qat(model, config) # Enable QAT mode
188
+ potnn.enable_integer_sim(model, input_std, input_mean) # C-compatible mode
189
+ potnn.export(model, output_path, config) # Generate C code
190
+ potnn.fuse_batchnorm(model) # Fuse BN layers
191
+ ```
192
+
193
+ ## ๐Ÿงช Verified Results
194
+
195
+ - **Bit-Exact Matching**: Python integer simulation matches C output 100%
196
+ - **MNIST**: 97%+ accuracy with 12KB binary
197
+ - **100-Model Stress Test**: Verified across random architectures
198
+
199
+ ## ๐Ÿ“ License
200
+
201
+ **Dual License**: GPL-3.0 + Commercial
202
+
203
+ | Use Case | License |
204
+ |----------|---------|
205
+ | Open Source Projects | GPL-3.0 (Free) |
206
+ | Proprietary/Commercial | Commercial License (Contact us) |
207
+
208
+ See [LICENSE](LICENSE) for details.
209
+
210
+ ## ๐Ÿ™ Contributing
211
+
212
+ This project was created by a solo developer without formal CS education.
213
+ There may be bugs, inefficiencies, or areas for improvement.
214
+
215
+ **Any contributions are greatly appreciated!**
216
+ - ๐Ÿ› Bug reports
217
+ - ๐Ÿ’ก Feature suggestions
218
+ - ๐Ÿ”ง Pull requests
219
+ - ๐Ÿ“– Documentation improvements
220
+
221
+ If you find issues or have ideas, please open an issue or PR. Thank you!
222
+
223
+ ---
224
+
225
+ **Made with โค๏ธ for ultra-low-power AI**
@@ -0,0 +1,86 @@
1
+ """potnn: Power-of-Two Neural Network Compiler for Ultra-Low-Cost MCUs
2
+
3
+ A PyTorch-based library for training and deploying neural networks
4
+ on MCUs without multiplication instructions, using only shifts and adds.
5
+ """
6
+
7
+ __version__ = "0.4.8"
8
+
9
+ # Import core modules
10
+ from .modules.conv import PoTConv2d
11
+ from .modules.conv1d import PoTConv1d
12
+ from .modules.depthwise import PoTDepthwiseConv2d
13
+ from .modules.linear import PoTLinear
14
+ from .modules.add import PoTAdd
15
+ from .modules.avgpool import PoTGlobalAvgPool
16
+ from .config import Config
17
+ from .export import export
18
+ from .quantize.calibration import calibrate_model
19
+ from .quantize.qat import prepare_qat, enable_integer_sim, disable_integer_sim
20
+ from .wrapper import train
21
+ from .fuse import fuse_batchnorm, check_bn_fused
22
+
23
+
24
+ def calibrate(model, data_loader, config=None, num_batches=10, mean=None, std=None):
25
+ """Calibrate model activation scales.
26
+
27
+ Two calling conventions supported:
28
+
29
+ 1. With config (recommended):
30
+ calibrate(model, loader, config, num_batches=10)
31
+
32
+ 2. Direct parameters:
33
+ calibrate(model, loader, num_batches=10, mean=[0.1307], std=[0.3081])
34
+
35
+ Args:
36
+ model: Model with PoT layers
37
+ data_loader: Calibration data loader
38
+ config: potnn.Config object (optional, extracts mean/std from it)
39
+ num_batches: Number of batches for calibration (default: 10)
40
+ mean: Dataset mean (list or float), used if config not provided
41
+ std: Dataset std (list or float), used if config not provided
42
+
43
+ Returns:
44
+ Dictionary of activation max values per layer
45
+ """
46
+ # Handle config object
47
+ if config is not None and isinstance(config, Config):
48
+ mean = config.mean if config.mean is not None else [0.0]
49
+ std = config.std if config.std is not None else [1.0]
50
+
51
+ # Handle num_batches passed as config (common mistake)
52
+ if isinstance(config, int):
53
+ num_batches = config
54
+ config = None
55
+
56
+ # Default values
57
+ if mean is None:
58
+ mean = 0.0
59
+ if std is None:
60
+ std = 1.0
61
+
62
+ return calibrate_model(model, data_loader, num_batches=num_batches, mean=mean, std=std)
63
+
64
+
65
+ __all__ = [
66
+ 'PoTConv2d',
67
+ 'PoTConv1d',
68
+ 'PoTDepthwiseConv2d',
69
+ 'PoTLinear',
70
+ 'PoTAdd',
71
+ 'PoTGlobalAvgPool',
72
+ 'Config',
73
+ 'export',
74
+ 'calibrate_model',
75
+ 'calibrate',
76
+ 'prepare_qat',
77
+ 'enable_integer_sim',
78
+ 'disable_integer_sim',
79
+ 'train',
80
+ 'fuse_batchnorm',
81
+ 'check_bn_fused',
82
+ ]
83
+
84
+ # Package metadata
85
+ __author__ = "potnn developers"
86
+ __license__ = "MIT"
@@ -0,0 +1,20 @@
1
+ """C code generation module for potnn."""
2
+
3
+ from .header import generate_c_header
4
+ from .unroll import generate_unrolled_layer
5
+ from .scale import decompose_scale_to_shifts, generate_scale_func
6
+ from .fp130 import generate_fp130_layer
7
+ from .bit2 import generate_2bit_layer
8
+ from .level5 import generate_5level_layer
9
+ from .ternary import generate_ternary_layer
10
+
11
+ __all__ = [
12
+ 'generate_c_header',
13
+ 'generate_unrolled_layer',
14
+ 'decompose_scale_to_shifts',
15
+ 'generate_scale_func',
16
+ 'generate_fp130_layer',
17
+ 'generate_2bit_layer',
18
+ 'generate_5level_layer',
19
+ 'generate_ternary_layer',
20
+ ]