DPsim
Loading...
Searching...
No Matches
InterfaceQueued.h
1/* Author: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
2 * SPDX-FileCopyrightText: 2023-2024 Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
3 * SPDX-License-Identifier: MPL-2.0
4 */
5
6#pragma once
7
8#include <thread>
9
10#include <dpsim-models/Attribute.h>
11#include <dpsim-models/Logger.h>
12#include <dpsim-models/Task.h>
13#include <dpsim/Config.h>
14#include <dpsim/Definitions.h>
15#include <dpsim/Interface.h>
16#include <dpsim/Scheduler.h>
17
18#include <readerwriterqueue.h>
19
20namespace DPsim {
21
22class InterfaceWorker;
23
24class InterfaceQueued : public Interface,
25 public SharedFactory<InterfaceQueued> {
26
27public:
28 typedef std::shared_ptr<InterfaceQueued> Ptr;
29
30 using AttributePacket = struct AttributePacket {
31 CPS::AttributeBase::Ptr value;
32 UInt
33 attributeId; // Used to identify the attribute. Defined by the position in the `mExportAttrsDpsim` and `mImportAttrsDpsim` lists
34 UInt
35 sequenceId; // Increasing ID used to discern multiple consecutive updates of a single attribute
36 unsigned char flags; // Bit 0 set: Close interface
37 };
38
39 enum AttributePacketFlags {
40 PACKET_NO_FLAGS = 0,
41 PACKET_CLOSE_INTERFACE = 1,
42 };
43
44 InterfaceQueued(std::shared_ptr<InterfaceWorker> intf,
45 const String &name = "", UInt downsampling = 1)
46 : Interface(name), mInterfaceWorker(intf), mDownsampling(downsampling) {
47 mQueueDpsimToInterface = std::make_shared<
48 moodycamel::BlockingReaderWriterQueue<AttributePacket>>();
49 mQueueInterfaceToDpsim = std::make_shared<
50 moodycamel::BlockingReaderWriterQueue<AttributePacket>>();
51 };
52
53 virtual void open() override;
54 virtual void close() override;
55
56 // Function used in the interface's simulation task to read all imported attributes from the queue
57 // Called once before every simulation timestep
58 virtual void pushDpsimAttrsToQueue();
59 // Function used in the interface's simulation task to write all exported attributes to the queue
60 // Called once after every simulation timestep
61 virtual void popDpsimAttrsFromQueue(bool isSync = false);
62
63 // Function called by the Simulation to perform interface synchronization
64 virtual void syncExports() override;
66 virtual void syncImports() override;
67
68 virtual CPS::Task::List getTasks() override;
69
70 virtual void setLogger(CPS::Logger::Log log) override;
71
72 virtual ~InterfaceQueued() {
73 if (mOpened)
74 close();
75 }
76
77protected:
78 std::shared_ptr<InterfaceWorker> mInterfaceWorker;
79 UInt mDownsampling;
80 std::thread mInterfaceWriterThread;
81 std::thread mInterfaceReaderThread;
82
83 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
84 mQueueDpsimToInterface;
85 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
86 mQueueInterfaceToDpsim;
87
88public:
89 class WriterThread {
90 private:
91 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
92 mQueueDpsimToInterface;
93 std::shared_ptr<InterfaceWorker> mInterfaceWorker;
94
95 public:
96 WriterThread(
97 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
98 queueDpsimToInterface,
99 std::shared_ptr<InterfaceWorker> intf)
100 : mQueueDpsimToInterface(queueDpsimToInterface),
101 mInterfaceWorker(intf){};
102 void operator()() const;
103 };
104
105 class ReaderThread {
106 private:
107 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
108 mQueueInterfaceToDpsim;
109 std::shared_ptr<InterfaceWorker> mInterfaceWorker;
110 std::atomic<bool> &mOpened;
111
112 public:
113 ReaderThread(
114 std::shared_ptr<moodycamel::BlockingReaderWriterQueue<AttributePacket>>
115 queueInterfaceToDpsim,
116 std::shared_ptr<InterfaceWorker> intf, std::atomic<bool> &opened)
117 : mQueueInterfaceToDpsim(queueInterfaceToDpsim), mInterfaceWorker(intf),
118 mOpened(opened){};
119 void operator()() const;
120 };
121
122 class PreStep : public CPS::Task {
123 public:
124 explicit PreStep(InterfaceQueued &intf)
125 : Task(intf.getName() + ".Read"), mIntf(intf) {
126 for (const auto &[attr, _seqId, _blockOnRead, _syncOnStart] :
127 intf.mImportAttrsDpsim) {
128 mModifiedAttributes.push_back(attr);
129 }
130 }
131
132 void execute(Real time, Int timeStepCount) override;
133
134 private:
135 InterfaceQueued &mIntf;
136 };
137
138 class PostStep : public CPS::Task {
139 public:
140 explicit PostStep(InterfaceQueued &intf)
141 : Task(intf.getName() + ".Write"), mIntf(intf) {
142 for (const auto &[attr, _seqId] : intf.mExportAttrsDpsim) {
143 mAttributeDependencies.push_back(attr);
144 }
145 mModifiedAttributes.push_back(Scheduler::external);
146 }
147
148 void execute(Real time, Int timeStepCount) override;
149
150 private:
151 InterfaceQueued &mIntf;
152 };
153};
154} // namespace DPsim
Tasks to be defined by every component.
Definition Task.h:25
virtual void syncImports() override
Function called by the Simulation to perform interface synchronization.