Page MenuHomePhorge

No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/deluxe-interface/deluxe-interface.cpp
index 82621ac..c742cce 100755
--- a/examples/deluxe-interface/deluxe-interface.cpp
+++ b/examples/deluxe-interface/deluxe-interface.cpp
@@ -1,272 +1,320 @@
//===-- examples/deluxe-interface/deluxe-interface.cpp ----------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/deluxe-interface/deluxe-interface.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related
/// classes.
//===----------------------------------------------------------------------===//
#include "rosa/config/version.h"
#include "rosa/deluxe/DeluxeContext.hpp"
#include <algorithm>
#include <cmath>
#include <vector>
using namespace rosa;
using namespace rosa::deluxe;
using namespace rosa::terminal;
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 16;
int main(void) {
LOG_INFO_STREAM << '\n'
<< library_string() << " -- " << Color::Red
<< "deluxe-interface example" << Color::Default << '\n';
std::unique_ptr<DeluxeContext> C = DeluxeContext::create("Deluxe");
//
// Create deluxe sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the last argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
// The first and second sensors do not receive master-input.
AgentHandle BoolSensor = C->createSensor<bool>("BoolSensor");
AgentHandle IntSensor = C->createSensor<int32_t>("IntSensor");
// This sensor receives master-input and dumps it to \c LOG_INFO_STREAM.
const std::string FloatSensorName = "FloatSensor";
AgentHandle FloatSensor = C->createSensor<uint32_t, float>(
FloatSensorName, [&FloatSensorName](std::pair<uint32_t, bool> I) {
LOG_INFO_STREAM << "\n******\n"
<< FloatSensorName
<< " master-input " << (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
});
+ // This sensor do not receive master-input but produces tuples.
+ using TupleType = DeluxeTuple<float, float>;
+ AgentHandle TupleSensor = C->createSensor<TupleType>("TupleSensor");
+
//
// Create low-level deluxe agents with \c createLowLevelAgent.
//
LOG_INFO("Creating low-level agents.");
// All agents below dump their received values to \c LOG_INFO_STREAM on each
// triggering.
// This agent does not receive master-input and does not produce
// master-output. It results in the value it received.
const std::string BoolAgentName = "BoolAgent";
using BoolResult = Optional<bool>;
using BoolHandler = std::function<BoolResult(std::pair<bool, bool>)>;
AgentHandle BoolAgent = C->createAgent(
BoolAgentName,
BoolHandler([&BoolAgentName](std::pair<bool, bool> I) -> BoolResult {
LOG_INFO_STREAM << "\n******\n"
<< BoolAgentName << " "
<< (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
return {I.first};
}));
// This agent receives master-input but does not produce master-output. The
// agent maintains a state in \c IntAgentOffset. The master-input handler
// updates \c IntAgentOffset according to each received (new) value from its
// master. The slave-input handler results in the sum of the received value
// and the actual value of \c IntAgentOffset.
const std::string IntAgentName = "IntAgent";
using IntMasterHandler = std::function<void(std::pair<uint32_t, bool>)>;
using IntResult = Optional<int32_t>;
using IntHandler = std::function<IntResult(std::pair<int32_t, bool>)>;
uint32_t IntAgentOffset = 0;
AgentHandle IntAgent = C->createAgent(
IntAgentName,
// Master-input handler.
IntMasterHandler([&IntAgentName,
&IntAgentOffset](std::pair<uint32_t, bool> I) {
LOG_INFO_STREAM << "\n******\n"
<< IntAgentName
<< " master-input " << (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
if (I.second) {
IntAgentOffset = I.first;
}
}),
// Slave-input handler.
IntHandler([&IntAgentName,
&IntAgentOffset](std::pair<int32_t, bool> I) -> IntResult {
LOG_INFO_STREAM << "\n******\n"
<< IntAgentName << " " << (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
return {I.first + IntAgentOffset};
}));
// This agent receives master-input and produces master-output. The
// master-input handler propagaates each received (new) value to its slave as
// master-output. The slave-input handler results in the value it received and
// produces no actual master-output.
const std::string FloatAgentName = "FloatAgent";
using FloatMasterResult = std::tuple<Optional<uint32_t>>;
using FloatMasterHandler =
std::function<FloatMasterResult(std::pair<uint32_t, bool>)>;
using FloatResult = std::tuple<Optional<float>, Optional<uint32_t>>;
using FloatHandler = std::function<FloatResult(std::pair<float, bool>)>;
AgentHandle FloatAgent = C->createAgent(
FloatAgentName,
// Master-input handler.
FloatMasterHandler([&FloatAgentName](
std::pair<uint32_t, bool> I) -> FloatMasterResult {
LOG_INFO_STREAM << "\n******\n"
<< FloatAgentName
<< " master-input " << (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
const auto Output =
I.second ? Optional<uint32_t>(I.first) : Optional<uint32_t>();
return {Output};
}),
// Slave-input handler.
FloatHandler([&FloatAgentName](std::pair<float, bool> I) -> FloatResult {
LOG_INFO_STREAM << "\n******\n"
<< FloatAgentName << " "
<< (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
return {{I.first}, {}};
}));
+ // This agent does not receive master-input and does not produce
+ // master-output. It results in the sum of the values it receives in a tuple.
+ const std::string TupleAgentName = "TupleAgent";
+ using TupleSumResult = Optional<DeluxeTuple<double>>;
+ using TupleHandler =
+ std::function<TupleSumResult(std::pair<TupleType, bool>)>;
+ AgentHandle TupleAgent = C->createAgent(
+ TupleAgentName,
+ TupleHandler(
+ [&TupleAgentName](std::pair<TupleType, bool> I) -> TupleSumResult {
+ LOG_INFO_STREAM << "\n******\n"
+ << TupleAgentName << " "
+ << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ return {std::get<0>(I.first) + std::get<1>(I.first)};
+ }));
+
//
// Connect sensors to low-level agents.
//
LOG_INFO("Connect sensors to their corresponding low-level agents.");
C->connectSensor(BoolAgent, 0, BoolSensor, "Bool Sensor Channel");
C->connectSensor(IntAgent, 0, IntSensor, "Int Sensor Channel");
C->connectSensor(FloatAgent, 0, FloatSensor, "Float Sensor Channel");
+ C->connectSensor(TupleAgent, 0, TupleSensor, "Tuple Sensor Channel");
//
// Create a high-level deluxe agent.
//
LOG_INFO("Create high-level agent.");
+ using SingleDoubleOutputType = Optional<DeluxeTuple<double>>;
+ using SingleUInt32OutputType = Optional<DeluxeTuple<uint32_t>>;
+ using NoOutputType = Optional<EmptyDeluxeTuple>;
+
// This agent does not receive master-input but produces master-output for its
// slaves at positions `1` and `2` but not for that at position `0`. The agent
// maintains a state in \c SumAgentState. The handler increments \c
// SumAgentState upon each received (new) `true` value from its slave at
// position `0`. Whenever \c SumAgentState has been updated, it is sent to the
// slaves at positions `1` and `2`. The handler results in the sum of the
- // values received from slaves at positions `1` and `2`.
- using SumResult = std::tuple<Optional<double>, Optional<unit_t>,
- Optional<uint32_t>, Optional<uint32_t>>;
+ // values received from slaves at positions `1`, `2`, and `3`.
+ using SumResult =
+ std::tuple<SingleDoubleOutputType, NoOutputType, SingleUInt32OutputType,
+ SingleUInt32OutputType, NoOutputType>;
using SumHandler = std::function<SumResult(
- std::pair<bool, bool>, std::pair<int32_t, bool>, std::pair<float, bool>)>;
+ std::pair<DeluxeTuple<bool>, bool>, std::pair<DeluxeTuple<int32_t>, bool>,
+ std::pair<DeluxeTuple<float>, bool>,
+ std::pair<DeluxeTuple<double>, bool>)>;
uint32_t SumAgentState = 0;
AgentHandle SumAgent = C->createAgent(
"Sum Agent",
- SumHandler([&SumAgentState](std::pair<bool, bool> I0,
- std::pair<int32_t, bool> I1,
- std::pair<float, bool> I2) -> SumResult {
+ SumHandler([&SumAgentState](
+ std::pair<DeluxeTuple<bool>, bool> I0,
+ std::pair<DeluxeTuple<int32_t>, bool> I1,
+ std::pair<DeluxeTuple<float>, bool> I2,
+ std::pair<DeluxeTuple<double>, bool> I3) -> SumResult {
+ const auto V0 = std::get<0>(I0.first);
+ const auto V1 = std::get<0>(I1.first);
+ const auto V2 = std::get<0>(I2.first);
+ const auto V3 = std::get<0>(I3.first);
LOG_INFO_STREAM << "\n*******\nSum Agent triggered with values:\n"
<< (I0.second ? "<New>" : "<Old>")
- << " bool value: " << I0.first << "\n"
+ << " bool value: " << V0 << "\n"
<< (I1.second ? "<New>" : "<Old>")
- << " int value: " << I1.first << "\n"
+ << " int value: " << V1 << "\n"
<< (I2.second ? "<New>" : "<Old>")
- << " float value: " << I2.first << "\n******\n";
- if (I0.second && I0.first) {
+ << " float value: " << V2 << "\n"
+ << (I3.second ? "<New>" : "<Old>")
+ << " double value: " << V3 << "\n******\n";
+ if (I0.second && V0) {
++SumAgentState;
}
- const auto MasterOutput = I0.second && I0.first
- ? Optional<uint32_t>(SumAgentState)
- : Optional<uint32_t>();
- const auto Output = I1.first + I2.first;
- return {{Output}, {}, {MasterOutput}, {MasterOutput}};
+ const SingleUInt32OutputType MasterOutput =
+ I0.second && V0
+ ? SingleUInt32OutputType(DeluxeTuple<uint32_t>(SumAgentState))
+ : SingleUInt32OutputType();
+ const DeluxeTuple<double> Output = {V1 + V2 + V3};
+ return {{Output}, {}, {MasterOutput}, {MasterOutput}, {}};
}));
//
// Connect low-level agents to the high-level agent.
//
LOG_INFO("Connect low-level agents to the high-level agent.");
C->connectAgents(SumAgent, 0, BoolAgent, "Bool Agent Channel");
C->connectAgents(SumAgent, 1, IntAgent, "Int Agent Channel");
C->connectAgents(SumAgent, 2, FloatAgent, "Float Agent Channel");
+ C->connectAgents(SumAgent, 3, TupleAgent, "Tuple Agent Channel");
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a log stream.
//
LOG_INFO("Create a logger agent.");
// The agent dumps each received (new) value to \c LOG_INFO_STREAM and
// produces nothing; does not receive mater-input and does not produce
// master-output.
AgentHandle LoggerAgent =
C->createAgent("Logger Agent",
std::function<Optional<unit_t>(std::pair<double, bool>)>(
[](std::pair<double, bool> Sum) -> Optional<unit_t> {
if (Sum.second) {
LOG_INFO_STREAM << "Result: " << Sum.first << "\n";
}
return {};
}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO("Connect the high-level agent to the logger agent.");
C->connectAgents(LoggerAgent, 0, SumAgent, "Sum Agent Channel");
//
// Do simulation.
//
LOG_INFO("Setting up and performing simulation.");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
//
// Create some vectors and register them for their corresponding sensors.
//
std::vector<bool> BoolValues(NumberOfSimulationCycles);
std::generate(BoolValues.begin(), BoolValues.end(),
[i = 0](void) mutable -> bool { return (++i % 4) == 0; });
C->registerSensorValues(BoolSensor, BoolValues.begin(), BoolValues.end());
std::vector<int32_t> IntValues(NumberOfSimulationCycles);
std::generate(IntValues.begin(), IntValues.end(),
[i = 0](void) mutable { return ++i; });
C->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end());
std::vector<float> FloatValues(NumberOfSimulationCycles);
std::generate(FloatValues.begin(), FloatValues.end(),
[f = 0.5f](void) mutable {
f += 0.3f;
return std::floor(f) + 0.5f;
});
C->registerSensorValues(FloatSensor, FloatValues.begin(), FloatValues.end());
+ std::vector<TupleType> TupleValues(NumberOfSimulationCycles);
+ std::generate(TupleValues.begin(), TupleValues.end(),
+ [f1 = 0.f, f2 = 3.14f](void) mutable -> TupleType {
+ f1 += f2;
+ f2 -= f1;
+ return {f1, f2};
+ });
+ C->registerSensorValues(TupleSensor, TupleValues.begin(), TupleValues.end());
+
//
// Simulate.
//
C->simulate(NumberOfSimulationCycles);
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Apr 27, 1:03 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
134504
Default Alt Text
(14 KB)

Event Timeline