77197b9c1e
E84 (Parallel I/O) is fundamentally per-load-port: each port has its own ten-wire handshake with the AMHS. Earlier revisions modeled it as a single equipment-wide FSM; this commit refactors to a per-port store, so multi-LP tools can run independent handshakes in parallel. Public API change in EquipmentDataModel: E84StateMachine e84; -> removed E84PortStore e84_ports; // create(port_id), get(port_id), ... Convenience pass-throughs: E84PortStore::on_signal_change auto-creates the port on first use (ergonomic for demos); applications should call create() explicitly with their full port set. The two existing callsites (test_gem300_scenario, test_e87_wire_scenarios) are updated. The multi-LP test now demonstrates the actual win: interleaved LP1 load + LP2 unload handshakes that reach their respective Ready states without sequencing, and an ES on LP1 that does NOT affect LP2 — exactly the failure mode the previous design couldn't catch. Five new dedicated tests in test_e84_ports.cpp for the store itself. COMPLIANCE.md §4i updated: row now reflects per-port design. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
84 lines
3.2 KiB
C++
84 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include "secsgem/gem/store/alarms.hpp"
|
|
#include "secsgem/gem/store/carriers.hpp"
|
|
#include "secsgem/gem/store/cem_objects.hpp"
|
|
#include "secsgem/gem/store/clock.hpp"
|
|
#include "secsgem/gem/e84_state.hpp"
|
|
#include "secsgem/gem/store/e84_ports.hpp"
|
|
#include "secsgem/gem/ept_state.hpp"
|
|
#include "secsgem/gem/store/control_jobs.hpp"
|
|
#include "secsgem/gem/store/equipment_constants.hpp"
|
|
#include "secsgem/gem/store/event_reports.hpp"
|
|
#include "secsgem/gem/store/exceptions.hpp"
|
|
#include "secsgem/gem/store/host_commands.hpp"
|
|
#include "secsgem/gem/store/limits.hpp"
|
|
#include "secsgem/gem/store/modules.hpp"
|
|
#include "secsgem/gem/store/process_jobs.hpp"
|
|
#include "secsgem/gem/store/substrates.hpp"
|
|
#include "secsgem/gem/store/recipes.hpp"
|
|
#include "secsgem/gem/store/spool.hpp"
|
|
#include "secsgem/gem/store/status_variables.hpp"
|
|
#include "secsgem/gem/store/trace.hpp"
|
|
|
|
namespace secsgem::gem {
|
|
|
|
// Composite over the focused stores covering every GEM data category.
|
|
// Each store is independently testable and independently usable — the
|
|
// application can keep a reference to just `alarms` and ignore the rest
|
|
// if that's all it needs. Variable lookups span SVIDs and DVIDs through
|
|
// this composite (the host's view per E30 §6.11).
|
|
struct EquipmentDataModel {
|
|
StatusVariableStore svids;
|
|
DataVariableStore dvids;
|
|
EquipmentConstantStore ecids;
|
|
EventReportSubscriptions events;
|
|
AlarmRegistry alarms;
|
|
RecipeStore recipes;
|
|
Clock clock;
|
|
HostCommandRegistry commands;
|
|
SpoolStore spool;
|
|
LimitMonitorStore limits;
|
|
TraceStore traces;
|
|
ProcessJobStore process_jobs;
|
|
ControlJobStore control_jobs;
|
|
ExceptionStore exceptions;
|
|
CarrierStore carriers;
|
|
LoadPortStore load_ports;
|
|
SubstrateStore substrates;
|
|
EptStateMachine ept;
|
|
CemObjectStore cem;
|
|
ModuleStore modules;
|
|
E84PortStore e84_ports;
|
|
|
|
// Convenience: VID -> value lookup spanning SVIDs and DVIDs.
|
|
std::optional<s2::Item> vid_value(uint32_t vid) const {
|
|
if (auto v = svids.value(vid)) return v;
|
|
if (auto v = dvids.value(vid)) return v;
|
|
return std::nullopt;
|
|
}
|
|
bool vid_exists(uint32_t vid) const {
|
|
return svids.has(vid) || dvids.has(vid);
|
|
}
|
|
|
|
// Sugar that adapts the EventReportSubscriptions API to the host-supplied
|
|
// VID list shape (matches what parse_s2f33 / parse_s2f35 yield).
|
|
DefineReportAck define_reports(
|
|
const std::vector<std::pair<uint32_t, std::vector<uint32_t>>>& rows) {
|
|
return events.define_reports(rows, [this](uint32_t vid) { return vid_exists(vid); });
|
|
}
|
|
LinkEventAck link_event_reports(
|
|
const std::vector<std::pair<uint32_t, std::vector<uint32_t>>>& rows) {
|
|
return events.link_event_reports(rows);
|
|
}
|
|
EnableEventAck enable_events(bool enable, const std::vector<uint32_t>& ceids) {
|
|
return events.enable_events(enable, ceids);
|
|
}
|
|
bool is_event_enabled(uint32_t ceid) const { return events.is_enabled(ceid); }
|
|
std::vector<ReportData> compose_reports_for(uint32_t ceid) const {
|
|
return events.compose_for(ceid, [this](uint32_t vid) { return vid_value(vid); });
|
|
}
|
|
};
|
|
|
|
} // namespace secsgem::gem
|