summaryrefslogtreecommitdiffstats
path: root/scripts/gen_flat.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gen_flat.py')
-rw-r--r--scripts/gen_flat.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/scripts/gen_flat.py b/scripts/gen_flat.py
new file mode 100644
index 0000000..c659432
--- /dev/null
+++ b/scripts/gen_flat.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+"""Generate flat-array C wrappers for all ts functions.
+
+Each wrapper takes flat input/output arrays instead of pointer-of-pointers,
+eliminating ctypes pointer marshaling overhead.
+"""
+
+import argparse
+import importlib.util
+import os
+import sys
+
+_spec = importlib.util.spec_from_file_location(
+ "ts_parser",
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "ts_parser.py"),
+)
+if _spec and _spec.loader:
+ _ts_parser = importlib.util.module_from_spec(_spec)
+ _spec.loader.exec_module(_ts_parser)
+ parse_all = _ts_parser.parse_all
+else:
+ print("Error: could not load ts_parser", file=sys.stderr)
+ sys.exit(1)
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+OUT = os.path.join(ROOT, "lib", "ts_flat_generated.c")
+
+
+def generate_wrappers(funcs, dry_run=False):
+ """Generate flat-array C wrapper functions."""
+ if dry_run:
+ print(f"[dry-run] Would generate {len(funcs)} flat wrappers -> {OUT}")
+ return
+
+ with open(OUT, "w", encoding="utf-8") as f:
+ f.write("/* Auto-generated flat-array wrappers. Do not edit. */\n\n")
+ f.write("#include <string.h>\n")
+ f.write('#include "ts.h"\n\n')
+
+ for fm in funcs:
+ safe_x_n = max(fm.x_n, 1)
+ safe_y_n = max(fm.y_n, 1)
+
+ f.write(f"/* {fm.name}: x_n={fm.x_n}, y_n={fm.y_n}, c_n={fm.c_n} */\n")
+ f.write(f"int ts_{fm.name}_flat(\n")
+
+ for i in range(fm.y_n):
+ f.write(f" fp_t *y{i},\n")
+
+ for i in range(fm.x_n):
+ f.write(f" fp_t const *x{i},\n")
+
+ f.write(f" uint_t n,\n")
+ f.write(f" ts_constant_t const *params\n")
+ f.write(f")\n{{\n")
+
+ f.write(f" fp_t * const _y[{safe_y_n}] = {{")
+ f.write(", ".join(f"y{i}" for i in range(fm.y_n)))
+ f.write("};\n")
+
+ f.write(f" fp_t const * const _x[{safe_x_n}] = {{")
+ f.write(", ".join(f"x{i}" for i in range(fm.x_n)))
+ f.write("};\n")
+
+ for i in range(fm.y_n):
+ f.write(f" memset(y{i}, 0, n * sizeof(fp_t));\n")
+
+ f.write(
+ f" return ts_{fm.name}(_y, {fm.y_n}, _x, {fm.x_n}, n, params);\n"
+ )
+ f.write("}\n\n")
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Generate flat-array C wrappers")
+ parser.add_argument(
+ "--dry-run",
+ action="store_true",
+ help="Print what would be generated without writing",
+ )
+ args = parser.parse_args()
+
+ funcs = parse_all(detect_x_access=True)
+
+ if not funcs:
+ print("Warning: no ts_parameter declarations found.", file=sys.stderr)
+ sys.exit(1)
+
+ generate_wrappers(funcs, dry_run=args.dry_run)
+
+ if not args.dry_run:
+ print(f"Generated {len(funcs)} flat wrappers -> {OUT}")
+
+
+if __name__ == "__main__":
+ main()