mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: update APU register testbench and add codec transport tests
- 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.
This commit is contained in:
59 files changed
+7854
-704
No files matched your search
@@ -0,0 +1,133 @@
|
||||
#!/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())
|
||||
Reference in new issue
Block a user