- 删 isa/Image.h + Image.cpp(ImageView/FNV/写文件/sidecar 不再属于 isa) - vm 自实现只读视图 vm/Image.h/cpp:头 104(12.13)/段校验/缺 SHA 尾报错 (型号匹配与 SHA 校验留步骤 8);Machine 改用 vm::Image + vm::ImageHeader - executor:本地读文件(替换 isa::read_stb_file) - 测试:isa_test 删映像/FNV 部分;codegen_test/vm_test 改用 compiler::StbView / vm::ConstEntry;vm_test 手拼映像适配新格式(头 104 + 尾 32 占位) - 验证:line1 编译 288 字节 → BytecodeExecutor 回放 Q 正确;ctest 12/12
137 lines
4.6 KiB
C++
137 lines
4.6 KiB
C++
/**
|
|
* @file isa_test.cpp
|
|
* @brief isa 合同测试:饱和、编解码、disasm、哈希、映像、sidecar
|
|
* @author
|
|
* @date 2026-08-19
|
|
*/
|
|
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "isa/Encode.h"
|
|
#include "isa/Instr.h"
|
|
#include "isa/Op.h"
|
|
#include "isa/Types.h"
|
|
|
|
static int g_checks = 0;
|
|
|
|
#define CHECK(cond) \
|
|
do { \
|
|
if (!(cond)) { \
|
|
std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
|
|
return false; \
|
|
} \
|
|
++g_checks; \
|
|
} while (0)
|
|
|
|
// ---- 1. 饱和算术 ----
|
|
|
|
static bool test_sat() {
|
|
using namespace isa::types;
|
|
CHECK(sat_add(30000, 30000) == 32767);
|
|
CHECK(sat_add(-30000, -30000) == -32768);
|
|
CHECK(sat_add(10, 20) == 30);
|
|
CHECK(sat_sub(-30000, 30000) == -32768);
|
|
CHECK(sat_sub(5, 3) == 2);
|
|
CHECK(sat_mul(300, 200) == 32767);
|
|
CHECK(sat_mul(-300, 200) == -32768);
|
|
CHECK(sat_mul(6, 7) == 42);
|
|
CHECK(sat_div(10, 3) == 3);
|
|
CHECK(sat_div(-32768, -1) == 32767); // INT_MIN / -1 饱和
|
|
CHECK(sat_div(7, 0) == 7); // 除零返回被除数
|
|
CHECK(static_cast<int>(TypeTag::Bool) == 0);
|
|
CHECK(static_cast<int>(TypeTag::Int) == 1);
|
|
CHECK(static_cast<int>(TypeTag::Time) == 2);
|
|
return true;
|
|
}
|
|
|
|
// ---- 2. 操作码与助记符 ----
|
|
|
|
static bool test_op() {
|
|
using namespace isa;
|
|
CHECK(static_cast<int>(Op::MOVE) == 0);
|
|
CHECK(static_cast<int>(Op::CAL_TON) == 24);
|
|
CHECK(static_cast<int>(Op::CAL_F_TRIG) == 31); // 8 个 CAL_* 连续 24..31
|
|
CHECK(static_cast<int>(Op::CALL) == 32);
|
|
CHECK(static_cast<int>(Op::RET) == 33);
|
|
CHECK(kOpCount == 34);
|
|
CHECK(std::strcmp(mnemonic(Op::CAL_CTUD), "CAL_CTUD") == 0);
|
|
CHECK(std::strcmp(mnemonic(Op::CAL_F_TRIG), "CAL_F_TRIG") == 0);
|
|
CHECK(std::strcmp(mnemonic(static_cast<Op>(255)), "???") == 0);
|
|
return true;
|
|
}
|
|
|
|
// ---- 3. 指令打包 / 拆字段 ----
|
|
|
|
static bool test_instr() {
|
|
using namespace isa;
|
|
const Instr w = pack(Op::ADD, 5, 3, 4);
|
|
CHECK(op(w) == Op::ADD);
|
|
CHECK(rd(w) == 5);
|
|
CHECK(a(w) == 3);
|
|
CHECK(b(w) == 4);
|
|
CHECK(imm16(enc_imm(Op::LOADK, 0, 0x1234)) == 0x1234);
|
|
CHECK(off16(enc_jmp(-1)) == -1);
|
|
CHECK(off16(enc_jmp(4)) == 4);
|
|
CHECK(rd(enc_jc(Op::JT, 2, -3)) == 2);
|
|
CHECK(off16(enc_jc(Op::JT, 2, -3)) == -3);
|
|
CHECK(imm16(enc_call(0xABCD)) == 0xABCD);
|
|
CHECK(imm16(enc_slot(Op::LOAD_I, 7, 300)) == 300);
|
|
CHECK(rd(enc_slot(Op::LOAD_I, 7, 300)) == 7);
|
|
CHECK(rd(enc_rr(Op::MOVE, 1, 2)) == 1);
|
|
CHECK(a(enc_rr(Op::MOVE, 1, 2)) == 2);
|
|
CHECK(op(enc_ret()) == Op::RET);
|
|
return true;
|
|
}
|
|
|
|
// ---- 4. encode / decode / disasm ----
|
|
|
|
static bool test_encode() {
|
|
using namespace isa;
|
|
const Instr w = enc_rrr(Op::ADD, 5, 3, 4);
|
|
CHECK(encode(decode(w)) == w);
|
|
CHECK(decode(w).op == Op::ADD);
|
|
CHECK(decode(w).rd == 5);
|
|
CHECK(decode(w).a == 3);
|
|
CHECK(decode(w).b == 4);
|
|
|
|
char buf[64];
|
|
disasm(w, buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "ADD r5, r3, r4") == 0);
|
|
disasm(enc_rr(Op::MOVE, 1, 2), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "MOVE r1, r2") == 0);
|
|
disasm(enc_imm(Op::LOADK, 0, 3), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "LOADK r0, 3") == 0);
|
|
disasm(enc_jmp(4), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "JMP +4") == 0);
|
|
disasm(enc_jmp(-1), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "JMP -1") == 0);
|
|
disasm(enc_jc(Op::JT, 0, -1), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "JT r0, -1") == 0);
|
|
disasm(enc_call(1), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "CALL 1") == 0);
|
|
disasm(enc_slot(Op::LOAD_I, 0, 2), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "LOAD_I r0, 2") == 0);
|
|
disasm(enc_slot(Op::STORE_Q, 4, 0), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "STORE_Q r4, 0") == 0);
|
|
disasm(enc_ret(), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "RET") == 0);
|
|
disasm(enc_imm(Op::CAL_TON, 0, 0), buf, sizeof buf);
|
|
CHECK(std::strcmp(buf, "CAL_TON 0") == 0);
|
|
disasm(0xFFu, buf, sizeof buf); // 未知操作码
|
|
CHECK(std::strcmp(buf, "??? 0x000000ff") == 0);
|
|
return true;
|
|
}
|
|
|
|
int main() {
|
|
if (!test_sat()) return 1;
|
|
if (!test_op()) return 1;
|
|
if (!test_instr()) return 1;
|
|
if (!test_encode()) return 1;
|
|
std::printf("isa_test: %d checks passed\n", g_checks);
|
|
return 0;
|
|
}
|