mirror of
https://github.com/ratspeak/C6-Reticulum-ASM
synced 2026-08-12 18:07:18 -04:00
Completes the ADR-0004 log primitive set (log_init + log_str shipped
in the previous commit). Each is a leaf or single-call wrapper:
log_hex — width hex digits, MSB first, lowercase a-f
log_u32 — unsigned decimal, no leading zeros, special-case 0
log_bytes — space-separated 2-digit pairs
log_event — <ts8hex>\t<tag>\r\n with the timestamp placeholder
at 0 until clock_get_freq lands; the wire format is
final, only the sampled value will change
_main now calls log_init then log_event("boot\tready") instead
of writing a hard-coded banner. The qemu output is byte-identical
(00000000\tboot\tready\r\n) so test__main.py is unchanged; the
refactor proves the log chain works end-to-end.
108 tests, all green.
59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
"""Tests for src/log/log_hex.S.
|
|
|
|
Static disassembly checks for the prologue/loop/digit-conversion shape.
|
|
Behavioural cover (a known value emits the expected hex chars) lands
|
|
through log_event's integration test, which uses log_hex to format the
|
|
8-digit timestamp.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
import pytest
|
|
|
|
from harness import build
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def artifacts() -> build.BuildArtifacts:
|
|
return build.build("qemu-virt")
|
|
|
|
|
|
def test_function_exists(artifacts: build.BuildArtifacts) -> None:
|
|
assert build.symbol_address(artifacts.elf, "log_hex") > 0
|
|
|
|
|
|
def test_prologue_saves_ra_s0_s1(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_hex")
|
|
head = "\n".join(body.splitlines()[:10])
|
|
assert "addi" in head and "sp" in head and "-16" in head, head
|
|
assert re.search(r"\bsw\b\s+ra", head), head
|
|
|
|
|
|
def test_handles_width_zero_via_head_branch(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_hex")
|
|
# The very first thing after the prologue/save is `beqz s1, …` so width=0
|
|
# exits without emitting anything.
|
|
assert re.search(r"\bbeqz\b\s+s1", body), body
|
|
|
|
|
|
def test_extracts_nibble_via_shift_and_mask(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_hex")
|
|
# srl t1, s0, t0 → srl with t1 dest
|
|
assert re.search(r"\bsrl\b\s+t1,", body), body
|
|
# andi t1, t1, 0xF (assembler emits 15)
|
|
assert re.search(r"\bandi\b\s+t1,\s*t1,\s*15\b", body), body
|
|
|
|
|
|
def test_digit_branch_for_a_through_f(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_hex")
|
|
# blt t1, t2 splits 0..9 (add 48 = '0') from a..f (add 87 = 'a' - 10)
|
|
assert "li\tt2,10" in body or re.search(r"\bli\b\s+t2,\s*10\b", body), body
|
|
assert "48" in body, body
|
|
assert "87" in body, body
|
|
|
|
|
|
def test_calls_uart_tx_byte_per_digit(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_hex")
|
|
assert "uart_tx_byte" in body, body
|