|
- #pragma once
-
- #include "domain/control_logic_model.h"
- #include "domain/register_repository.h"
-
- #include <chrono>
- #include <cstdint>
- #include <map>
- #include <string>
- #include <unordered_map>
- #include <utility>
- #include <vector>
-
- // 一轮离线扫描可能返回的错误
- 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<std::string, bool> nodeValues;
- std::unordered_map<std::string, bool> nodePowerValues;
- std::unordered_map<std::string, bool> expressionValues;
- std::unordered_map<std::string, bool> expressionInputValues;
- std::unordered_map<std::string, bool> expressionPowerValues;
- std::unordered_map<std::string, bool> rungValues;
- std::unordered_map<std::string, TonTraceValue> tonValues;
- std::unordered_map<std::string, CounterTraceValue> counterValues;
- std::unordered_map<std::string, WordTraceValue> wordValues;
-
- void clear();
- };
-
- // 全工程轨迹;logicValues 按逻辑 ID 隔离,避免节点 ID 重复互相覆盖
- struct LogicTraceSnapshot : LogicTraceValues
- {
- std::unordered_map<std::string, LogicTraceValues> 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<ControlLogic> &logics) const;
- // 清除沿触发、定时器和计数器的跨扫描运行状态
- void resetRuntime();
- // 使用当前 steady_clock 执行一轮扫描
- LogicScanResult executeScan(
- const std::vector<ControlLogic> &logics,
- RegisterRepository &repository,
- LogicTraceSnapshot *trace = nullptr);
- // 使用指定时间执行扫描,便于稳定验证 TON 等时间逻辑
- LogicScanResult executeScanAt(
- const std::vector<ControlLogic> &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<std::pair<std::string, std::string>, bool> previous_edge_inputs_;
- std::map<std::pair<std::string, std::string>, bool> previous_counter_inputs_;
- std::unordered_map<int, TonRuntimeState> ton_states_;
- struct CounterRuntimeState
- {
- bool done = false;
- };
- std::unordered_map<int, CounterRuntimeState> counter_states_;
- };
|