Files
cpu-miner/.codex/skills/python-to-c-efficiency/scripts/scaffold_c_module.py

202 lines
4.6 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Generate a performance-oriented C module skeleton.
Creates:
- include/<name>.h
- src/<name>.c
- tests/test_<name>.c
- bench/bench_<name>.c
"""
from __future__ import annotations
import argparse
import re
from pathlib import Path
def normalize_name(raw: str) -> str:
name = raw.strip().lower().replace("-", "_")
name = re.sub(r"[^a-z0-9_]", "_", name)
name = re.sub(r"_+", "_", name).strip("_")
if not name:
raise ValueError("module name is empty after normalization")
if name[0].isdigit():
name = f"m_{name}"
return name
def write_file(path: Path, content: str, force: bool) -> None:
if path.exists() and not force:
raise FileExistsError(f"file exists: {path}")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
def render_header(module: str) -> str:
guard = f"{module.upper()}_H"
return f"""#ifndef {guard}
#define {guard}
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {{
#endif
typedef enum {{
{module}_ok = 0,
{module}_err_null = 1,
{module}_err_size = 2
}} {module}_status_t;
{module}_status_t {module}_process_f32(
const float *restrict in,
float *restrict out,
size_t n);
#ifdef __cplusplus
}}
#endif
#endif
"""
def render_source(module: str) -> str:
return f"""#include "{module}.h"
{module}_status_t {module}_process_f32(
const float *restrict in,
float *restrict out,
size_t n)
{{
if (in == NULL || out == NULL) {{
return {module}_err_null;
}}
if (n == 0) {{
return {module}_err_size;
}}
for (size_t i = 0; i < n; ++i) {{
out[i] = in[i] * 1.0f;
}}
return {module}_ok;
}}
"""
def render_test(module: str) -> str:
return f"""#include <assert.h>
#include <stdio.h>
#include "{module}.h"
int main(void)
{{
float in[4] = {{1.0f, 2.0f, 3.0f, 4.0f}};
float out[4] = {{0.0f, 0.0f, 0.0f, 0.0f}};
{module}_status_t st = {module}_process_f32(in, out, 4);
assert(st == {module}_ok);
for (size_t i = 0; i < 4; ++i) {{
assert(out[i] == in[i]);
}}
printf("test_{module}: ok\\n");
return 0;
}}
"""
def render_bench(module: str) -> str:
return f"""#define _POSIX_C_SOURCE 200809L
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "{module}.h"
static uint64_t ns_now(void)
{{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec;
}}
int main(void)
{{
const size_t n = 1u << 20;
float *in = (float *)malloc(n * sizeof(float));
float *out = (float *)malloc(n * sizeof(float));
if (!in || !out) {{
fprintf(stderr, "alloc failed\\n");
free(in);
free(out);
return 1;
}}
for (size_t i = 0; i < n; ++i) {{
in[i] = (float)(i & 1023u);
}}
uint64_t t0 = ns_now();
{module}_status_t st = {module}_process_f32(in, out, n);
uint64_t t1 = ns_now();
if (st != {module}_ok) {{
fprintf(stderr, "kernel error: %d\\n", (int)st);
free(in);
free(out);
return 1;
}}
double ns_per_elem = (double)(t1 - t0) / (double)n;
printf("{module} ns/elem: %.3f\\n", ns_per_elem);
free(in);
free(out);
return 0;
}}
"""
def main() -> int:
parser = argparse.ArgumentParser(description="Scaffold a C module with tests and bench")
parser.add_argument("--name", required=True, help="Module name (snake_case preferred)")
parser.add_argument(
"--out-dir",
default=".",
help="Project root where include/src/tests/bench live",
)
parser.add_argument("--force", action="store_true", help="Overwrite existing files")
args = parser.parse_args()
module = normalize_name(args.name)
root = Path(args.out_dir).resolve()
write_file(root / "include" / f"{module}.h", render_header(module), args.force)
write_file(root / "src" / f"{module}.c", render_source(module), args.force)
write_file(root / "tests" / f"test_{module}.c", render_test(module), args.force)
write_file(root / "bench" / f"bench_{module}.c", render_bench(module), args.force)
print(f"created module skeleton: {module}")
print(f"root: {root}")
print("next:")
print(
f" gcc -O0 -g3 -fsanitize=address,undefined "
f"-Iinclude src/{module}.c tests/test_{module}.c -o test_{module}"
)
print(
f" gcc -O3 -march=native "
f"-Iinclude src/{module}.c bench/bench_{module}.c -o bench_{module}"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())