tinymlc 0.1.0__py3-none-any.whl

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 (47) hide show
  1. TinyMLC/ANG/__init__.py +0 -0
  2. TinyMLC/ANG/args.py +86 -0
  3. TinyMLC/ANG/estimator.py +103 -0
  4. TinyMLC/ANG/estimator_hal.py +184 -0
  5. TinyMLC/ANG/estimator_qemu.py +257 -0
  6. TinyMLC/ANG/estimator_software.py +130 -0
  7. TinyMLC/ANG/model_builder.py +508 -0
  8. TinyMLC/ANG/model_generator.py +439 -0
  9. TinyMLC/ANG/model_info.py +283 -0
  10. TinyMLC/ANG/utils.py +420 -0
  11. TinyMLC/__init__.py +0 -0
  12. TinyMLC/cli.py +126 -0
  13. TinyMLC/codegen.py +877 -0
  14. TinyMLC/converter/__init__.py +0 -0
  15. TinyMLC/converter/export_weights.py +382 -0
  16. TinyMLC/converter/parser_litert.py +757 -0
  17. TinyMLC/converter/parser_onnx.py +649 -0
  18. TinyMLC/generate_lut.py +97 -0
  19. TinyMLC/handlers.py +325 -0
  20. TinyMLC/ops.py +76 -0
  21. TinyMLC/templates/lut.c.tpl +23 -0
  22. TinyMLC/templates/lut.h.tpl +67 -0
  23. TinyMLC/templates/model.c.tpl +314 -0
  24. TinyMLC/templates/model.h.tpl +66 -0
  25. TinyMLC/transform/__init__.py +0 -0
  26. TinyMLC/transform/algebraic.py +286 -0
  27. TinyMLC/transform/base.py +58 -0
  28. TinyMLC/transform/constant_folding.py +260 -0
  29. TinyMLC/transform/cse.py +192 -0
  30. TinyMLC/transform/dce.py +182 -0
  31. TinyMLC/transform/fusion.py +723 -0
  32. TinyMLC/transform/memory.py +200 -0
  33. TinyMLC/transform/pass_manager.py +101 -0
  34. TinyMLC/transform/simplify.py +515 -0
  35. tinymlc-0.1.0.dist-info/METADATA +49 -0
  36. tinymlc-0.1.0.dist-info/RECORD +47 -0
  37. tinymlc-0.1.0.dist-info/WHEEL +4 -0
  38. tinymlc-0.1.0.dist-info/entry_points.txt +2 -0
  39. tinymlc-0.1.0.dist-info/licenses/LICENSE +201 -0
  40. utils/__init__.py +0 -0
  41. utils/arm-none-eabi-gcc.cmake +53 -0
  42. utils/dump.py +86 -0
  43. utils/generate_onnx_models.py +183 -0
  44. utils/generate_tflite_models.py +236 -0
  45. utils/pack_macos.sh +88 -0
  46. utils/path.py +31 -0
  47. utils/riscv-none-elf-gcc.cmake +50 -0
