12.8 切片 7:FB 实例块、用户 FB 内联、CAL_TON/TOF/CTU。
- FB 实例 → 数据区实例块(字段地址 = 基址+偏移,编译期算死;跨周期持久) - 用户 FB 调用点内联展开(实参写字段 → FB 体以实例字段为变量编译) - 内建 TON/TOF/CTU:实参写字段 → CAL_* <实例偏移>;FB 生成空函数占位保持 fn_id - codegen_test:189 断言(用例 15 内联序列、17 CAL_TON 字段偏移、18 TOF/CTU、line1 全链路 LOAD_I/STORE_Q),ctest 9/9 - 20 用例扫描:14 正例全部出映像,6 负例按期望在前层拒绝
This commit is contained in:
@@ -541,6 +541,151 @@ static bool test_case13() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 14. 用例 15:用户 FB 内联展开 ----
|
||||
|
||||
static bool test_case15() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("15_fb_instance", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.header().n_funcs == 2); // FB 占位 + MAIN
|
||||
CHECK(v.header().entry_fn_id == 1);
|
||||
CHECK(v.data_len() == 8); // 实例 3B(start@0 stop@1 q@2),8 对齐
|
||||
|
||||
const isa::FuncRow fm = v.func_row(1);
|
||||
CHECK(fm.nregs == 12);
|
||||
CHECK(fm.code_len == 12);
|
||||
const uint32_t* im = reinterpret_cast<const uint32_t*>(v.code_bytes()) + fm.code_offset / 4;
|
||||
char buf[64];
|
||||
// 实参写字段:start := TRUE / stop := FALSE
|
||||
isa::disasm(im[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r9, 0") == 0);
|
||||
isa::disasm(im[1], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 0") == 0);
|
||||
isa::disasm(im[2], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r10, 1") == 0);
|
||||
isa::disasm(im[3], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r10, 1") == 0);
|
||||
// 内联体:Q := start AND NOT stop(短路跳转)
|
||||
isa::disasm(im[4], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 0") == 0);
|
||||
isa::disasm(im[5], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "JF r9, +3") == 0);
|
||||
isa::disasm(im[9], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 2") == 0); // Q 字段
|
||||
// q := starter.Q
|
||||
isa::disasm(im[10], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 2") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 15. 用例 17:TON(CAL_TON + 字段偏移)----
|
||||
|
||||
static bool test_case17() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("17_ton", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.data_len() == 32); // in@0 pt@8 q@16 et@24
|
||||
const isa::FuncRow r = v.func_row(0);
|
||||
CHECK(r.nregs == 11);
|
||||
const uint32_t* ins = reinterpret_cast<const uint32_t*>(v.code_bytes());
|
||||
char buf[64];
|
||||
isa::disasm(ins[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r9, 0") == 0);
|
||||
isa::disasm(ins[1], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 0") == 0); // in
|
||||
isa::disasm(ins[2], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOADK r10, 1") == 0);
|
||||
isa::disasm(ins[3], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r10, 8") == 0); // pt(TIME 8 对齐)
|
||||
isa::disasm(ins[4], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "CAL_TON 0") == 0);
|
||||
isa::disasm(ins[5], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 16") == 0); // t.Q
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 16. 用例 18:TOF / CTU ----
|
||||
|
||||
static bool test_case18() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
CHECK(compile_case("18_tof_ctu", &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.data_len() == 40); // tf 块 0..31(in@0 pt@8 q@16 et@24)、c 块 32..
|
||||
const isa::FuncRow r = v.func_row(0);
|
||||
CHECK(r.nregs == 14);
|
||||
const uint32_t* ins = reinterpret_cast<const uint32_t*>(v.code_bytes());
|
||||
char buf[64];
|
||||
isa::disasm(ins[4], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "CAL_TOF 0") == 0);
|
||||
isa::disasm(ins[12], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "CAL_CTU 32") == 0);
|
||||
isa::disasm(ins[13], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 36") == 0); // c.Q
|
||||
isa::disasm(ins[14], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r10, 38") == 0); // c.CV(INT 2 对齐)
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- 17. line1 全链路(MAIN + Motor FB + I/O + 全局)----
|
||||
|
||||
static bool test_line1() {
|
||||
std::vector<uint8_t> img;
|
||||
std::string err;
|
||||
using namespace compiler;
|
||||
const std::string toml = std::string(REPO_ROOT) + "/examples/line1/project.toml";
|
||||
Project p;
|
||||
CHECK(parse_project(toml, &p, &err));
|
||||
std::vector<SourceUnit> units;
|
||||
for (const std::string& f : compile_files(p)) {
|
||||
SourceUnit u;
|
||||
CHECK(load_unit(p.base_dir + "/" + f, &u, &err));
|
||||
units.push_back(std::move(u));
|
||||
}
|
||||
LinkResult link;
|
||||
CHECK(link_project(p, units, &link, &err));
|
||||
CHECK(check_project(p, units, link, &err));
|
||||
CHECK(codegen_project(p, units, link, &img, &err));
|
||||
|
||||
const isa::ImageView v = isa::ImageView::from(img);
|
||||
CHECK(v.ok());
|
||||
CHECK(v.header().n_globals == 4);
|
||||
CHECK(v.header().n_funcs == 2);
|
||||
CHECK(v.header().entry_fn_id == 1);
|
||||
CHECK(v.data_len() == 16); // 全局 4B + 实例块 8..10(8 对齐)
|
||||
|
||||
const isa::FuncRow fm = v.func_row(1);
|
||||
CHECK(fm.nregs == 13);
|
||||
CHECK(fm.code_len == 17);
|
||||
const uint32_t* im = reinterpret_cast<const uint32_t*>(v.code_bytes()) + fm.code_offset / 4;
|
||||
char buf[64];
|
||||
isa::disasm(im[0], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_I r8, 1") == 0); // I0_0(io.input)
|
||||
isa::disasm(im[1], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r8, 8") == 0); // starter.start
|
||||
isa::disasm(im[2], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 2") == 0); // I0_1
|
||||
isa::disasm(im[3], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 9") == 0); // starter.stop
|
||||
isa::disasm(im[13], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_GLOBAL r8, 10") == 0); // starter.Q
|
||||
isa::disasm(im[14], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 10") == 0); // starter.Q 读回
|
||||
isa::disasm(im[15], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "STORE_Q r8, 3") == 0); // Q0_0(io.output)
|
||||
isa::disasm(im[16], buf, sizeof buf);
|
||||
CHECK(std::strcmp(buf, "RET") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (!test_case01()) return 1;
|
||||
if (!test_case02()) return 1;
|
||||
@@ -555,6 +700,10 @@ int main() {
|
||||
if (!test_case07()) return 1;
|
||||
if (!test_case08()) return 1;
|
||||
if (!test_case13()) return 1;
|
||||
if (!test_case15()) return 1;
|
||||
if (!test_case17()) return 1;
|
||||
if (!test_case18()) return 1;
|
||||
if (!test_line1()) return 1;
|
||||
std::printf("codegen_test: %d checks passed\n", g_checks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user