Commit 7e5c5f96 authored by yoogx's avatar yoogx

Merge branch 'master' of https://github.com/OpenAADL/polyorb-hi-c

parents 59965273 b2838051
......@@ -2,10 +2,11 @@ Current maintainer is
- Jerome Hugues
Contributors
- Raphael Defoin (2018)
- Antonia Francis (2018)
- Hariprasath Shanmugasundaram (2017)
The initial design team of PolyORB-HI/C was
- Julien Delange (up to 2016)
- Julien Delange (initial author, up to 2016)
- Jerome Hugues
- Laurent Pautet (up to 2009)
......@@ -221,9 +221,11 @@ AC_OUTPUT([
examples/aadlv2/file-store/Makefile
examples/aadlv2/latency/Makefile
examples/aadlv2/rma/Makefile
examples/aadlv2/rpc/Makefile
examples/aadlv2/some-types/Makefile
examples/aadlv2/some-types-stdint/Makefile
examples/aadlv2/sunseeker/Makefile
examples/aadlv2/torture_gqueue/Makefile
tools/Makefile
tools/check-symbols/Makefile
tools/check-symbols/examples/Makefile
......
SUBDIRS = d3.1.3-1 ping rma sunseeker producer-consumer some-types \
some-types-stdint flight-mgmt import monitor lua cpp \
packet-store file-store latency code_coverage
packet-store file-store latency code_coverage torture_gqueue \
rpc
SAMPLE_DIR = ${shell $(CYGPATH_U) '$(OCARINA_PREFIX)/examples/ocarina/polyorb-hi-c/aadlv2'}
......
#!/bin/sh
for i in "$@"
do
case $i in
--output-dir-name=*)
OUTPUT_DIR="${i#*=}" #ONLY NAME OF DIR
shift # past argument=value
;;
*)
# unknown option
;;
esac
done
if [ -z "$OUTPUT_DIR" ]; then
OUTPUT_DIR=./gcov_output
else
OUTPUT_DIR=./$OUTPUT_DIR
fi
if (! test -d $OUTPUT_DIR )
then
echo "Missing path: $OUTPUT_DIR. Creating directory..."
mkdir $OUTPUT_DIR
fi
lcov -c -i -d . -o .coverage.base
lcov -c -d . -o .coverage.run
lcov -d . -a .coverage.base -a .coverage.run -o .coverage.total
genhtml --no-branch-coverage -o $OUTPUT_DIR .coverage.total
rm -f .coverage.base .coverage.run .coverage.total
This diff is collapsed.
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <types.h>
int16_t boolean_type_var = 0;
int32_t integer_type_var = 0;
int64_t natural_type_var = 0;
void user_emit_boolean( int16_t* boolean)
int8_t int8_type_var = 0;
int16_t int16_type_var = 0;
int32_t int32_type_var = 0;
int64_t int64_type_var = 0;
uint8_t uint8_type_var = 0;
uint16_t uint16_type_var = 0;
uint32_t uint32_type_var = 0;
uint64_t uint64_type_var = 0;
float_t float0_type_var = 0.0;
float_t float32_type_var = 0.0;
double_t float64_type_var = 0.0;
char char_type_var = 'A';
/* Macros Definition */
/* Integer */
#define EMIT_TYPE_INT(TYPE, VAR, FORMAT) \
void user_emit_##TYPE (VAR * type) \
{\
TYPE##_type_var++; \
*type = TYPE##_type_var;\
printf("Emetting integer : ");\
printf(FORMAT, *type);\
printf("\n"); \
fflush (stdout); \
}
#define RECEIVE_TYPE_INT(TYPE, VAR, FORMAT) \
void user_receive_##TYPE (VAR type)\
{\
printf("Receiving integer : ");\
printf(FORMAT, type);\
printf("\n"); \
fflush (stdout); \
}
/* Float */
#define EMIT_TYPE_FLOAT(TYPE, VAR, FORMAT) \
void user_emit_##TYPE (VAR * type) \
{\
TYPE##_type_var++; \
*type = TYPE##_type_var;\
printf("Emetting float : ");\
printf(FORMAT, *type);\
printf("\n"); \
fflush (stdout); \
}
#define RECEIVE_TYPE_FLOAT(TYPE, VAR, FORMAT) \
void user_receive_##TYPE (VAR type)\
{\
printf("Receiving float : ");\
printf(FORMAT, type);\
printf("\n"); \
fflush (stdout); \
}
/* Boolean sub case */
void user_emit_boolean(int16_t* boolean)
{
if (boolean_type_var == 1)
{
......@@ -16,21 +85,93 @@ void user_emit_boolean( int16_t* boolean)
}
*boolean = boolean_type_var;
printf ("Sending boolean : %d\n", *boolean);
fflush (stdout);
}
void user_receive_boolean (int16_t boolean)
{
printf ("Receiving boolean : %d\n", boolean);
fflush (stdout);
}
void user_emit_integer( int32_t* integer)
/* Char sub case */
void user_emit_char (char* character)
{
integer_type_var++;
*integer = integer_type_var;
printf ("Emetting integer : %d\n", *integer);
char_type_var = 'A' + ((char_type_var - 'A' +1) %26) ;
*character = (char)char_type_var;
printf ("Emetting char : %c\n", *character);
fflush (stdout);
}
void user_receive_integer (int32_t integer)
void user_receive_char (char character)
{
printf ("Receiving integer : %d\n", integer);
printf ("Receiving char : %c\n", character);
fflush (stdout);
}
/* Array sub case */
void user_emit_array (software__array_type* data)
{
int i;
for (i = 0; i < 16; i++)
{(*data)[i]=i;}
printf ("Emetting array\n");
fflush (stdout);
}
void user_receive_array (software__array_type data)
{
int i;
printf("Receive array: ");
for (i = 0; i < 16; i++)
{assert (data[i] == i);}
printf ("OK \n");
fflush(stdout);
}
/* Appel des fonctions */
EMIT_TYPE_INT(integer, int32_t, "%d")
RECEIVE_TYPE_INT(integer, int32_t, "%d")
EMIT_TYPE_INT(natural, int64_t, "%lld")
RECEIVE_TYPE_INT(natural, int64_t, "%lld")
EMIT_TYPE_INT(int8,int8_t, "%hhd")
RECEIVE_TYPE_INT(int8,int8_t, "%hhd")
EMIT_TYPE_INT(int16,int16_t, "%d")
RECEIVE_TYPE_INT(int16,int16_t, "%d")
EMIT_TYPE_INT(int32,int32_t, "%d")
RECEIVE_TYPE_INT(int32,int32_t, "%d")
EMIT_TYPE_INT(int64,int64_t, "%ld")
RECEIVE_TYPE_INT(int64,int64_t, "%ld")
EMIT_TYPE_INT(uint8,uint8_t, "%hhu")
RECEIVE_TYPE_INT(uint8,uint8_t, "%hhu")
EMIT_TYPE_INT(uint16,uint16_t, "%u")
RECEIVE_TYPE_INT(uint16,uint16_t, "%u")
EMIT_TYPE_INT(uint32,uint32_t,"%u")
RECEIVE_TYPE_INT(uint32,uint32_t, "%u")
EMIT_TYPE_INT(uint64,uint64_t, "%lu")
RECEIVE_TYPE_INT(uint64,uint64_t, "%lu")
EMIT_TYPE_FLOAT(float0,float_t, "%lf")
RECEIVE_TYPE_FLOAT(float0,float_t, "%lf")
EMIT_TYPE_FLOAT(float32,float_t, "%lf")
RECEIVE_TYPE_FLOAT(float32,float_t, "%lf")
EMIT_TYPE_FLOAT(float64,double_t, "%llf")
RECEIVE_TYPE_FLOAT(float64,double_t,"%llf")
C_FILES = $(srcdir)/rpc.c
AADL_FILES = $(srcdir)/rpc.aadl
SCENARIO_FILES = $(srcdir)/scenario.aadl
include $(srcdir)/../../Makefile.common
EXTRA_DIST = $(AADL_FILES) $(SCENARIO_FILES) $(C_FILES)
CLEANDIRS = rpc_impl
package RPC
-- This example illustrates how to emulate RPC synchronous (or
-- rendez-vous) interactions using a tuple of parameter/return value
-- ports, and the AADL runtime services.
public
with Data_Model;
with Deployment;
---------------
-- Processes --
---------------
-- RPC_Process host two threads interacting in a synchronou way: a
-- client and a server
process RPC_Process
end RPC_Process;
process implementation RPC_Process.Impl
subcomponents
Client_T : thread Client_Thread.Impl;
Server_T : thread Server_Thread.Impl;
connections
C1 : port Client_T.Out_Parameter -> Server_T.In_Parameter;
C2 : port Server_T.Return_Value -> Client_T.Return_Value;
end RPC_Process.Impl;
-------------
-- Threads --
-------------
thread Client_Thread
features
Out_Parameter : out event data port Alpha_Type;
Return_Value : in event data port Alpha_Type;
end Client_Thread;
thread implementation Client_Thread.Impl
-- In the case of the client-side of the RPC: the corresponding
-- AADL subprogram is *NOT* connected to AADL thread ports. The
-- Client_Side_Function interacts directly with the port
-- variables to emulate a RPC synchronous call:
--
-- 1/ we send the parameter through the "out_parameter" port
-- 2/ we block and wait for return parameters through the return_value
properties
Dispatch_Protocol => Periodic;
Period => 1 sec;
Priority => 110;
Compute_Entrypoint => classifier (Client_Side_Function);
end Client_Thread.Impl;
thread Server_Thread
features
In_Parameter : in event data port Alpha_Type;
Return_Value : out event data port Alpha_Type;
end Server_Thread;
thread implementation Server_Thread.Impl
-- In the case of the server-side RPC: the server function is
-- connected to the input parameter and return value ports, we
-- take advantage of port-to-parameter conenctions to hook the
-- server code directly. It is sporadic to reflect it server
-- nature: ut reacts to incoming events representing the arrival
-- of in parameters and will answer back through the return_value
-- port.
calls
Mycalls: {
S_Spg : subprogram Server_Side_Function;
};
connections
parameter S_Spg.Return_Value -> Return_Value;
parameter In_Parameter -> S_Spg.In_Parameter;
properties
Dispatch_Protocol => Sporadic;
Period => 10 ms;
end Server_Thread.Impl;
----------
-- Data --
----------
data Alpha_Type
properties
Data_Model::Data_Representation => integer;
end Alpha_Type;
-----------------
-- Subprograms --
-----------------
subprogram Server_Side_Function
features
In_Parameter : in parameter Alpha_Type;
Return_Value : out parameter Alpha_Type;
properties
Source_Language => (C);
Source_Name => "rpc_server";
Source_Text => ("rpc.c");
end Server_Side_Function;
subprogram Client_Side_Function
features
Out_Parameter : out parameter Alpha_Type;
Return_Value : in parameter Alpha_Type;
properties
Source_Language => (C);
Source_Name => "rpc_client";
Source_Text => ("rpc.c");
end Client_Side_Function;
---------------
-- Processor --
---------------
processor the_processor
properties
Deployment::Execution_Platform => Native;
end the_processor;
processor implementation the_processor.i
end the_processor.i;
------------
-- System --
------------
system RPC
end RPC;
system implementation RPC.Impl
subcomponents
RPC : process RPC_Process.Impl;
CPU : processor the_processor.i;
properties
Actual_Processor_Binding => (reference (CPU)) applies to RPC;
end RPC.Impl;
end RPC;
#include <aadl.h>
#include <stdio.h>
/* Files generated from AADL model */
#include <request.h>
#include <deployment.h>
#include "types.h"
#include <po_hi_transport.h>
#include <po_hi_gqueue.h>
/******************************************************************************/
/* In the case of the client-side of the RPC: the corresponding AADL
* subprogram is *NOT* connected to AADL thread ports. We interact
* directly with the port variables to emulate a RPC synchronous call:
* 1/ we send the parameter through the "out_parameter" port
* 2/ we block and wait for return parameters through the return_value
*/
void rpc_client (__po_hi_task_id self) {
static int i = 0;
__po_hi_request_t req;
__po_hi_local_port_t return_value_port;
printf ("[START of RPC]\n");
req.port = REQUEST_PORT (client_t, out_parameter);
req.PORT_VARIABLE (client_t,out_parameter) = i;
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (client_t,out_parameter),
&req);
__po_hi_send_output (self,REQUEST_PORT(client_t, out_parameter));
printf ("Client thread: sending parameter %d\n", i);
__po_hi_gqueue_wait_for_incoming_event(self, &return_value_port);
__po_hi_gqueue_get_value(self,return_value_port,&req);
__po_hi_gqueue_next_value(self,return_value_port);
printf ("Client received: %d\n",
req.PORT_VARIABLE(client_t,return_value));
i++;
printf ("[END of RPC]\n\n");
}
/******************************************************************************/
/* In the case of the server-side RPC: the server function is
* connected to the input parameter and return value ports, we take
* advantage of port-to-parameter conenctions to hook the server code
* directly
*/
void rpc_server
(rpc__alpha_type in_parameter,
rpc__alpha_type* return_value)
{
printf ("Server thread: received %d\n", in_parameter);
*return_value = in_parameter + 1;
printf ("Server thread: sending return value %d\n", *return_value);
}
package Scenario
public
with Ocarina_Config;
with Ocarina_Library;
system producer_consumer extends Ocarina_Library::Default_PolyORB_HI_C_Config
properties
Ocarina_Config::Timeout_Property => 10500ms;
Ocarina_Config::AADL_Files +=>
("rpc.aadl");
Ocarina_Config::Root_System_Name => "rpc.impl";
end producer_consumer;
system implementation producer_consumer.Impl
end producer_consumer.Impl;
end scenario;
\ No newline at end of file
C_FILES = $(srcdir)/torture.c
AADL_FILES = $(srcdir)/torture.aadl
SCENARIO_FILES = $(srcdir)/scenario.aadl
include $(srcdir)/../../Makefile.common
EXTRA_DIST = $(AADL_FILES) $(SCENARIO_FILES) $(C_FILES)
CLEANDIRS = rma_impl rma_rtems
# torture.c
## About
This file allows the user to test the functions of the gqueue.
The functions directly tested are listed below :
__po_hi_gqueue_store_out,
__po_hi_gqueue_send_output,
__po_hi_gqueue_get_value,
__po_hi_gqueue_next_value,
__po_hi_gqueue_get_count,
__po_hi_gqueue_wait_for_incoming_event.
The functions directly tested are listed below :
__po_hi_gqueue_store_in.
## Global details
The boolean init is used to initialize the semaphores used in the
test, at the first awakening of the periodic function (first to awaken
between the two tasks).
The boolean first_iteration is used to coordinate the awakening of the
two tasks.
In fact, after the first awakening of the periodic function, we go
through the first five tests. However something is needed to indicate
we switch to the next battery of test. That is the role of the
"number" integer and the first_iteration boolean. When the value of
"number" is of 1, the first 5 tests are conducted (with one message at
each awakening). When the value of "number" switches from 1 to 2, the
periodic test 1 is triggered (two messages).
## Sporadic Test details
Each time messages are sent by the periodic task and received by the
Sporadic Task.
The Per Port 1 is linked to the Spo Port 2.
The Per Port 2 is linked to the Spo Port 1.
From the Sporadic 1 to the Sporadic 5:
- tests are made with only one message sent on a output port to an
event port (each time the periodic task is triggered).
- the tests are following each other.
Test Sporadic 1 :
A message has been sent and therefore, a message should be found on each port.
The get_count function is tested by verifying its value on each port is 1.
Test Sporadic 2 :
The goal is to verify :
- whether the wait_for_incoming_event function shows the events in the
right chronological order (FIFO behavior of the function awaited).
- whether the next_value function dequeues correctly the events stored
on each port.
Secondly, to verify :
- whether the value obtained from the get_value function is correct,
compared to the sent values.
As the first message sent was from Port P1 to Port P2, we at first
verify that the first port indicated by the wait_for_next_event
function is the port P2. Then the value sent and obtained thanks to
the get_value function are compared. Finally we verify that after the
dequeue, the get_count functions shows empty ports. At this point,
both ports are empty.
Test Sporadic 3 :
The goal is to verify whether the get_value function (thanks to
semaphores) waits correctly when the port is empty. The test is done
on an empty port. We verify that, when the lock is released, it is
only because both ports are now full : the Periodic task has been
triggered, releasing the get_value function.
Test Sporadic 4 and 5 :
These tests are used to verify this time the FIFO behavior of the
get_value function. The first lines roles are to establish the
optimal set up for the test (2 values on one port, and 1 value only on
the other). We verify thanks to the following assertion that the
value first obtained on the port with 2 events is not the value just
sent, but the previous one (inferior by 1). assert (reception !=
sent_level ); assert (reception == sent_level - 1); The other port
constitutes a control assay.
Test Sporadic 6 :
These tests are used to verify the behavior when working with IN DATA PORTS
and not IN EVENT DATA PORTS. It allows us to get a coverage of 100% of the code
with this test file.
Initially we verify that the reception has been done well.
First we use a get_value function, and then a next_value before verifying that
a get_count on a IN DATA PORT always gives back the value 1 and an used_size
always giving back the value 0.
Thay behavior awaited is illustrated by Beware Warnings.
We try a get_value on an empty port and finally we dequeue the event
sent from Period Port P2 to Sporad Port P1 to trigger the sporadic task.
## Periodic Test details
Each time messages are sent by the periodic task and received by itself.
The Per Port P3 is linked to the Per Port P4.
The Per Port P5 is linked to the Per Port P6.
Test Periodic 1 :
This time, two messages are sent on the port P3 towards port P4 of the
periodic task : the task are sending messages to itself.
The goal is to verify:
- whether the send_output (or transport_send) function works correctly.
- whether the FIFO behavior is maintained if two messages are sent in
only one awakening of the task.
The awaited behavior of the store_out function is to crush the value
stored out if no send_output is done, which we have been able to see
in the past. We verify that the duo store_out/send_output works fine
when called one after each other.
Finally we verify whether the two functions are recovered in the right
chronological order (the little value and the incremented one next).
The assertion to verify that is quite complex because only the last
value has been stored thanks to sent_lvl. However, as the
incrementation is of 1 at each awakening, it is easy to recover the
previous value sent thanks to the assertion : reception == sent_lvl -
number + j + 1. The value is then dequeued to get to the following
value.
Test Periodic 2 :
This time two messages are as well sent to the periodic task to itself.
The goal is to verify whether, if the queue is full, only a message is received
and it is the first one.The transport file must send an error message and prevent
the sending of the file.
The goal is then to verify whether the store_in function is also blocked
when the queue of the destined port isfull.
In both cases we verify that the message first sent is not erased by the other ones,
respectively supposedly not transmitted and not stored_in.
If messages are printed, then the test is passed.
In another hand, the goal is to verify that a get_value on an output port
gives right back an error message.
package scenario
public
with Ocarina_Config;
system rma
properties
Ocarina_Config::Timeout_Property => 4000ms;
Ocarina_Config::Referencial_Files =>
("node_a", "node_a.ref");
Ocarina_Config::AADL_Files =>
("torture.aadl");
Ocarina_Config::Root_System_Name => "torture.impl";
Ocarina_Config::Generator => polyorb_hi_c;
Ocarina_Config::Needed_Property_Sets =>
(Ocarina_Config::Data_Model,
Ocarina_Config::Deployment,
Ocarina_Config::Cheddar_Properties);
Ocarina_Config::AADL_Version => AADLv2;
end rma;
system implementation rma.Impl
end rma.Impl;
end scenario;
package Torture
public
with Data_Model;
with Deployment;
data Int
properties
Data_Model::Data_Representation => Integer;
end Int;
thread Per1
features
P1 : out event data port int;
P2 : out event data port int;
P3 : out event data port int;
P4 : in event data port int { Queue_Size => 42;};
P5 : out event data port int;
P6 : in event data port int {Queue_Size => 1;};
P7 : out data port int; -- XXX
properties
Dispatch_Protocol => Periodic;
Period => 1000 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "period";
Source_Text => ("torture.c");
end Per1;
thread Spo1
features
P1 : in event data port int { Queue_Size => 42;};
P2 : in event data port int { Queue_Size => 42;};
P3 : in data port int;
properties
Dispatch_Protocol => Sporadic; -- Concurrency configuration
Period => 100 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source