hdcstorage / tests /test_isa.py
AEUPH's picture
HDCSTORAGE: hyperdimensional computer, webOS and agentic MCP layer (stdlib-only Python)
ad474c9 verified
Raw History Blame Contribute Delete
4.79 kB
"""Tests for instruction encoding and compute-in-memory decoding."""
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from hdc.isa import ( # noqa: E402
OPCODES,
DecodeContext,
DecodeError,
decode_instr,
encode_instr,
format_operands,
opcode_table_text,
)
D = 2000
def ctx(**kw):
base = dict(d=D)
base.update(kw)
return DecodeContext(**base)
class TestRoundTrip(unittest.TestCase):
"""Every field kind must survive encode -> bundle -> unbind -> cleanup."""
CASES = [
("NOP", dict(), dict()),
("HALT", dict(), dict()),
("LDI", dict(regs=[3], imm=7), dict(imms=[7])),
("MOV", dict(regs=[1, 2]), dict()),
("ADD", dict(regs=[2, 0, 1]), dict()),
("PERMUTE", dict(regs=[4, 5], imm=3), dict(imms=[3])),
("POPC", dict(regs=[6, 7]), dict()),
("JMP", dict(tgt=9), dict(tgts=[9])),
("JNZ", dict(tgt=12), dict(tgts=[12])),
("STORE", dict(name="out", regs=[6]), dict(names=["out"])),
("LOAD", dict(regs=[7], name="out"), dict(names=["out"])),
("RECALL", dict(regs=[9, 10], imm=3), dict(imms=[3])),
("PRINTS", dict(text="hi there"), dict(strs=["hi there"])),
(
"TOOL",
dict(regs=[0, 1, 2], tool="hdc.similarity"),
dict(tools=["hdc.similarity"]),
),
]
def test_roundtrip_fields(self):
for op, kw, alphabets in self.CASES:
with self.subTest(op=op):
hv = encode_instr(op, d=D, **kw)
dec = decode_instr(hv, ctx(**alphabets))
self.assertEqual(dec.op, op)
self.assertEqual(dec.regs, list(kw.get("regs", [])))
self.assertEqual(dec.imm, kw.get("imm"))
self.assertEqual(dec.tgt, kw.get("tgt"))
self.assertEqual(dec.name, kw.get("name"))
self.assertEqual(dec.text, kw.get("text"))
self.assertEqual(dec.tool, kw.get("tool"))
self.assertGreater(dec.confidence, 0.2, msg="op %s" % op)
def test_margins_are_recorded(self):
dec = decode_instr(encode_instr("ADD", regs=[2, 0, 1], d=D), ctx())
self.assertIn("op", dec.margins)
self.assertIn("ra", dec.margins)
self.assertGreater(dec.margins["op"], 0.0)
def test_whole_opcode_table_encodes(self):
for name in OPCODES:
with self.subTest(op=name):
# a body-free vector must still identify its opcode
dec = decode_instr(encode_instr(name, d=D), ctx())
self.assertEqual(dec.op, name)
def test_format_operands(self):
dec = decode_instr(encode_instr("STORE", name="out", regs=[6], d=D), ctx(names=["out"]))
self.assertEqual(format_operands(dec), "out, R6")
dec = decode_instr(encode_instr("JMP", tgt=9, d=D), ctx(tgts=[9]))
self.assertEqual(format_operands(dec), "@9")
class TestDegradedContext(unittest.TestCase):
def test_missing_literal_alphabet_still_decodes_opcode(self):
hv = encode_instr("LDI", regs=[3], imm=7, d=D)
dec = decode_instr(hv, ctx()) # no imms supplied at all
self.assertEqual(dec.op, "LDI")
self.assertEqual(dec.regs, [3])
self.assertIsNone(dec.imm)
def test_default_context_has_no_alphabets(self):
self.assertEqual(DecodeContext().imms, ())
self.assertEqual(DecodeContext().names, ())
# The context must carry the same dimensionality as the encoding;
# an empty alphabet is the point, a mismatched d would be a user error.
dec = decode_instr(encode_instr("HALT", d=D), DecodeContext(d=D))
self.assertEqual(dec.op, "HALT")
class TestErrors(unittest.TestCase):
def test_unknown_opcode(self):
with self.assertRaises(DecodeError):
encode_instr("FROBNICATE", d=D)
def test_register_out_of_range(self):
with self.assertRaises(DecodeError):
encode_instr("MOV", regs=[16], d=D)
def test_too_many_registers(self):
with self.assertRaises(DecodeError):
encode_instr("ADD", regs=[0, 1, 2, 3], d=D)
def test_negative_register(self):
with self.assertRaises(DecodeError):
encode_instr("MOV", regs=[-1], d=D)
class TestTable(unittest.TestCase):
def test_table_text_mentions_every_opcode(self):
text = opcode_table_text()
for name in OPCODES:
self.assertIn(name, text)
def test_effects_are_known_classes(self):
allowed = {"ctrl", "alu", "hd", "mem", "io", "tool", "debug"}
for op in OPCODES.values():
self.assertIn(op.effect, allowed)
if __name__ == "__main__":
unittest.main()