File size: 2,457 Bytes
9b8659b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""Generate DROM fixed-point math lookup tables (`graphcalc_tables.h`) and bignum print sleds (`sled.S`)."""
import math
import sys
from pathlib import Path


def write_tables(hdr_path: Path) -> None:
    one32 = 1 << 32
    lines = [
        "// Auto-generated Q32.32 constants and CORDIC / log tables in DROM (.rodata).",
        "#pragma once",
        "#include <stdint.h>",
        "",
        f"#define Q32_ONE ({one32}LL)",
        f"#define Q32_PI ({round(math.pi * one32)}LL)",
        f"#define Q32_TWO_PI ({round(2.0 * math.pi * one32)}LL)",
        f"#define Q32_INV_TWO_PI ({round((1.0 / (2.0 * math.pi)) * one32)}LL)",
        f"#define Q32_HALF_PI ({round(0.5 * math.pi * one32)}LL)",
        f"#define Q32_E ({round(math.e * one32)}LL)",
        f"#define Q32_LN2 ({round(math.log(2.0) * one32)}LL)",
        f"#define Q32_INV_LN2 ({round((1.0 / math.log(2.0)) * one32)}LL)",
        f"#define Q32_LN10 ({round(math.log(10.0) * one32)}LL)",
        "",
    ]
    # CORDIC gain K = prod_{i=0}^{29} 1 / sqrt(1 + 2^{-2i})
    k_gain = 1.0
    atan_vals = []
    for i in range(30):
        k_gain /= math.hypot(1.0, 2.0 ** (-i))
        atan_vals.append(round(math.atan(2.0 ** (-i)) * one32))
    lines.append(f"#define CORDIC_K ({round(k_gain * one32)}LL)")
    lines.append("static const int64_t CORDIC_ATAN[30] = {")
    for i in range(0, 30, 5):
        chunk = ", ".join(f"{v}LL" for v in atan_vals[i : i + 5])
        lines.append(f"    {chunk},")
    lines.append("};\n")

    # Shifted log table: ln(1 + 2^{-i}) for i = 1..30 in Q32.32
    ln1p_vals = [0] + [round(math.log1p(2.0 ** (-i)) * one32) for i in range(1, 31)]
    lines.append("static const int64_t LN1P_POW2[31] = {")
    for i in range(0, 31, 5):
        chunk = ", ".join(f"{v}LL" for v in ln1p_vals[i : i + 5])
        lines.append(f"    {chunk},")
    lines.append("};\n")

    hdr_path.write_text("\n".join(lines), encoding="utf-8")


def write_sled(sled_path: Path) -> None:
    out = ["    .section .text", "    .globl bn_sleds"]
    for r in range(8):
        out += [f"bn_sled{r}:"] + [f"    .insn i 0x2B, 0, x{r}, x0, {k}" for k in range(127, -1, -1)]
        out += ["    ret"]
    out += ["    .section .rodata", "    .align 2", "bn_sleds:"]
    out += [f"    .word bn_sled{r}" for r in range(8)]
    sled_path.write_text("\n".join(out) + "\n", encoding="utf-8")


if __name__ == "__main__":
    write_tables(Path(sys.argv[1]))
    write_sled(Path(sys.argv[2]))