3 #include <dpsim/Interface.h>
4 #include <dpsim/InterfaceWorker.h>
10 void Interface::open() {
11 mInterfaceWorker->open();
14 if (!mImportAttrsDpsim.empty()) {
15 mInterfaceReaderThread = std::thread(Interface::ReaderThread(
16 mQueueInterfaceToDpsim, mInterfaceWorker, mOpened));
18 if (!mExportAttrsDpsim.empty()) {
19 mInterfaceWriterThread = std::thread(
20 Interface::WriterThread(mQueueDpsimToInterface, mInterfaceWorker));
24 void Interface::close() {
26 mQueueDpsimToInterface->emplace(AttributePacket{
27 nullptr, 0, 0, AttributePacketFlags::PACKET_CLOSE_INTERFACE});
29 if (!mExportAttrsDpsim.empty()) {
30 mInterfaceWriterThread.join();
33 if (!mImportAttrsDpsim.empty()) {
34 mInterfaceReaderThread.join();
36 mInterfaceWorker->close();
39 CPS::Task::List Interface::getTasks() {
40 auto tasks = CPS::Task::List();
41 if (!mImportAttrsDpsim.empty()) {
42 tasks.push_back(std::make_shared<Interface::PreStep>(*
this));
44 if (!mExportAttrsDpsim.empty()) {
45 tasks.push_back(std::make_shared<Interface::PostStep>(*
this));
50 void Interface::PreStep::execute(Real time, Int timeStepCount) {
51 if (timeStepCount % mIntf.mDownsampling == 0)
52 mIntf.popDpsimAttrsFromQueue();
55 void Interface::PostStep::execute(Real time, Int timeStepCount) {
56 if (timeStepCount % mIntf.mDownsampling == 0)
57 mIntf.pushDpsimAttrsToQueue();
61 bool syncOnSimulationStart) {
64 mLog,
"Cannot modify interface configuration after simulation start!");
68 mImportAttrsDpsim.emplace_back(attr, 0, blockOnRead, syncOnSimulationStart);
74 mLog,
"Cannot modify interface configuration after simulation start!");
78 mExportAttrsDpsim.emplace_back(attr, 0);
81 void Interface::setLogger(CPS::Logger::Log log) {
83 if (mInterfaceWorker !=
nullptr) {
84 mInterfaceWorker->mLog = log;
88 void Interface::syncImports() {
90 this->popDpsimAttrsFromQueue(
true);
93 void Interface::syncExports() {
95 this->pushDpsimAttrsToQueue();
98 void Interface::popDpsimAttrsFromQueue(
bool isSync) {
99 AttributePacket receivedPacket = {
nullptr, 0, 0,
100 AttributePacketFlags::PACKET_NO_FLAGS};
101 UInt currentSequenceId = mNextSequenceInterfaceToDpsim;
105 while (std::find_if(mImportAttrsDpsim.cbegin(), mImportAttrsDpsim.cend(),
106 [currentSequenceId, isSync](
auto attrTuple) {
107 auto &[_attr, seqId, blockOnRead, syncOnStart] =
110 return syncOnStart && seqId < currentSequenceId;
112 return blockOnRead && seqId < currentSequenceId;
114 }) != mImportAttrsDpsim.cend()) {
115 mQueueInterfaceToDpsim->wait_dequeue(receivedPacket);
116 if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId])
117 ->copyValue(receivedPacket.value)) {
119 mLog,
"Failed to copy received value onto attribute in Interface!");
121 std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) =
122 receivedPacket.sequenceId;
123 mNextSequenceInterfaceToDpsim = receivedPacket.sequenceId + 1;
127 while (mQueueInterfaceToDpsim->try_dequeue(receivedPacket)) {
128 if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId])
129 ->copyValue(receivedPacket.value)) {
131 mLog,
"Failed to copy received value onto attribute in Interface!");
133 std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) =
134 receivedPacket.sequenceId;
135 mNextSequenceInterfaceToDpsim = receivedPacket.sequenceId + 1;
139 void Interface::pushDpsimAttrsToQueue() {
140 for (UInt i = 0; i < mExportAttrsDpsim.size(); i++) {
141 mQueueDpsimToInterface->emplace(AttributePacket{
142 std::get<0>(mExportAttrsDpsim[i])->cloneValueOntoNewAttribute(), i,
143 std::get<1>(mExportAttrsDpsim[i]),
144 AttributePacketFlags::PACKET_NO_FLAGS});
145 std::get<1>(mExportAttrsDpsim[i]) = mCurrentSequenceDpsimToInterface;
146 mCurrentSequenceDpsimToInterface++;
150 void Interface::WriterThread::operator()()
const {
151 bool interfaceClosed =
false;
152 std::vector<Interface::AttributePacket> attrsToWrite;
153 while (!interfaceClosed) {
154 AttributePacket nextPacket = {
nullptr, 0, 0,
155 AttributePacketFlags::PACKET_NO_FLAGS};
158 mQueueDpsimToInterface->wait_dequeue(nextPacket);
159 if (nextPacket.flags & AttributePacketFlags::PACKET_CLOSE_INTERFACE) {
160 interfaceClosed =
true;
162 attrsToWrite.push_back(nextPacket);
166 while (mQueueDpsimToInterface->try_dequeue(nextPacket)) {
167 if (nextPacket.flags & AttributePacketFlags::PACKET_CLOSE_INTERFACE) {
168 interfaceClosed =
true;
170 attrsToWrite.push_back(nextPacket);
173 mInterfaceWorker->writeValuesToEnv(attrsToWrite);
177 void Interface::ReaderThread::operator()()
const {
178 std::vector<Interface::AttributePacket> attrsRead;
180 mInterfaceWorker->readValuesFromEnv(attrsRead);
181 for (
const auto &packet : attrsRead) {
182 mQueueInterfaceToDpsim->enqueue(packet);