1
0

DTC and SCI improvements

This commit is contained in:
Aiden
2026-05-25 14:22:32 +10:00
parent 62d1c3c876
commit 80819448cf
21 changed files with 13823 additions and 86 deletions

122
tests/test_sci_inference.py Normal file
View File

@@ -0,0 +1,122 @@
import json
import tempfile
import unittest
from pathlib import Path
from h8536.model import Instruction
from h8536.render import format_listing, write_json
from h8536.rom import Rom
from h8536.sci import analyze_sci, sci_comment_for_instruction
def sci1_setup(scr: int = 0x3C) -> dict[int, Instruction]:
return {
0x1000: Instruction(
0x1000,
bytes.fromhex("15FED80624"),
"MOV:G.B",
"#H'24, @SCI1_SMR",
references=[0xFED8],
comment="SCI1_SMR = H'24",
),
0x1005: Instruction(
0x1005,
bytes([0x15, 0xFE, 0xDA, 0x06, scr]),
"MOV:G.B",
f"#H'{scr:02X}, @SCI1_SCR",
references=[0xFEDA],
comment=f"SCI1_SCR = H'{scr:02X}",
),
0x100A: Instruction(
0x100A,
bytes.fromhex("15FED90607"),
"MOV:G.B",
"#H'07, @SCI1_BRR",
references=[0xFED9],
comment="SCI1_BRR = H'07",
),
}
class SciInferenceTest(unittest.TestCase):
def test_async_internal_baud_uses_manual_brr_formula(self):
analysis = analyze_sci(sci1_setup(), clock_hz=16_000_000)
config = analysis["channels"]["SCI1"]["configurations"][0]
self.assertEqual(config["mode"], "async")
self.assertEqual(config["cks_n"], 0)
self.assertEqual(config["brr"], 7)
self.assertEqual(config["baud_bps"], 31_250)
self.assertEqual(config["formula"], "B = clock_hz / (64 * 2^(2n) * (N + 1))")
self.assertIn("SCI1 async 8-bit even parity 1 stop baud 31250 bps", config["comment"])
def test_missing_clock_keeps_baud_partial(self):
analysis = analyze_sci(sci1_setup(), clock_hz=None)
comment = sci_comment_for_instruction(analysis, 0x100A)
config = analysis["channels"]["SCI1"]["configurations"][0]
self.assertIsNone(config["baud_bps"])
self.assertEqual(config["reason"], "clock_hz_missing")
self.assertIn("baud needs --clock-hz", comment)
self.assertNotIn("31250 bps", comment)
def test_external_clock_selection_suppresses_internal_baud(self):
analysis = analyze_sci(sci1_setup(scr=0x3E), clock_hz=16_000_000)
config = analysis["channels"]["SCI1"]["configurations"][0]
self.assertIsNone(config["baud_bps"])
self.assertEqual(config["clock_source"], "external")
self.assertEqual(config["reason"], "external_clock_selected")
self.assertIn("external clock selected", config["comment"])
def test_scr_bit_writes_are_tracked_without_repeating_same_baud(self):
instructions = sci1_setup()
instructions[0x1010] = Instruction(
0x1010,
bytes.fromhex("15FEDAC7"),
"BSET.B",
"#7, @SCI1_SCR",
references=[0xFEDA],
comment="set TIE (bit 7) of SCI1_SCR",
)
analysis = analyze_sci(instructions, clock_hz=16_000_000)
writes = analysis["channels"]["SCI1"]["writes"]
self.assertEqual([write["register"] for write in writes], ["SMR", "SCR", "BRR", "SCR"])
self.assertEqual(writes[-1]["value"], 0xBC)
self.assertNotIn(0x1010, analysis["annotations"])
def test_listing_preserves_existing_comment_and_appends_sci_comment(self):
instructions = sci1_setup()
analysis = analyze_sci(instructions, clock_hz=16_000_000)
listing = format_listing(
Path("rom.bin"),
Rom(b"\xFF" * 0x20),
instructions,
{},
{},
"min",
traced=False,
sci_analysis=analysis,
)
self.assertIn("SCI1_BRR = H'07; SCI1 async 8-bit even parity 1 stop baud 31250 bps", listing)
def test_json_includes_top_level_and_instruction_sci_metadata(self):
instructions = sci1_setup()
analysis = analyze_sci(instructions, clock_hz=16_000_000)
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.json"
write_json(path, instructions, {}, {}, sci_analysis=analysis)
payload = json.loads(path.read_text(encoding="utf-8"))
self.assertEqual(payload["sci"]["channels"]["SCI1"]["configurations"][0]["baud_bps"], 31_250)
brr_instruction = next(item for item in payload["instructions"] if item["address"] == 0x100A)
self.assertEqual(brr_instruction["sci"]["inferences"][0]["brr"], 7)
if __name__ == "__main__":
unittest.main()