#pragma once #include "domain/control_logic_model.h" #include "domain/register_repository.h" #include #include #include #include #include #include #include // 一轮离线扫描可能返回的错误 enum class LogicScanError { None, InvalidLogic, ConflictingOutput, RegisterReadFailed, RegisterWriteFailed }; // 扫描结果;失败时携带出错的逻辑、网络和节点 ID struct LogicScanResult { bool succeeded = false; LogicScanError error = LogicScanError::None; std::string message; std::string logicId; std::string rungId; std::string nodeId; }; // TON 节点在最近一轮扫描中的可视化状态 struct TonTraceValue { bool input = false; bool done = false; std::int64_t elapsedMs = 0; int presetMs = 0; }; // CTU/CTD 节点在最近一轮扫描中的可视化状态 struct CounterTraceValue { bool input = false; bool reset = false; bool done = false; std::int16_t value = 0; std::int16_t preset = 0; }; // MOVE/ADD/SUB 节点的结果值和溢出标记 struct WordTraceValue { std::int16_t value = 0; bool overflow = false; }; // 一条逻辑或一个网络的运行轨迹快照 struct LogicTraceValues { std::unordered_map nodeValues; std::unordered_map nodePowerValues; std::unordered_map expressionValues; std::unordered_map expressionInputValues; std::unordered_map expressionPowerValues; std::unordered_map rungValues; std::unordered_map tonValues; std::unordered_map counterValues; std::unordered_map wordValues; void clear(); }; // 全工程轨迹;logicValues 按逻辑 ID 隔离,避免节点 ID 重复互相覆盖 struct LogicTraceSnapshot : LogicTraceValues { std::unordered_map logicValues; void clear(); LogicTraceSnapshot forLogic(const std::string &logic_id) const; }; // 按工程顺序执行受限梯形图的一次确定性扫描 class SoftwareLogicExecutor { public: using Clock = std::chrono::steady_clock; using TimePoint = Clock::time_point; // 在启动仿真前检查所有启用逻辑及 T/C 资源引用 LogicScanResult validate(const std::vector &logics) const; // 清除沿触发、定时器和计数器的跨扫描运行状态 void resetRuntime(); // 使用当前 steady_clock 执行一轮扫描 LogicScanResult executeScan( const std::vector &logics, RegisterRepository &repository, LogicTraceSnapshot *trace = nullptr); // 使用指定时间执行扫描,便于稳定验证 TON 等时间逻辑 LogicScanResult executeScanAt( const std::vector &logics, RegisterRepository &repository, TimePoint now, LogicTraceSnapshot *trace = nullptr); private: struct TonRuntimeState { bool timing = false; bool done = false; TimePoint startedAt{}; std::chrono::milliseconds elapsed{0}; }; LogicScanResult evaluateCondition( const std::string &logic_id, const LogicNode &node, RegisterRepository &repository, bool *value); LogicScanResult evaluateExpression( const std::string &logic_id, const ConditionExpression &expression, RegisterRepository &repository, LogicTraceValues *trace, bool input_power, bool *value); LogicScanResult executeOutput( const std::string &logic_id, const LogicNode &node, bool rung_value, RegisterRepository &repository, TimePoint now, LogicTraceValues *trace, bool *output_value); LogicScanResult readWordOperand( const WordOperand &operand, RegisterRepository &repository, std::int16_t *value, const std::string &node_id) const; std::map, bool> previous_edge_inputs_; std::map, bool> previous_counter_inputs_; std::unordered_map ton_states_; struct CounterRuntimeState { bool done = false; }; std::unordered_map counter_states_; };