DTC and SCI improvements
This commit is contained in:
122
tests/test_sci_inference.py
Normal file
122
tests/test_sci_inference.py
Normal 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()
|
||||
Reference in New Issue
Block a user