Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1497893
application-interface.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
13 KB
Referenced Files
None
Subscribers
None
application-interface.cpp
View Options
//===-- examples/application-interface/application-interface.cpp *- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file examples/application-interface/application-interface.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2020
///
/// \brief A simple example on the \c rosa::app::Application and related
/// classes.
//===----------------------------------------------------------------------===//
#include
"rosa/config/version.h"
#include
"rosa/app/Application.hpp"
#include
<algorithm>
#include
<cmath>
#include
<vector>
using
namespace
rosa
;
using
namespace
rosa
::
app
;
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
<<
"application-interface example"
<<
Color
::
Default
<<
'\n'
;
std
::
unique_ptr
<
Application
>
App
=
Application
::
create
(
"App"
);
//
// Create application 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
=
App
->
createSensor
<
bool
>
(
"BoolSensor"
);
AgentHandle
IntSensor
=
App
->
createSensor
<
int32_t
>
(
"IntSensor"
);
// This sensor receives master-input and dumps it to \c LOG_INFO_STREAM.
const
std
::
string
FloatSensorName
=
"FloatSensor"
;
AgentHandle
FloatSensor
=
App
->
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
=
AppTuple
<
float
,
float
>
;
AgentHandle
TupleSensor
=
App
->
createSensor
<
TupleType
>
(
"TupleSensor"
);
//
// Check and set execution policy for sensors.
//
LOG_INFO
(
"Execution policies for sensors."
);
LOG_INFO
(
std
::
to_string
(
*
App
->
getExecutionPolicy
(
IntSensor
)));
App
->
setExecutionPolicy
(
IntSensor
,
AppExecutionPolicy
::
decimation
(
2
));
App
->
setExecutionPolicy
(
FloatSensor
,
AppExecutionPolicy
::
decimation
(
2
));
LOG_INFO
(
std
::
to_string
(
*
App
->
getExecutionPolicy
(
IntSensor
)));
//
// Create low-level application 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
=
App
->
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
=
App
->
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
=
App
->
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
<
AppTuple
<
double
>>
;
using
TupleHandler
=
std
::
function
<
TupleSumResult
(
std
::
pair
<
TupleType
,
bool
>
)
>
;
AgentHandle
TupleAgent
=
App
->
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
)};
}));
//
// Set execution policies for low-level agents.
//
LOG_INFO
(
"Setting Execution policies for low-level agents."
);
App
->
setExecutionPolicy
(
IntAgent
,
AppExecutionPolicy
::
awaitAll
({
0
}));
App
->
setExecutionPolicy
(
FloatAgent
,
AppExecutionPolicy
::
awaitAll
({
0
}));
//
// Connect sensors to low-level agents.
//
LOG_INFO
(
"Connect sensors to their corresponding low-level agents."
);
App
->
connectSensor
(
BoolAgent
,
0
,
BoolSensor
,
"Bool Sensor Channel"
);
App
->
connectSensor
(
IntAgent
,
0
,
IntSensor
,
"Int Sensor Channel"
);
App
->
connectSensor
(
FloatAgent
,
0
,
FloatSensor
,
"Float Sensor Channel"
);
App
->
connectSensor
(
TupleAgent
,
0
,
TupleSensor
,
"Tuple Sensor Channel"
);
//
// Create a high-level application agent.
//
LOG_INFO
(
"Create high-level agent."
);
using
SingleDoubleOutputType
=
Optional
<
AppTuple
<
double
>>
;
using
SingleUInt32OutputType
=
Optional
<
AppTuple
<
uint32_t
>>
;
using
NoOutputType
=
Optional
<
EmptyAppTuple
>
;
// 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`, `2`, and `3`.
using
SumResult
=
std
::
tuple
<
SingleDoubleOutputType
,
NoOutputType
,
SingleUInt32OutputType
,
SingleUInt32OutputType
,
NoOutputType
>
;
using
SumHandler
=
std
::
function
<
SumResult
(
std
::
pair
<
AppTuple
<
bool
>
,
bool
>
,
std
::
pair
<
AppTuple
<
int32_t
>
,
bool
>
,
std
::
pair
<
AppTuple
<
float
>
,
bool
>
,
std
::
pair
<
AppTuple
<
double
>
,
bool
>
)
>
;
uint32_t
SumAgentState
=
0
;
AgentHandle
SumAgent
=
App
->
createAgent
(
"Sum Agent"
,
SumHandler
(
[
&
SumAgentState
](
std
::
pair
<
AppTuple
<
bool
>
,
bool
>
I0
,
std
::
pair
<
AppTuple
<
int32_t
>
,
bool
>
I1
,
std
::
pair
<
AppTuple
<
float
>
,
bool
>
I2
,
std
::
pair
<
AppTuple
<
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
*******
\n
Sum Agent triggered with values:
\n
"
<<
(
I0
.
second
?
"<New>"
:
"<Old>"
)
<<
" bool value: "
<<
V0
<<
"
\n
"
<<
(
I1
.
second
?
"<New>"
:
"<Old>"
)
<<
" int value: "
<<
V1
<<
"
\n
"
<<
(
I2
.
second
?
"<New>"
:
"<Old>"
)
<<
" float value: "
<<
V2
<<
"
\n
"
<<
(
I3
.
second
?
"<New>"
:
"<Old>"
)
<<
" double value: "
<<
V3
<<
"
\n
******
\n
"
;
if
(
I0
.
second
&&
V0
)
{
++
SumAgentState
;
}
const
SingleUInt32OutputType
MasterOutput
=
I0
.
second
&&
V0
?
SingleUInt32OutputType
(
AppTuple
<
uint32_t
>
(
SumAgentState
))
:
SingleUInt32OutputType
();
const
AppTuple
<
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."
);
App
->
connectAgents
(
SumAgent
,
0
,
BoolAgent
,
"Bool Agent Channel"
);
App
->
connectAgents
(
SumAgent
,
1
,
IntAgent
,
"Int Agent Channel"
);
App
->
connectAgents
(
SumAgent
,
2
,
FloatAgent
,
"Float Agent Channel"
);
App
->
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
=
App
->
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."
);
App
->
connectAgents
(
LoggerAgent
,
0
,
SumAgent
,
"Sum Agent Channel"
);
//
// Do simulation.
//
LOG_INFO
(
"Setting up and performing simulation."
);
//
// Initialize application for simulation.
//
App
->
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
;
});
App
->
registerSensorValues
(
BoolSensor
,
BoolValues
.
begin
(),
BoolValues
.
end
());
std
::
vector
<
int32_t
>
IntValues
(
NumberOfSimulationCycles
);
std
::
generate
(
IntValues
.
begin
(),
IntValues
.
end
(),
[
i
=
0
](
void
)
mutable
{
return
++
i
;
});
App
->
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
;
});
App
->
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
};
});
App
->
registerSensorValues
(
TupleSensor
,
TupleValues
.
begin
(),
TupleValues
.
end
());
//
// Simulate.
//
App
->
simulate
(
NumberOfSimulationCycles
);
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, Mar 1, 10:18 PM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
288101
Default Alt Text
application-interface.cpp (13 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment