Files
retroSoC/tests/test_jpeg.py
T
maksyuki 9c706ba0ff feat: refactor test scripts to update paths and improve organization
- Updated paths in test files to reflect new directory structure for RTL and script files.
- Changed references from rtl/mini to rtl/ip and scripts/rtl where applicable.
- Added a new test file for Tiny product isolation, ensuring independent ABI and bus acceptance.
- Enhanced tests for memory map generation and protocol contracts for Tiny architecture.
- Ensured that all tests are aligned with the latest directory structure and naming conventions.
2026-09-25 15:44:02 +08:00

970 lines
33 KiB
Python

"""Directed RTL tests for the JPEG accelerator."""
from __future__ import annotations
import re
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def _write_hex_bytes(path: Path, data: bytes) -> None:
path.write_text("".join(f"{value:02x}\n" for value in data), encoding="ascii")
def _write_hex_words(path: Path, data: list[int]) -> None:
path.write_text("".join(f"{value:08x}\n" for value in data), encoding="ascii")
def test_jpeg_forward_inverse_transform(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_transform_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_transform_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_transform.sv"),
str(ROOT / "tests/rtl/jpeg_transform_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG transform tests passed" in result.stdout
def test_jpeg_quantize_dequantize(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_quantizer_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_quantizer_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv"),
str(ROOT / "tests/rtl/jpeg_quantizer_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG quantizer tests passed" in result.stdout
def test_jpeg_coefficient_engine(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_coefficient_engine_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_coefficient_engine_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_transform.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_coefficient_engine.sv"),
str(ROOT / "tests/rtl/jpeg_coefficient_engine_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG coefficient engine test passed" in result.stdout
def test_jpeg_entropy_encoder(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_entropy_encoder_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_entropy_encoder_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_entropy_encoder.sv"),
str(ROOT / "tests/rtl/jpeg_entropy_encoder_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG entropy encoder tests passed" in result.stdout
def test_jpeg_bit_packer_and_stuffing(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_bit_packer_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_bit_packer_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_bit_packer.sv"),
str(ROOT / "tests/rtl/jpeg_bit_packer_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG bit packer tests passed" in result.stdout
def test_jpeg_apb_register_path(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_reg.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/ip/multimedia'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_reg.sv"),
str(ROOT / "tests/rtl/jpeg_reg_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_reg_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_reg_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_reg_tb", "-o", str(simulation), str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG APB register tests passed" in result.stdout
def test_jpeg_2d_axi_dma(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_dma.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl/interface'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/peripheral/dma_axi4_master.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_dma.sv"),
str(ROOT / "tests/rtl/jpeg_dma_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_dma_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_dma_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_dma_tb", "-o", str(simulation), str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG DMA tests passed" in result.stdout
def test_jpeg_apb_ring_descriptor_path(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
multimedia = ROOT / "rtl/ip/multimedia"
source_list = tmp_path / "apb4_jpeg_ring.fl"
modules = [
"jpeg_pkg.sv",
"jpeg_transform.sv",
"jpeg_quantizer.sv",
"jpeg_coefficient_engine.sv",
"jpeg_entropy_encoder.sv",
"jpeg_entropy_decoder.sv",
"jpeg_bit_packer.sv",
"jpeg_bit_reader.sv",
"jpeg_byte_unpacker.sv",
"jpeg_byte_joiner.sv",
"jpeg_header_writer.sv",
"jpeg_marker_parser.sv",
"jpeg_table_store.sv",
"jpeg_table_cache.sv",
"jpeg_table_register_bank.sv",
"jpeg_block_encoder.sv",
"jpeg_block_decoder.sv",
"jpeg_mcu_builder.sv",
"jpeg_mcu_reconstructor.sv",
"jpeg_encode_core.sv",
"jpeg_decode_core.sv",
"jpeg_dma.sv",
"jpeg_reg.sv",
"apb4_jpeg.sv",
]
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl/interface'}",
f"+incdir+{multimedia}",
"+define+SV_ASSRT_DISABLE",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/spill_register.sv"),
str(ROOT / "rtl/tech/tc_sram.sv"),
str(ROOT / "rtl/ip/peripheral/dma_axi4_master.sv"),
*(str(multimedia / module) for module in modules),
str(ROOT / "tests/rtl/apb4_jpeg_ring_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "apb4_jpeg_ring_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "apb4_jpeg_ring_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-DPDK_BEHAV",
"-s",
"apb4_jpeg_ring_tb",
"-o",
str(simulation),
str(converted),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG APB ring tests passed" in result.stdout
def test_jpeg_table_store(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_table_store_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-DPDK_BEHAV",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_table_store_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/tech/tc_sram.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_table_store.sv"),
str(ROOT / "tests/rtl/jpeg_table_store_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG table store tests passed" in result.stdout
def test_jpeg_entropy_decoder(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_entropy_decoder_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_entropy_decoder_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_entropy_decoder.sv"),
str(ROOT / "tests/rtl/jpeg_entropy_decoder_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG entropy decoder tests passed" in result.stdout
def test_jpeg_byte_unpacker_and_bit_reader(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_bit_reader.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_byte_unpacker.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_bit_reader.sv"),
str(ROOT / "tests/rtl/jpeg_bit_reader_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_bit_reader_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_bit_reader_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_bit_reader_tb", "-o", str(simulation),
str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG byte unpacker and bit reader tests passed" in result.stdout
def test_jpeg_marker_parser(tmp_path: Path) -> None:
from jpeg_reference import (
AC_CHROMA_BITS,
AC_CHROMA_VALUES,
AC_LUMA_BITS,
AC_LUMA_VALUES,
DC_CHROMA_BITS,
DC_LUMA_BITS,
DC_VALUES,
Sampling,
_huffman_codes,
encode_rgb,
scaled_quant_table,
LUMA_QUANT,
CHROMA_QUANT,
)
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
encoded = encode_rgb(
bytes((index * 13) & 0xFF for index in range(17 * 15 * 3)),
17,
15,
quality=75,
sampling=Sampling.YUV420,
restart_interval=1,
)
hex_path = tmp_path / "jpeg_input.hex"
tables_path = tmp_path / "jpeg_tables.hex"
_write_hex_bytes(hex_path, encoded)
expected_tables = [0] * 3072
luma_quant = scaled_quant_table(LUMA_QUANT, 75)
chroma_quant = scaled_quant_table(CHROMA_QUANT, 75)
for index, value in enumerate(luma_quant):
expected_tables[index] = value
for index, value in enumerate(chroma_quant):
expected_tables[256 + index] = value
table_specs = (
(4, DC_LUMA_BITS, DC_VALUES),
(5, DC_CHROMA_BITS, DC_VALUES),
(8, AC_LUMA_BITS, AC_LUMA_VALUES),
(9, AC_CHROMA_BITS, AC_CHROMA_VALUES),
)
for kind, bits, values in table_specs:
for symbol, (code, length) in _huffman_codes(bits, values).items():
expected_tables[(kind * 256) + symbol] = (length << 16) | code
_write_hex_words(tables_path, expected_tables)
simulation = tmp_path / "jpeg_marker_parser_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_marker_parser_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_marker_parser.sv"),
str(ROOT / "tests/rtl/jpeg_marker_parser_tb.sv"),
],
check=True,
)
result = subprocess.run(
[vvp, str(simulation), f"+jpeg_hex={hex_path}", f"+tables_hex={tables_path}",
f"+jpeg_size={len(encoded)}"],
text=True,
capture_output=True,
check=True,
)
assert "JPEG marker parser tests passed" in result.stdout
def test_jpeg_block_decoder_pipeline(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_block_decoder_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_block_decoder_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_entropy_decoder.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_transform.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_block_decoder.sv"),
str(ROOT / "tests/rtl/jpeg_block_decoder_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG block decoder tests passed" in result.stdout
def test_jpeg_block_encoder_pipeline(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
simulation = tmp_path / "jpeg_block_encoder_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_block_encoder_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_transform.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_entropy_encoder.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_block_encoder.sv"),
str(ROOT / "tests/rtl/jpeg_block_encoder_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG block encoder tests passed" in result.stdout
def test_jpeg_mcu_reconstructor(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_mcu_reconstructor.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
"+define+SV_ASSRT_DISABLE",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_mcu_reconstructor.sv"),
str(ROOT / "tests/rtl/jpeg_mcu_reconstructor_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_mcu_reconstructor_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_mcu_reconstructor_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-s",
"jpeg_mcu_reconstructor_tb",
"-o",
str(simulation),
str(converted),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG MCU reconstructor tests passed" in result.stdout
def test_jpeg_mcu_builder(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_mcu_builder.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/tech/tc_sram.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_mcu_builder.sv"),
str(ROOT / "tests/rtl/jpeg_mcu_builder_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_mcu_builder_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_mcu_builder_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-s",
"jpeg_mcu_builder_tb",
"-o",
str(simulation),
str(converted),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG MCU builder tests passed" in result.stdout
def test_jpeg_header_writer(tmp_path: Path) -> None:
from jpeg_reference import (
CHROMA_QUANT,
LUMA_QUANT,
Sampling,
_parse_header,
encode_rgb,
scaled_quant_table,
)
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
encoded = encode_rgb(
bytes((index * 13) & 0xFF for index in range(17 * 15 * 3)),
17,
15,
quality=75,
sampling=Sampling.YUV420,
restart_interval=1,
)
header = encoded[: _parse_header(encoded).entropy_offset]
luma = scaled_quant_table(LUMA_QUANT, 75)
chroma = scaled_quant_table(CHROMA_QUANT, 75)
header_path = tmp_path / "header.hex"
luma_path = tmp_path / "luma.hex"
chroma_path = tmp_path / "chroma.hex"
_write_hex_bytes(header_path, header)
_write_hex_bytes(luma_path, bytes(luma))
_write_hex_bytes(chroma_path, bytes(chroma))
simulation = tmp_path / "jpeg_header_writer_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-DSV_ASSRT_DISABLE",
"-I",
str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-s",
"jpeg_header_writer_tb",
"-o",
str(simulation),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_header_writer.sv"),
str(ROOT / "tests/rtl/jpeg_header_writer_tb.sv"),
],
check=True,
)
result = subprocess.run(
[
vvp,
str(simulation),
f"+header_hex={header_path}",
f"+luma_hex={luma_path}",
f"+chroma_hex={chroma_path}",
f"+header_size={len(header)}",
],
text=True,
capture_output=True,
check=True,
)
assert "JPEG header writer tests passed" in result.stdout
def test_jpeg_byte_joiner(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
source_list = tmp_path / "jpeg_byte_joiner.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_byte_joiner.sv"),
str(ROOT / "tests/rtl/jpeg_byte_joiner_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_byte_joiner_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "scripts/rtl/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "jpeg_byte_joiner_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_byte_joiner_tb", "-o", str(simulation),
str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "JPEG byte joiner tests passed" in result.stdout
def test_jpeg_encode_core_complete_file(tmp_path: Path) -> None:
from jpeg_reference import (
AC_CHROMA_BITS,
AC_CHROMA_VALUES,
AC_LUMA_BITS,
AC_LUMA_VALUES,
CHROMA_QUANT,
DC_CHROMA_BITS,
DC_LUMA_BITS,
DC_VALUES,
LUMA_QUANT,
Sampling,
_huffman_codes,
encode_rgb,
scaled_quant_table,
)
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
def entries(bits: tuple[int, ...], values: tuple[int, ...], size: int) -> list[int]:
codes = _huffman_codes(bits, values)
return [((codes[symbol][1] << 16) | codes[symbol][0]) if symbol in codes else 0
for symbol in range(size)]
rgb = bytes([128] * (16 * 16 * 3))
expected = encode_rgb(rgb, 16, 16, quality=75, sampling=Sampling.YUV420)
files = {
"expected": tmp_path / "expected.hex",
"luma_quant": tmp_path / "luma_quant.hex",
"chroma_quant": tmp_path / "chroma_quant.hex",
"luma_dc": tmp_path / "luma_dc.hex",
"chroma_dc": tmp_path / "chroma_dc.hex",
"luma_ac": tmp_path / "luma_ac.hex",
"chroma_ac": tmp_path / "chroma_ac.hex",
}
_write_hex_bytes(files["expected"], expected)
_write_hex_bytes(files["luma_quant"], bytes(scaled_quant_table(LUMA_QUANT, 75)))
_write_hex_bytes(files["chroma_quant"], bytes(scaled_quant_table(CHROMA_QUANT, 75)))
_write_hex_words(files["luma_dc"], entries(DC_LUMA_BITS, DC_VALUES, 12))
_write_hex_words(files["chroma_dc"], entries(DC_CHROMA_BITS, DC_VALUES, 12))
_write_hex_words(files["luma_ac"], entries(AC_LUMA_BITS, AC_LUMA_VALUES, 256))
_write_hex_words(files["chroma_ac"], entries(AC_CHROMA_BITS, AC_CHROMA_VALUES, 256))
source_list = tmp_path / "jpeg_encode_core.fl"
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
"+define+SV_ASSRT_DISABLE",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/spill_register.sv"),
str(ROOT / "rtl/tech/tc_sram.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_transform.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_coefficient_engine.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_entropy_encoder.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_block_encoder.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_bit_packer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_header_writer.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_mcu_builder.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_byte_joiner.sv"),
str(ROOT / "rtl/ip/multimedia/jpeg_encode_core.sv"),
str(ROOT / "tests/rtl/jpeg_encode_core_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_encode_core_tb.v"
subprocess.run(
[sys.executable, str(ROOT / "scripts/rtl/convt_sv2v.py"), "-f", str(source_list),
"--output", str(converted)],
check=True,
)
simulation = tmp_path / "jpeg_encode_core_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_encode_core_tb", "-o", str(simulation),
str(converted)],
check=True,
)
plusargs = [f"+{name}_hex={path}" for name, path in files.items()]
result = subprocess.run(
[vvp, str(simulation), *plusargs, f"+expected_size={len(expected)}"],
text=True,
capture_output=True,
check=True,
)
assert "JPEG encode core tests passed" in result.stdout
baseline_match = re.search(r"cycles=(\d+)", result.stdout)
assert baseline_match is not None
baseline_cycles = int(baseline_match.group(1))
benchmark_rgb = bytes([128] * (16 * 32 * 3))
benchmark = encode_rgb(benchmark_rgb, 16, 32, quality=75, sampling=Sampling.YUV420)
_write_hex_bytes(files["expected"], benchmark)
result = subprocess.run(
[
vvp,
str(simulation),
*plusargs,
f"+expected_size={len(benchmark)}",
"+test_width=16",
"+test_height=32",
"+input_beats=192",
],
text=True,
capture_output=True,
check=True,
)
match = re.search(r"cycles=(\d+)", result.stdout)
assert match is not None
benchmark_cycles = int(match.group(1))
assert baseline_cycles < benchmark_cycles
assert benchmark_cycles - baseline_cycles <= 550
def test_jpeg_decode_core_complete_file(tmp_path: Path) -> None:
from jpeg_reference import Sampling, decode_rgb, encode_rgb
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
sv2v = shutil.which("sv2v")
if iverilog is None or vvp is None or sv2v is None:
return
rgb = bytes([128] * (16 * 16 * 3))
encoded = encode_rgb(rgb, 16, 16, quality=75, sampling=Sampling.YUV420)
expected = decode_rgb(encoded).rgb
input_path = tmp_path / "input.hex"
expected_path = tmp_path / "expected_rgb.hex"
_write_hex_bytes(input_path, encoded)
_write_hex_bytes(expected_path, expected)
source_list = tmp_path / "jpeg_decode_core.fl"
sources = [
ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv",
ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv",
ROOT / "rtl/tech/tc_sram.sv",
ROOT / "rtl/ip/multimedia/jpeg_byte_unpacker.sv",
ROOT / "rtl/ip/multimedia/jpeg_marker_parser.sv",
ROOT / "rtl/ip/multimedia/jpeg_table_store.sv",
ROOT / "rtl/ip/multimedia/jpeg_table_cache.sv",
ROOT / "rtl/ip/multimedia/jpeg_table_register_bank.sv",
ROOT / "rtl/ip/multimedia/jpeg_bit_reader.sv",
ROOT / "rtl/ip/multimedia/jpeg_entropy_decoder.sv",
ROOT / "rtl/ip/multimedia/jpeg_quantizer.sv",
ROOT / "rtl/ip/multimedia/jpeg_transform.sv",
ROOT / "rtl/ip/multimedia/jpeg_coefficient_engine.sv",
ROOT / "rtl/ip/multimedia/jpeg_block_decoder.sv",
ROOT / "rtl/ip/multimedia/jpeg_mcu_reconstructor.sv",
ROOT / "rtl/ip/multimedia/jpeg_decode_core.sv",
ROOT / "tests/rtl/jpeg_decode_core_tb.sv",
]
source_list.write_text(
"\n".join(
[
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
"+define+PDK_BEHAV",
"+define+SV_ASSRT_DISABLE",
*(str(source) for source in sources),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "jpeg_decode_core_tb.v"
subprocess.run(
[sys.executable, str(ROOT / "scripts/rtl/convt_sv2v.py"), "-f", str(source_list),
"--output", str(converted)],
check=True,
)
simulation = tmp_path / "jpeg_decode_core_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "jpeg_decode_core_tb", "-o", str(simulation),
str(converted)],
check=True,
)
result = subprocess.run(
[
vvp,
str(simulation),
f"+input_hex={input_path}",
f"+input_size={len(encoded)}",
f"+expected_rgb_hex={expected_path}",
f"+expected_rgb_size={len(expected)}",
],
text=True,
capture_output=True,
check=True,
)
assert "JPEG decode core tests passed" in result.stdout