mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Added new tests for FLAC encoding and decoding, including handling of rice parameters and partial LPC tail. - Introduced WAV PCM encoding tests to ensure correct behavior across various configurations. - Updated test cases to validate the handling of malformed FLAC files and metadata structures. - Enhanced the APU register tests to include expanded P5 profile capabilities and ensure accurate register descriptions. - Improved assertions for manifest checks in the APU release tests to validate ABI and instruction counts. - Refactored existing tests for clarity and maintainability, ensuring they align with the latest APU specifications.
142 lines
5.1 KiB
Python
142 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the deterministic APU-P5 codec bundle and evidence reports."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT / "scripts"))
|
|
|
|
from apu_mcasm import _artifact_data, assemble # noqa: E402
|
|
from apu_isa import abi_manifest, control_flow_report # noqa: E402
|
|
from apu_p5_coefficients import coefficient_bytes # noqa: E402
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--output-dir", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
output = args.output_dir.resolve()
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
coefficients = coefficient_bytes()
|
|
source = ROOT / "rtl/ip/multimedia/apu_p5_codecs.apus"
|
|
assembly = assemble(source.read_text(encoding="utf-8"), "p5", coefficients)
|
|
bundle_path = output / "apu-p5.apumc"
|
|
coefficient_path = output / "apu-p5-coefficients.bin"
|
|
bundle_path.write_bytes(assembly.bundle)
|
|
coefficient_path.write_bytes(coefficients)
|
|
(output / "symbols.json").write_text(
|
|
json.dumps(assembly.symbols, indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
|
)
|
|
reports = {
|
|
"cfg-report.json": {
|
|
**_artifact_data(assembly),
|
|
"entries": [entry.__dict__ for entry in assembly.entries],
|
|
"control_flow": [
|
|
control_flow_report(
|
|
assembly.instructions,
|
|
entry,
|
|
assembly.target,
|
|
assembly.mc_abi,
|
|
)
|
|
for entry in assembly.entries
|
|
],
|
|
},
|
|
"primitive-manifest.json": {
|
|
"target": "p5",
|
|
"implemented_mask": 0x001FFFFF,
|
|
"required_mask": __import__("functools").reduce(
|
|
int.__or__, (entry.primitive_mask for entry in assembly.entries), 0
|
|
),
|
|
"entry_masks": [entry.primitive_mask for entry in assembly.entries],
|
|
},
|
|
"trace-input.json": {
|
|
"entries": [entry.entry_pc for entry in assembly.entries],
|
|
"instructions": [f"0x{item.encode():016x}" for item in assembly.instructions],
|
|
},
|
|
"abi-input-manifest.json": {
|
|
**_artifact_data(assembly),
|
|
"canonical_abi": abi_manifest(),
|
|
},
|
|
}
|
|
for name, report in reports.items():
|
|
(output / name).write_text(
|
|
json.dumps(report, indent=2, sort_keys=True) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
high_water = {
|
|
"apumc_version": f"0x{assembly.mc_abi:08x}",
|
|
"instruction_words": len(assembly.instructions),
|
|
"maximum_instruction_words": 4096,
|
|
"free_instruction_words": 4096 - len(assembly.instructions),
|
|
"control_store_bytes": len(assembly.instructions) * 8,
|
|
"table_bytes": len(coefficients),
|
|
"maximum_scratch_end": max(
|
|
entry.scratch_base + entry.scratch_bytes for entry in assembly.entries
|
|
),
|
|
"loader_proof_workspace": {
|
|
"pending_record_bits": 64,
|
|
"pending_path_records_v1": 2048,
|
|
"pending_path_records_v2": 4096,
|
|
"pending_storage_bytes_v1": 2048 * 8,
|
|
"pending_storage_bytes_v2": 4096 * 8,
|
|
"memo_entries": 8192,
|
|
"memo_entry_bits": 65,
|
|
"memo_storage_bytes_ceiling": (8192 * 65 + 7) // 8,
|
|
"traversal_limit_v1": 131072,
|
|
"traversal_limit_v2": 262144,
|
|
},
|
|
"entries": [
|
|
{
|
|
"format_id": entry.format_id,
|
|
"first_pc": entry.first_pc,
|
|
"last_pc": entry.last_pc,
|
|
"instruction_span": entry.last_pc - entry.first_pc + 1,
|
|
"scratch_end": entry.scratch_base + entry.scratch_bytes,
|
|
"maximum_loop_count": entry.max_loop_count,
|
|
"maximum_retired": entry.max_retired,
|
|
}
|
|
for entry in assembly.entries
|
|
],
|
|
}
|
|
(output / "high-water.json").write_text(
|
|
json.dumps(high_water, indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
|
)
|
|
(output / "manifest.json").write_text(
|
|
json.dumps(
|
|
{
|
|
**_artifact_data(assembly),
|
|
"target": "p5",
|
|
"coefficient_words": len(coefficients) // 4,
|
|
"entries": [entry.__dict__ for entry in assembly.entries],
|
|
"sha256": {
|
|
"bundle": hashlib.sha256(assembly.bundle).hexdigest(),
|
|
"coefficients": hashlib.sha256(coefficients).hexdigest(),
|
|
"source": hashlib.sha256(source.read_bytes()).hexdigest(),
|
|
"reports": {
|
|
name: hashlib.sha256(
|
|
(output / name).read_bytes()
|
|
).hexdigest()
|
|
for name in reports
|
|
},
|
|
},
|
|
"high_water": high_water,
|
|
},
|
|
indent=2,
|
|
sort_keys=True,
|
|
)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|