@@ -0,0 +1,97 @@
1
+ # -*- coding: utf-8 -*-
2
+ # TinyMLC - Tiny Machine Learning Compiler
3
+ #
4
+ # Copyright (c) 2026 Jia Liu & TinyMLC Contributors
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ #
7
+ # This file is part of TinyMLC.
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at:
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ #!/usr/bin/env python3
21
+ """
22
+ Generate sigmoid and tanh int16 lookup tables (256 entries,
23
+ for int8 quantized LSTM)
24
+ """
25
+
26
+ import numpy as np
27
+ from pathlib import Path
28
+ from jinja2 import Template
29
+
30
+ from utils.dump import fatal_error, info
31
+
32
+
33
+ def generate_sigmoid_lut():
34
+ """Generate sigmoid LUT, output int16 range [0, 32767]"""
35
+ x = np.linspace(-8, 8, 256, endpoint=False)
36
+ y = 1 / (1 + np.exp(-x))
37
+ # Quantize to int16: 0~1 maps to 0~32767
38
+ y_scaled = np.round(y * 32767).astype(np.int16)
39
+ return y_scaled
40
+
41
+
42
+ def generate_tanh_lut():
43
+ """Generate tanh LUT, output int16 range [-32768, 32767]"""
44
+ x = np.linspace(-8, 8, 256, endpoint=False)
45
+ y = np.tanh(x)
46
+ # Quantize to int16: -1~1 maps to -32768~32767
47
+ y_scaled = np.round(y * 32767).astype(np.int16)
48
+ return y_scaled
49
+
50
+
51
+ def generate_lut(output_dir: Path):
52
+ """Generate LUT header and source files"""
53
+ try:
54
+ output_dir.mkdir(parents=True, exist_ok=True)
55
+
56
+ sigmoid_lut = generate_sigmoid_lut()
57
+ tanh_lut = generate_tanh_lut()
58
+
59
+ # Render lut.h.tpl
60
+ template_path = Path(__file__).parent / 'templates' / 'lut.h.tpl'
61
+ with open(template_path, 'r') as f:
62
+ template = Template(f.read())
63
+
64
+ lut_h = template.render(
65
+ sigmoid_lut=sigmoid_lut.tolist(),
66
+ tanh_lut=tanh_lut.tolist()
67
+ )
68
+
69
+ with open(output_dir / 'lut.h', 'w') as f:
70
+ f.write(lut_h)
71
+
72
+ # Render lut.c.tpl
73
+ template_path = Path(__file__).parent / 'templates' / 'lut.c.tpl'
74
+ with open(template_path, 'r') as f:
75
+ template = Template(f.read())
76
+
77
+ lut_c = template.render()
78
+
79
+ with open(output_dir / 'lut.c', 'w') as f:
80
+ f.write(lut_c)
81
+
82
+ info(f"Generated: {output_dir}/lut.h")
83
+ info(f"Generated: {output_dir}/lut.c")
84
+
85
+ except Exception as e:
86
+ fatal_error(
87
+ f"LUT generation failed: {e}",
88
+ "Check numpy and file system permissions")
89
+
90
+
91
+ def main():
92
+ output_dir = Path('tinymlc_generated')
93
+ generate_lut(output_dir)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
TinyMLC/handlers.py ADDED
@@ -0,0 +1,325 @@
1
+ # -*- coding: utf-8 -*-
2
+ # TinyMLC - Tiny Machine Learning Compiler
3
+ #
4
+ # Copyright (c) 2026 Jia Liu & TinyMLC Contributors
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ #
7
+ # This file is part of TinyMLC.
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at:
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ #!/usr/bin/env python3
21
+ """
22
+ Command handlers for TinyMLC CLI.
23
+ Contains handle_generate, handle_table, handle_convert.
24
+ """
25
+
26
+ import argparse
27
+ import json
28
+ import subprocess
29
+ import sys
30
+ from pathlib import Path
31
+
32
+ from TinyMLC.ANG.model_generator import ModelGenerator
33
+ from TinyMLC.ANG.args import create_estimator
34
+ from TinyMLC.converter.parser_litert import parse_model_tflite, extract_all_weights_litert
35
+ from TinyMLC.converter.parser_onnx import parse_model_onnx, extract_all_weights_onnx
36
+ from TinyMLC.converter.export_weights import export_model_weights
37
+ from utils.path import get_output_dir
38
+ from TinyMLC.codegen import generate_c_code, copy_files_to_build
39
+ from TinyMLC.generate_lut import generate_lut
40
+ from TinyMLC.transform.pass_manager import PassManager
41
+ from utils.dump import fatal_error, warning, info, dump_model_info
42
+
43
+
44
+ def handle_generate(args: argparse.Namespace) -> int:
45
+ info("Running network generation...")
46
+ estimator = create_estimator(args)
47
+
48
+ generator = ModelGenerator(
49
+ estimator=estimator,
50
+ config={
51
+ "task_type": getattr(args, "task_type", "classification"),
52
+ "population_size": getattr(args, "population", 50),
53
+ "generations": getattr(args, "generations", 50),
54
+ "mutation_rate": getattr(args, "mutation_rate", 0.1),
55
+ "crossover_rate": getattr(args, "crossover_rate", 0.8),
56
+ "early_stop": getattr(args, "early_stop", 10),
57
+ "input_shape": getattr(args, "input_shape", [1, 28, 28, 1]),
58
+ "output_shape": getattr(args, "output_shape", [1, 10]),
59
+ "max_macs": getattr(args, "max_macs", 100000),
60
+ "max_ram": getattr(args, "max_ram", 30) * 1024,
61
+ "max_flash": getattr(args, "max_flash", 64) * 1024,
62
+ "num_samples": getattr(args, "num_samples", 100),
63
+ },
64
+ )
65
+
66
+ mode = getattr(args, "generate_mode", "genetic")
67
+ model_info = generator.generate(mode=mode)
68
+
69
+ # Get target, mode, accel for code generation and build
70
+ target = getattr(args, "target", "riscv")
71
+ mode = getattr(args, "mode", "release")
72
+ accel = getattr(args, "accel", "pure-c")
73
+ run = getattr(args, "run", False)
74
+
75
+ # Validate target/accel/mode combination
76
+ if target == "arm":
77
+ if accel not in ("pure-c", "cmsis-nn"):
78
+ fatal_error(
79
+ f"Invalid --accel '{accel}' for --target arm",
80
+ "Supported accel for ARM: pure-c, cmsis-nn")
81
+ elif target == "riscv":
82
+ if accel not in ("pure-c", "nmsis-nn", "nuclei-ai"):
83
+ fatal_error(
84
+ f"Invalid --accel '{accel}' for --target riscv",
85
+ "Supported accel for RISC-V: pure-c, nmsis-nn, nuclei-ai")
86
+ elif target == "host":
87
+ # Host only supports pure-c and debug mode
88
+ if accel != "pure-c":
89
+ fatal_error(
90
+ f"Invalid --accel '{accel}' for --target host",
91
+ "Host only supports pure-c (no hardware acceleration)")
92
+ if mode != "debug":
93
+ warning("Host target only supports debug mode, forcing mode=debug")
94
+ mode = "debug"
95
+
96
+ # ---- Dump model_info BEFORE optimization? No ----
97
+ # dump_model = getattr(args, "dump_model", None)
98
+ # if dump_model:
99
+ # with open(dump_model, "w") as f:
100
+ # json.dump(model_info, f, indent=2, default=str)
101
+ # info(f"Model info saved to: {dump_model}")
102
+
103
+ # ---- Optimization passes ----
104
+ pm = PassManager.default_pipeline()
105
+ info("Running optimization passes...")
106
+ optimized_model_info = pm.run(model_info)
107
+ pm.dump_summary()
108
+
109
+ # ---- Generate C code ----
110
+ info("Generating C code...")
111
+ out_dir = get_output_dir(args)
112
+ result = generate_c_code(
113
+ model_info=optimized_model_info,
114
+ output_dir=str(out_dir),
115
+ target=target,
116
+ inference_func=getattr(args, "inference_function_name",
117
+ "tinymlc_inference"),
118
+ with_test_main=True, # Always generate test main for generated networks
119
+ )
120
+
121
+ # ---- Dump optimized model_info (with quant_scales) ----
122
+ dump_model = getattr(args, "dump_model", None)
123
+ if dump_model:
124
+ with open(dump_model, "w") as f:
125
+ json.dump(optimized_model_info, f, indent=2, default=str)
126
+ info(f"Optimized model info saved to: {dump_model}")
127
+
128
+ for filename, content in result.items():
129
+ filepath = out_dir / filename
130
+ with open(filepath, "w") as f:
131
+ f.write(content)
132
+ info(f"Generated: {filepath}")
133
+
134
+ # Export weights (needed for ANG-generated models)
135
+ quant_scales = export_model_weights(out_dir, optimized_model_info)
136
+ optimized_model_info["quant_scales"] = quant_scales
137
+
138
+ # Generate LUT and copy build files
139
+ generate_lut(out_dir)
140
+
141
+ # Compute accel library paths if not provided
142
+ project_root = Path(__file__).parent
143
+ accel_lib_inc = getattr(args, "accel_lib_inc", None)
144
+ accel_lib_lib = getattr(args, "accel_lib_lib", None)
145
+
146
+ if accel == "cmsis-nn" and (not accel_lib_inc or not accel_lib_lib):
147
+ accel_lib_inc = str(project_root / "third_party" /
148
+ "CMSIS-NN-7.0.0" / "Include")
149
+ accel_lib_lib = str(project_root / "third_party" /
150
+ "CMSIS-NN-7.0.0" / "Lib" / "libcmsis-nn.a")
151
+ elif accel == "nmsis-nn" and (not accel_lib_inc or not accel_lib_lib):
152
+ accel_lib_inc = str(project_root / "third_party" /
153
+ "NMSIS-NN-1.6.0" / "Include")
154
+ accel_lib_lib = str(project_root / "third_party" /
155
+ "NMSIS-NN-1.6.0" / "Lib" / "libNMSISNN.a")
156
+
157
+ if accel == "pure-c":
158
+ copy_files_to_build(out_dir, target, mode, accel)
159
+ copy_files_to_build(out_dir, target, mode, accel,
160
+ accel_lib_inc, accel_lib_lib)
161
+
162
+ # Determine script name (must match copy_files_to_build logic)
163
+ if target == "host":
164
+ script_name = "build_host_debug.sh"
165
+ elif accel != 'none':
166
+ script_name = f"build_{target}_{accel.replace('-', '_')}_{mode}.sh"
167
+ else:
168
+ script_name = f"build_{target}_{mode}.sh"
169
+
170
+ if run:
171
+ script_path = out_dir / script_name
172
+ try:
173
+ script_path.chmod(0o755)
174
+ except OSError:
175
+ pass
176
+ info(f"Executing: {script_path}")
177
+ result = subprocess.run(
178
+ [str(script_path.resolve())],
179
+ cwd=out_dir)
180
+ sys.exit(result.returncode)
181
+
182
+ info(f"Done! Output directory: {out_dir}")
183
+ info("\nNext steps:")
184
+ info(f" cd {out_dir}")
185
+ info(f" ./{script_name}")
186
+
187
+ return 0
188
+
189
+
190
+ def handle_convert(args: argparse.Namespace) -> int:
191
+ target = getattr(args, "target", None)
192
+ mode = getattr(args, "mode", None)
193
+ accel = getattr(args, "accel", None)
194
+ model_path = getattr(args, "model", None)
195
+ output_dir = Path(getattr(args, "output_dir", ".."))
196
+ with_test_main = getattr(args, "with_test_main", None)
197
+ inference_function_name = getattr(args, "inference_function_name", None)
198
+ verbose = getattr(args, "verbose", None)
199
+ run = getattr(args, "run", None)
200
+
201
+ if not model_path:
202
+ fatal_error("--model is required for convert")
203
+ if not Path(model_path).exists():
204
+ fatal_error(f"Model file not found: {model_path}",
205
+ "Please check file path")
206
+
207
+ output_dir.mkdir(parents=True, exist_ok=True)
208
+
209
+ if model_path.endswith(".tflite"):
210
+ # Lazy import to avoid dependency when not using tflite
211
+ model_info = parse_model_tflite(model_path)
212
+ # Extract weights (interpreter created internally)
213
+ extract_all_weights_litert(model_path, model_info)
214
+ # Export weights using unified function
215
+ quant_scales = export_model_weights(output_dir, model_info)
216
+ model_info["quant_scales"] = quant_scales
217
+ elif model_path.endswith(".onnx"):
218
+ model_info = parse_model_onnx(model_path)
219
+ # Extract weights (model_path for consistency)
220
+ extract_all_weights_onnx(model_path, model_info)
221
+ # Export weights using unified function
222
+ quant_scales = export_model_weights(output_dir, model_info)
223
+ model_info["quant_scales"] = quant_scales
224
+ else:
225
+ fatal_error("Unsupported model format", "Supported: .tflite and .onnx")
226
+
227
+ info(f"Converting model: {model_path}")
228
+
229
+ if verbose:
230
+ dump_model_info(model_info)
231
+
232
+ if target == "arm":
233
+ if accel not in ("pure-c", "cmsis-nn"):
234
+ fatal_error(
235
+ f"Invalid --accel '{accel}' for --target arm",
236
+ "Supported accel for ARM: pure-c, cmsis-nn")
237
+ elif target == "riscv":
238
+ if accel not in ("pure-c", "nmsis-nn", "nuclei-ai"):
239
+ fatal_error(
240
+ f"Invalid --accel '{accel}' for --target riscv",
241
+ "Supported accel for RISC-V: pure-c, nmsis-nn, nuclei-ai")
242
+ elif target == "host":
243
+ # Host only supports pure-c and debug mode
244
+ if accel != "pure-c":
245
+ fatal_error(
246
+ f"Invalid --accel '{accel}' for --target host",
247
+ "Host only supports pure-c (no hardware acceleration)")
248
+ if mode != "debug":
249
+ warning("Host target only supports debug mode, forcing mode=debug")
250
+ mode = "debug"
251
+ else:
252
+ fatal_error(
253
+ f"Invalid --target '{target}'",
254
+ "Supported targets: arm, riscv, host")
255
+
256
+ dump_model = getattr(args, "dump_model", None)
257
+ if dump_model:
258
+ with open(dump_model, "w") as f:
259
+ json.dump(model_info, f, indent=2, default=str)
260
+ info(f"Model info saved to: {dump_model}")
261
+
262
+ # ---- Optimization passes ----
263
+ pm = PassManager.default_pipeline()
264
+ info("Running optimization passes...")
265
+ optimized_model_info = pm.run(model_info)
266
+ pm.dump_summary()
267
+
268
+ info("Generating C code...")
269
+ generated_files = generate_c_code(
270
+ optimized_model_info, output_dir, target,
271
+ inference_func=inference_function_name,
272
+ with_test_main=with_test_main)
273
+
274
+ for filename, content in generated_files.items():
275
+ output_path = output_dir / filename
276
+ with open(output_path, 'w') as f:
277
+ f.write(content)
278
+ info(f"Generated: {output_path}")
279
+
280
+ generate_lut(output_dir)
281
+
282
+ # Compute accel library paths if not provided
283
+ project_root = Path(__file__).parent
284
+ accel_lib_inc = getattr(args, "accel_lib_inc", None)
285
+ accel_lib_lib = getattr(args, "accel_lib_lib", None)
286
+
287
+ if accel == "cmsis-nn" and (not accel_lib_inc or not accel_lib_lib):
288
+ accel_lib_inc = str(project_root / "third_party" /
289
+ "CMSIS-NN-7.0.0" / "Include")
290
+ accel_lib_lib = str(project_root / "third_party" /
291
+ "CMSIS-NN-7.0.0" / "Lib" / "libcmsis-nn.a")
292
+ elif accel == "nmsis-nn" and (not accel_lib_inc or not accel_lib_lib):
293
+ accel_lib_inc = str(project_root / "third_party" /
294
+ "NMSIS-NN-1.6.0" / "Include")
295
+ accel_lib_lib = str(project_root / "third_party" /
296
+ "NMSIS-NN-1.6.0" / "Lib" / "libNMSISNN.a")
297
+
298
+ copy_files_to_build(output_dir, target, mode, accel,
299
+ accel_lib_inc, accel_lib_lib)
300
+
301
+ # Determine script name
302
+ if target == "host":
303
+ script_name = "build_host_debug.sh"
304
+ elif accel != 'none':
305
+ script_name = (
306
+ f"build_{target}_{accel.replace('-', '_')}_{mode}.sh")
307
+ else:
308
+ script_name = f"build_{target}_{mode}.sh"
309
+
310
+ if run:
311
+ script_path = output_dir / script_name
312
+ try:
313
+ script_path.chmod(0o755)
314
+ except OSError:
315
+ pass
316
+ info(f"Executing: {script_path} {model_path}")
317
+ result = subprocess.run(
318
+ [str(script_path.resolve()), model_path],
319
+ cwd=output_dir)
320
+ sys.exit(result.returncode)
321
+
322
+ info(f"Done! Output directory: {output_dir}")
323
+ info("\nNext steps:")
324
+ info(f" cd {output_dir}")
325
+ info(f" ./{script_name} {model_path}")
TinyMLC/ops.py ADDED
@@ -0,0 +1,76 @@
1
+ # -*- coding: utf-8 -*-
2
+ # TinyMLC - Tiny Machine Learning Compiler
3
+ #
4
+ # Copyright (c) 2026 Jia Liu & TinyMLC Contributors
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ #
7
+ # This file is part of TinyMLC.
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at:
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+
21
+ SUPPORTED_OPS = [
22
+ # Activation
23
+ "RELU",
24
+ "RELU6",
25
+ "LEAKY_RELU",
26
+ "PRELU",
27
+ "HARD_SIGMOID",
28
+ "SIGMOID",
29
+ "TANH",
30
+ "CLIP",
31
+
32
+ # Convolution
33
+ "CONV_2D",
34
+ "DEPTHWISE_CONV_2D",
35
+ "CONV_TRANSPOSE",
36
+
37
+ # Pooling
38
+ "MAX_POOL_2D",
39
+ "AVG_POOL_2D",
40
+ "GLOBAL_AVG_POOL",
41
+
42
+ # Fully Connected
43
+ "FULLY_CONNECTED",
44
+
45
+ # Activation (continued)
46
+ "SOFTMAX",
47
+
48
+ # Tensor operations
49
+ "RESHAPE",
50
+ "TRANSPOSE",
51
+ "CONCAT",
52
+ "SPLIT",
53
+ "PAD",
54
+ "STRIDED_SLICE",
55
+ "FLATTEN",
56
+
57
+ # Arithmetic
58
+ "ADD",
59
+ "MULTIPLY",
60
+ "SUB",
61
+ "MEAN",
62
+ "REDUCE_SUM",
63
+ "ARGMAX",
64
+
65
+ # Upsampling
66
+ "UPSAMPLE",
67
+ "RESIZE_NEAREST_NEIGHBOR",
68
+
69
+ # RNN
70
+ "LSTM",
71
+ "SVDF",
72
+
73
+ # Quantization
74
+ "QUANTIZE",
75
+ "DEQUANTIZE",
76
+ ]
@@ -0,0 +1,23 @@
1
+ /* TinyMLC - Tiny Machine Learning Compiler
2
+ *
3
+ * Copyright (c) 2026 Jia Liu & TinyMLC Contributors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * This file is part of TinyMLC.
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ // Auto-generated LUT implementation
21
+ // Actual content is in lut.h, this file is just a placeholder
22
+
23
+ #include "lut.h"
@@ -0,0 +1,67 @@
1
+ /* TinyMLC - Tiny Machine Learning Compiler
2
+ *
3
+ * Copyright (c) 2026 Jia Liu & TinyMLC Contributors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * This file is part of TinyMLC.
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ // Auto-generated LUT tables, do not modify manually
21
+ // sigmoid and tanh int16 lookup tables (256 entries)
22
+
23
+ #ifndef TINYMLC_LUT_H
24
+ #define TINYMLC_LUT_H
25
+
26
+ #include <stdint.h>
27
+
28
+ // Sigmoid LUT (input range [-8,8), output range [0,1] quantized to [0,32767])
29
+ static const int16_t sigmoid_lut[256] = {
30
+ {% for val in sigmoid_lut %}
31
+ {{ val }}{% if not loop.last %},{% endif %}
32
+ {% endfor %}
33
+ };
34
+
35
+ // Tanh LUT (input [-8,8), output [-1,1] quantized to [-32768,32767])
36
+ static const int16_t tanh_lut[256] = {
37
+ {% for val in tanh_lut %}
38
+ {{ val }}{% if not loop.last %},{% endif %}
39
+ {% endfor %}
40
+ };
41
+
42
+ // LUT lookup functions (linear interpolation)
43
+ static inline int16_t sigmoid_lut_lookup(int32_t x) {
44
+ // x is int32 accumulator, map to [-8,8) range based on quantization
45
+ // Assume x is already scaled to [0, 256*8) range
46
+ int32_t idx = (x >> 8) & 0xFF;
47
+ uint8_t frac = (uint8_t)(x & 0xFF);
48
+
49
+ int16_t lower = sigmoid_lut[idx];
50
+ int16_t upper = sigmoid_lut[idx + 1];
51
+
52
+ int32_t result = lower + ((upper - lower) * frac >> 8);
53
+ return (int16_t)result;
54
+ }
55
+
56
+ static inline int16_t tanh_lut_lookup(int32_t x) {
57
+ int32_t idx = (x >> 8) & 0xFF;
58
+ uint8_t frac = (uint8_t)(x & 0xFF);
59
+
60
+ int16_t lower = tanh_lut[idx];
61
+ int16_t upper = tanh_lut[idx + 1];
62
+
63
+ int32_t result = lower + ((upper - lower) * frac >> 8);
64
+ return (int16_t)result;
65
+ }
66
+
67
+ #endif // TINYMLC_LUT_H