扩充内置功能块为 8 个:TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG。
- isa:CAL_* 操作码连续占 24..31(CALL/RET 后移为 32/33,kOpCount=34);disasm 支持 5 个新操作码 - 词法/语法/链接:新 8 个关键字与冻结布局(TP=in/pt/q/et、CTD=cd/ld/pv/q/cv、 CTUD=cu/cd/r/lu/pv/qu/qd/cv、R_TRIG/F_TRIG=clk/q) - VM:do_cal 全 8 个语义(TP 脉冲、CTD 递减、CTUD 双向+装载、R_TRIG 上升沿、F_TRIG 下降沿); edge_prev_ 每槽 2 字节存边沿上次输入;exec_one 分发补 5 个新操作码 - 验证:TP 30ms 脉冲 2 周期、CTD 装载+递减到 q=1、CTUD cu/cd 双向、R/F_TRIG 交替; ctest 11/11 全绿 - 文档:指令与映像/词法/初步计划/符号表与链接/指令执行/扫描周期/使用说明 同步
This commit is contained in:
+116
-22
@@ -35,7 +35,7 @@ bool Machine::create(const std::vector<uint8_t>& image, Machine* out,
|
||||
// 数据区工作副本(8 字节定宽槽)
|
||||
out->data_.assign(out->image_.data_bytes(),
|
||||
out->image_.data_bytes() + out->image_.data_len());
|
||||
out->ctu_prev_.assign(out->data_len() / 8, 0);
|
||||
out->edge_prev_.assign(out->data_len() / 8 * 2, 0);
|
||||
|
||||
// MAIN 帧(跨周期保留)
|
||||
const uint32_t entry = out->image_.header().entry_fn_id;
|
||||
@@ -265,7 +265,12 @@ bool Machine::exec_one() {
|
||||
return !ended_; // MAIN 的 RET → 周期结束(返回 false)
|
||||
case isa::Op::CAL_TON:
|
||||
case isa::Op::CAL_TOF:
|
||||
case isa::Op::CAL_TP:
|
||||
case isa::Op::CAL_CTU:
|
||||
case isa::Op::CAL_CTD:
|
||||
case isa::Op::CAL_CTUD:
|
||||
case isa::Op::CAL_R_TRIG:
|
||||
case isa::Op::CAL_F_TRIG:
|
||||
fault_ = do_cal(static_cast<uint8_t>(op), isa::imm16(w));
|
||||
return fault_ == Fault::None;
|
||||
default:
|
||||
@@ -340,15 +345,18 @@ Fault Machine::do_ret() {
|
||||
|
||||
Fault Machine::do_cal(uint8_t op, uint16_t slot) {
|
||||
// 内建 FB 布局冻结(Doc/compiler/符号表与链接.md):
|
||||
// TON/TOF:in/pt/q/et(字段 0/1/2/3)
|
||||
// CTU:cu/r/pv/q/cv(字段 0/1/2/3/4)
|
||||
// 实例槽号从 slot(基槽)起;字段偏移 = 字段序号 × 8(8 字节定宽)
|
||||
// TON/TOF/TP:in/pt/q/et(字段 0/1/2/3)
|
||||
// CTU:cu/r/pv/q/cv(0/1/2/3/4);CTD:cd/ld/pv/q/cv(同)
|
||||
// CTUD:cu/cd/r/lu/pv/qu/qd/cv(0..7)
|
||||
// R_TRIG / F_TRIG:clk/q(0/1)
|
||||
// 字段偏移 = 字段序号 × 8(8 字节定宽槽);边沿存 edge_prev_
|
||||
const int64_t dt = image_.header().dt_ms;
|
||||
int64_t v = 0;
|
||||
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_TON) ||
|
||||
op == static_cast<uint8_t>(isa::Op::CAL_TOF)) {
|
||||
// 字段:in=0 pt=1 q=2 et=3
|
||||
const bool is_ton = op == static_cast<uint8_t>(isa::Op::CAL_TON);
|
||||
const bool is_tof = op == static_cast<uint8_t>(isa::Op::CAL_TOF);
|
||||
if (is_ton || is_tof) {
|
||||
// in=0 pt=1 q=2 et=3
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 0), &v)) return Fault::BadSlot;
|
||||
const bool in = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 1), &v)) return Fault::BadSlot;
|
||||
@@ -356,7 +364,7 @@ Fault Machine::do_cal(uint8_t op, uint16_t slot) {
|
||||
int64_t et = 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 3), &et)) return Fault::BadSlot;
|
||||
int64_t q = 0;
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_TON)) {
|
||||
if (is_ton) {
|
||||
// TON:in 真 → et += dt(到 pt 停)、q = et ≥ pt;in 假 → et = 0、q = 0
|
||||
if (in) {
|
||||
et += dt;
|
||||
@@ -383,29 +391,115 @@ Fault Machine::do_cal(uint8_t op, uint16_t slot) {
|
||||
return Fault::None;
|
||||
}
|
||||
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_CTU)) {
|
||||
// 字段:cu=0 r=1 pv=2 q=3 cv=4
|
||||
if (slot >= ctu_prev_.size()) return Fault::BadSlot;
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_TP)) {
|
||||
// in=0 pt=1 q=2 et=3 + 上次 in(edge_prev_[slot*2])
|
||||
if (static_cast<size_t>(slot) * 2 + 1 >= edge_prev_.size()) return Fault::BadSlot;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 0), &v)) return Fault::BadSlot;
|
||||
const bool cu = v != 0;
|
||||
const bool in = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 1), &v)) return Fault::BadSlot;
|
||||
const bool r = v != 0;
|
||||
const int64_t pt = v;
|
||||
int64_t et = 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 3), &et)) return Fault::BadSlot;
|
||||
// TP(脉冲):in 上升沿启动 PT 时长的脉冲,期间 in 变化不影响
|
||||
const bool prev = edge_prev_[slot * 2] != 0;
|
||||
const bool rising = in && !prev;
|
||||
int64_t q = 0;
|
||||
if (rising) {
|
||||
et = 0;
|
||||
}
|
||||
const bool timing = rising || (et > 0);
|
||||
if (timing) {
|
||||
et += dt;
|
||||
if (pt > 0 && et >= pt) {
|
||||
et = 0; // 脉冲结束:et 归零,下周期不再计时
|
||||
q = 0;
|
||||
} else {
|
||||
q = 1;
|
||||
}
|
||||
} else {
|
||||
et = 0;
|
||||
q = 0;
|
||||
}
|
||||
edge_prev_[slot * 2] = in ? 1 : 0;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 3), et)) return Fault::BadSlot;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 2), q)) return Fault::BadSlot;
|
||||
return Fault::None;
|
||||
}
|
||||
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_CTU) ||
|
||||
op == static_cast<uint8_t>(isa::Op::CAL_CTD)) {
|
||||
// CTU:cu/r/pv/q/cv;CTD:cd/ld/pv/q/cv
|
||||
if (static_cast<size_t>(slot) * 2 >= edge_prev_.size()) return Fault::BadSlot;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 0), &v)) return Fault::BadSlot;
|
||||
const bool edge_in = v != 0; // cu(CTU)/ cd(CTD)
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 1), &v)) return Fault::BadSlot;
|
||||
const bool ld_in = v != 0; // r(CTU)/ ld(CTD)
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 2), &v)) return Fault::BadSlot;
|
||||
const int64_t pv = v;
|
||||
int64_t cv = 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 4), &cv)) return Fault::BadSlot;
|
||||
// 上升沿:本周期 cu 真且上次 cu 假 → cv + 1;r → 复位
|
||||
const bool prev = ctu_prev_[slot] != 0;
|
||||
const bool prev = edge_prev_[slot * 2] != 0;
|
||||
if (ld_in) {
|
||||
cv = pv;
|
||||
} else if (edge_in && !prev) {
|
||||
cv += (op == static_cast<uint8_t>(isa::Op::CAL_CTU)) ? 1 : -1;
|
||||
}
|
||||
edge_prev_[slot * 2] = edge_in ? 1 : 0;
|
||||
const int64_t q = (op == static_cast<uint8_t>(isa::Op::CAL_CTU))
|
||||
? ((cv >= pv) ? 1 : 0)
|
||||
: ((cv <= 0) ? 1 : 0);
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 4), cv)) return Fault::BadSlot;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 3), q)) return Fault::BadSlot;
|
||||
return Fault::None;
|
||||
}
|
||||
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_CTUD)) {
|
||||
// cu=0 cd=1 r=2 lu=3 pv=4 qu=5 qd=6 cv=7
|
||||
if (static_cast<size_t>(slot) * 2 + 1 >= edge_prev_.size()) return Fault::BadSlot;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 0), &v)) return Fault::BadSlot;
|
||||
const bool cu = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 1), &v)) return Fault::BadSlot;
|
||||
const bool cd = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 2), &v)) return Fault::BadSlot;
|
||||
const bool r = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 3), &v)) return Fault::BadSlot;
|
||||
const bool lu = v != 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 4), &v)) return Fault::BadSlot;
|
||||
const int64_t pv = v;
|
||||
int64_t cv = 0;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 7), &cv)) return Fault::BadSlot;
|
||||
const bool prev_cu = edge_prev_[slot * 2] != 0;
|
||||
const bool prev_cd = edge_prev_[slot * 2 + 1] != 0;
|
||||
if (r) {
|
||||
cv = 0;
|
||||
} else if (cu && !prev) {
|
||||
cv += 1;
|
||||
}
|
||||
ctu_prev_[slot] = cu ? 1 : 0; // 记录本次 cu(跨周期)
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 4), cv)) return Fault::BadSlot;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 3), (cv >= pv) ? 1 : 0)) {
|
||||
return Fault::BadSlot;
|
||||
} else if (lu) {
|
||||
cv = pv;
|
||||
} else {
|
||||
if (cu && !prev_cu) cv += 1;
|
||||
if (cd && !prev_cd) cv -= 1;
|
||||
}
|
||||
edge_prev_[slot * 2] = cu ? 1 : 0;
|
||||
edge_prev_[slot * 2 + 1] = cd ? 1 : 0;
|
||||
const int64_t qu = (cv >= pv) ? 1 : 0;
|
||||
const int64_t qd = (cv <= 0) ? 1 : 0;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 7), cv)) return Fault::BadSlot;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 5), qu)) return Fault::BadSlot;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 6), qd)) return Fault::BadSlot;
|
||||
return Fault::None;
|
||||
}
|
||||
|
||||
if (op == static_cast<uint8_t>(isa::Op::CAL_R_TRIG) ||
|
||||
op == static_cast<uint8_t>(isa::Op::CAL_F_TRIG)) {
|
||||
// clk=0 q=1
|
||||
if (static_cast<size_t>(slot) * 2 >= edge_prev_.size()) return Fault::BadSlot;
|
||||
if (!slot_get(static_cast<uint16_t>(slot + 0), &v)) return Fault::BadSlot;
|
||||
const bool clk = v != 0;
|
||||
const bool prev = edge_prev_[slot * 2] != 0;
|
||||
const int64_t q = (op == static_cast<uint8_t>(isa::Op::CAL_R_TRIG))
|
||||
? ((clk && !prev) ? 1 : 0)
|
||||
: ((!clk && prev) ? 1 : 0);
|
||||
edge_prev_[slot * 2] = clk ? 1 : 0;
|
||||
if (!slot_set(static_cast<uint16_t>(slot + 1), q)) return Fault::BadSlot;
|
||||
return Fault::None;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user