mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Modified the capability register value in apu_reg_tb.sv to 0x01bd. - Simplified rejected write checks for the COMMAND register in apu_reg_tb.sv. - Added backend build ID input to the ring scheduler testbench. - Updated test cases in test_apu.py to include new codec transport and controller files. - Created new test file test_apu_codec_transport.py for APU-P5 transport assembler and parser tests. - Added codec profile and dependency tests in test_apu_codecs.py. - Enhanced register parity tests to include P5 primitive mask. - Improved script tools tests for file download functionality and dependency helpers.
134 lines
4.5 KiB
Python
134 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate the frozen APU-P5 32-phase, 16-tap Q2.30 coefficient banks."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import struct
|
|
from decimal import Decimal, ROUND_HALF_EVEN, localcontext
|
|
from pathlib import Path
|
|
|
|
|
|
def _pi(precision: int) -> Decimal:
|
|
with localcontext() as context:
|
|
context.prec = precision + 16
|
|
multiplier = Decimal(1)
|
|
linear = Decimal(13591409)
|
|
exponent = Decimal(1)
|
|
total = linear
|
|
k_value = Decimal(6)
|
|
terms = precision // 14 + 3
|
|
for index in range(1, terms):
|
|
divisor = Decimal(index) ** 3
|
|
multiplier = multiplier * (k_value**3 - Decimal(16) * k_value) / divisor
|
|
linear += Decimal(545140134)
|
|
exponent *= Decimal(-262537412640768000)
|
|
total += multiplier * linear / exponent
|
|
k_value += Decimal(12)
|
|
value = Decimal(426880) * Decimal(10005).sqrt() / total
|
|
context.prec = precision
|
|
return +value
|
|
|
|
|
|
def _sin(value: Decimal, pi_value: Decimal, precision: int) -> Decimal:
|
|
with localcontext() as context:
|
|
context.prec = precision + 12
|
|
period = Decimal(2) * pi_value
|
|
value %= period
|
|
if value > pi_value:
|
|
value -= period
|
|
term = value
|
|
total = value
|
|
index = 1
|
|
threshold = Decimal(10) ** Decimal(-(precision + 4))
|
|
while abs(term) > threshold:
|
|
term *= -(value * value) / Decimal((2 * index) * (2 * index + 1))
|
|
total += term
|
|
index += 1
|
|
context.prec = precision
|
|
return +total
|
|
|
|
|
|
def _cos(value: Decimal, pi_value: Decimal, precision: int) -> Decimal:
|
|
return _sin(value + pi_value / Decimal(2), pi_value, precision)
|
|
|
|
|
|
def coefficient_words(precision: int = 112) -> list[int]:
|
|
with localcontext() as context:
|
|
context.prec = precision
|
|
pi_value = _pi(precision)
|
|
banks = (Decimal(1), Decimal(2) / Decimal(3), Decimal(1) / Decimal(2))
|
|
words: list[int] = []
|
|
for cutoff in banks:
|
|
for phase in range(32):
|
|
amplitudes: list[Decimal] = []
|
|
for tap in range(16):
|
|
x_value = Decimal(tap - 7) - Decimal(phase) / Decimal(32)
|
|
argument = cutoff * x_value
|
|
sinc = (
|
|
Decimal(1)
|
|
if argument == 0
|
|
else _sin(pi_value * argument, pi_value, precision) /
|
|
(pi_value * argument)
|
|
)
|
|
window = (
|
|
Decimal(1) -
|
|
_cos(
|
|
Decimal(2) * pi_value * (Decimal(tap) + Decimal("0.5")) /
|
|
Decimal(16),
|
|
pi_value,
|
|
precision,
|
|
)
|
|
) / Decimal(2)
|
|
amplitudes.append(cutoff * sinc * window)
|
|
scale = sum(amplitudes)
|
|
phase_words = [
|
|
int((Decimal(1 << 30) * value / scale).to_integral_value(
|
|
rounding=ROUND_HALF_EVEN
|
|
))
|
|
for value in amplitudes
|
|
]
|
|
phase_words[7] += (1 << 30) - sum(phase_words)
|
|
words.extend(phase_words)
|
|
return words
|
|
|
|
|
|
def coefficient_bytes() -> bytes:
|
|
first = coefficient_words(112)
|
|
independent = coefficient_words(160)
|
|
if first != independent:
|
|
raise RuntimeError("coefficient rounding did not converge across precision bounds")
|
|
return b"".join(struct.pack("<i", word) for word in first)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--manifest", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
payload = coefficient_bytes()
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_bytes(payload)
|
|
args.manifest.write_text(
|
|
json.dumps(
|
|
{
|
|
"banks": 3,
|
|
"phases": 32,
|
|
"taps": 16,
|
|
"words": len(payload) // 4,
|
|
"bytes": len(payload),
|
|
"sha256": hashlib.sha256(payload).hexdigest(),
|
|
},
|
|
indent=2,
|
|
sort_keys=True,
|
|
) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|