diff --git a/doc/about.rst b/doc/about.rst index 5e85f49f..b429fa9a 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -1,5 +1,3 @@ - - .. _about: ================ @@ -65,4 +63,3 @@ Copyright Information If you have any questions regarding this document, its copyright, or publishing this document in non-electronic form, please contact us. - diff --git a/doc/bug.rst b/doc/bug.rst deleted file mode 100644 index 3271cf33..00000000 --- a/doc/bug.rst +++ /dev/null @@ -1,8 +0,0 @@ -Submitting a bug -================ - -To submit a bug report, please follow the following steps, you may then use Ocarina bug tracking system. -See Ocarina main web site for more details. - -.. include:: PROBLEM-REPORT-FORM - :literal: \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py index e238ed65..4b7fa63c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -261,7 +261,7 @@ def get_version(): # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'ocarina.tex', u'Ocarina Documentation', - u'Jerome Hugues', 'manual'), + u'Julien Delange, Jerome Hugues, Bechir Zalila', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -320,4 +320,11 @@ def get_version(): # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'http://docs.python.org/': None} +intersphinx_mapping = {'https://docs.python.org/': None} + + +def setup(sphinx): + sys.path.append(os.path.abspath('.')) + sys.path.append(os.path.abspath('./util/')) + from AADLLexer import AADLLexer + sphinx.add_lexer("aadl", AADLLexer()) diff --git a/doc/index.rst b/doc/index.rst index 9b48dafd..f26923b9 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -14,11 +14,11 @@ Ocarina User's Guide introduction installation usage + scenario + polyorb-hi-c osate-ocarina python editors - bug + ocarina_config gfdl annexes - - diff --git a/doc/installation.rst b/doc/installation.rst index 0be4586c..34bca11e 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -47,7 +47,7 @@ Optional components: Semi-automated build instructions ################################# -The `ocarina-build https://github.com/OpenAADL/ocarina-build/`_ +The `ocarina-build `_ repository proposes a script, `build_ocarina.sh`, to get source code, compile and test Ocarina. diff --git a/doc/introduction.rst b/doc/introduction.rst index 6639138d..9cdc3322 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -1,4 +1,3 @@ - .. _introduction: ============ @@ -169,3 +168,16 @@ a complete model. :align: center ASSERT MPC Case study + +Ocarina concepts +################ + +Ocarina uses the following set of definitions : + +.. index:: scenario files + +* A *scenario file* is a specific AADL system that controls the behavior of Ocarina through various properties, see :ref:`scenariofiles`. + +.. index:: root system + +* A *root system* is the root of an AADL model; it is a system implementation without feature. As a closed system, it has definitions required for complete processing by Ocarina: processors, threads, processes, etc. diff --git a/doc/ocarina_config.rst b/doc/ocarina_config.rst new file mode 100644 index 00000000..8ff6f133 --- /dev/null +++ b/doc/ocarina_config.rst @@ -0,0 +1,17 @@ +===================== +Ocarina property sets +===================== + +Deployment +########## + +.. literalinclude:: ../resources/deployment.aadl + :language: aadl + +.. _ocarina_config: + +Ocarina_Config +############## + +.. literalinclude:: ../resources/ocarina_config.aadl + :language: aadl diff --git a/doc/polyorb-hi-c.rst b/doc/polyorb-hi-c.rst new file mode 100644 index 00000000..64d5a408 --- /dev/null +++ b/doc/polyorb-hi-c.rst @@ -0,0 +1,843 @@ +.. _polyorb-hi-c: + +############ +PolyORB-HI/C +############ + +About +##### + +PolyORB-HI/C is a middleware for High-Integrity Systems, it inherits +most concepts of the schizophrenic middleware *PolyORB* while being +based on a complete new source code base, compatible with the +Ravenscar profile and the restrictions for High-Integrity systems. + +PolyORB-HI/C acts as an execution runtime for the AADL language. In +this context, Ocarina acts as a compiler, turning an AADL model into C +code that uses low-level constructs provided by PolyORB-HI/C. + +The generated code is in charge of allocating all required ressources +(threads, buffers, message queue), configure communication stacks, +marshallers and concurrency structures. + +Supported Platforms +################### + +PolyORB-HI-C has been compiled and sucessfully tested on + +Native platforms + +- Linux +- Mac OS X +- FreeBSD +- Windows + +Embedded platforms + +- AIR Hypervisor +- FreeRTOS (alpha stage) +- RTEMS +- Xenomai +- XtratuM + +.. note:: when using RTEMS operating system, you have to define the :command:`RTEMS_MAKEFILE_PATH` environment variable. See RTEMS documentation for more details. + +Tree structure +############## + +PolyORB-HI-C source directory has the following tree structure: + +- :file:`doc/`: documentation, +- :file:`examples/`: set of examples to test PolyORB-HI-C +- :file:`share/`: common files (aadl files used by Ocarina, makefiles, ...) +- :file:`src/`: core of PolyORB-HI +- :file:`src/drivers`: device drivers supported by PolyORB-HI-C +- :file:`tools/`: some script to handle the packaging and a verification tool to check if the binaries are compliant with the POSIX restrictions +- :file:`COPYING3` and :file:`COPYING.RUNTIME`: licence information +- :file:`README`: short description of the distribution + +When installed with Ocarina, in :file:`$OCARINA_PATH` directory: + +- documentation is in :file:`$OCARINA_PATH/share/doc/ocarina` +- examples are in :file:`$OCARINA_PATH/examples/ocarina/polyorb-hi-c/` +- runtime files are in :file:`$OCARINA_PATH/include/ocarina/runtime/polyorb-hi-c/` + +Generating code from an AADL model +################################## + +To build your own system, you have to select the PolyORB-HI/C backend, +either using a scenario file or the command line. + +- To use a scenario file, refer to :ref:`scenariofiles` + +- To use command line, you have to select the :file:`polyorb_hi_c` backend, e.g. by using the command :command:`ocarina -g polyorb_hi_c `. Refer to :ref:`ocarinacli` for more details . + +Code generation towards PolyORB-HI/C +#################################### + +The :code:`ping` example +------------------------ + +In the following, and for each component of the distributed +application, we give the AADL entities that are used to model this +component, and then the transformation rules used by the code +generator to generate C code from these entities. + +The mapping rules will be illustrated using the following simple +example of a distributed application: + +@image{fig/ping, 12cm} + +The figure above shows the architecture of the :code:`ping` example: a +client, which is a process containing one single *periodic* thread, +sends a message to the server which is a process containing one +*sporadic* thread that handles incoming ping messages from the +client. Each node of the :code:`ping` application runs on a different +machine. + +In this chapter, we first present the AADL modeling patterns used to +define a distributed application. Then, we give the rules applied to +map AADL entities onto instances of PolyORB-HI/C elements. + +In the following, we detail only the rules that are directly related +to the distributed application as a whole system. The rules that are +specific to the components of the distributed application are +explained in the sections that deals with these respective components. + +Mapping AADL :code:`system` +--------------------------- + +A full system is captured using a root system. The system +implementation shown on the following example models such system. + +.. literalinclude:: source/ping/ping.aadl + :language: aadl + +For each node (process) of the system, we instantiate a subcomponent +in the system implementation, and bind it to a :code:`processor` +component. This processor will configure the build target. + +We use the :code:`properties` section of the AADL :code:`system` (see +@ref{Hosts` for more details) to map the different nodes on the +different platforms of the distributed application. The +:code:`connections` section of the system implementation models the +connections between the different nodes of the application. + +An AADL :code:`system` is mapped into a hierarchy of directories: + +* the root directory of the distributed application has the same name + as the root system implementation, in lower case, all dot being + converted into underscores. This directory is the root of the + directory hierarchy of the generated C code. + +* for each node of the distributed application, a child directory + having the same name as the corresponding process subcomponent (in + lower case) is created inside the root directory. This child + directory will contain all the code generated for the particular + node it was created for (see @ref{Distributed application nodes} for + more details). + +Mapping AADL :code:`process` +---------------------------- + +We use the :code:`process` component category to model an application +node (e.g. an element that would ultimately become a Unix process, an +embedded application or an ARINC653 partition). The process +implementation shown in the listing below shows such system. + +.. literalinclude:: source/ping/node_a_model.aadl + :language: aadl + +For each thread that belongs to a node of the distributed application, +we instantiate a subcomponent in the process implementation. For each +connection between a node and another, a :code:`port` feature has to be +added to both nodes with the direction :code:`out` for the source and +:code:`in` for the destination (see @ref{Connections} for more details +on connections mapping). + +Elements associated to this process (threads, subprograms, data types, +etc) are generated in a child directory of the root system directory. +This directory has the same name as the process *subcomponent* +instance relative to the handled node in the system implementation +that model the distributed application, in lower case. + +For example, all the entities relative to the process :code:`A.Impl` +of the :code:`Ping` example are generated in the directory +:code:`ping_impl/node_a`. + +The following paragraphs list the C compilation units that are +created for each node of the distributed application. + +Marshallers functions +^^^^^^^^^^^^^^^^^^^^^ + +The marshallers functions are used to put all request and types values +in a message in order to send them through a network connections. All +marshalling functions are declared in the file :code:`marshallers.c`. + +However, PolyORB-HI-C can also use third-party marshallers. It can +rely on the marshallers generated for ASN1 encoding. Details about +ASN1 marshallers are provided in the next section. + +@subsubsection Using ASN1 marshallers + +With the ASN1 tools from Semantix +(see. @url{http://www.semantix.gr/assert/}), you can convert ASN1 +declarations into AADL models. Then, these models can be used with +AADL components and PolyORB-HI-C relies on Semantix tools to +automatically generates C code that implements the ASN1 types. + +For that purpose, you need to install the program :code:`asn2aadlPlus` +and :code:`asn1cc`. These programs are freely available on +@url{http://www.semantix.gr/assert/}. Then, when you use ASN1 types +with your AADL model (with the AADL files generated with +:code:`asn2aadlPlus`), PolyORB-HI-C uses the generated code from ASN1 +descriptions and integrate it to marshall data. + +Node activity +^^^^^^^^^^^^^ +We denote *activity* the set of the actions performed by one +particular node which are not triggered by other nodes. All the +periodic threads of a node are part of the node activity. + +The code related to the node activity is generated in an C file +with the name :file:`activity.c`. An example is shown below : + +.. literalinclude:: source/ping/activity.c + :language: c + +All the naming rules explained in @ref{Whole distributed application} +are also applied to map the package name. This file contains all the +routines mapped from the periodic threads that belong to the handled +node (see @ref{Threads} for more details on thread mapping). This +package contains also the instances of shared objects used in this +node (see @ref{Data} for more details). If the node does not contain +any *periodic* thread nor shared objects, there is no +:file:`activity.c` file generated for this node. Thus, the node +:code:`B` in the :code:`Ping` example does not have a +:file:`activity.c` package. + +Data types +^^^^^^^^^^ + +All the data types mapped from AADL data components and used by a +particular node of a distributed application are gathered in a +separate C file called :file:`types.h`. + +For more detail on the mapping of data components, see @ref{Data}. + +Subprograms +^^^^^^^^^^^ + +The mapping of all AADL subprogram components used by a particular +node is generated in a separate file called :file:`subprograms.c`. +The content of the file is shown in the following example: + +For more detail on the mapping of subprogram components, see +@ref{Subprograms}. + +Deployment information +^^^^^^^^^^^^^^^^^^^^^^ + +The deployment information is the information each node has on the +other nodes in the distributed applications. This information is used, +to send a request to another node or to receive a request from +another node. The deployment information is generated for each node in +two C files : :file:`deployment.h` and :file:`deployment.c`. + +The file :file:`deployment.h` contains the following types + +* a first type called :code:`__po_hi_node_t`. For each node in the + application we create an enum whose name is mapped from the node + *instance* declared in the system implementation to which we + concatenate the string *_k*. All the naming rules listed in + @ref{Whole distributed application} have to be respected. + +* a second type called :code:`__po_hi_entity_t`. For each thread in the + the application, we declare an enum. + +* a third type called :code:`__po_hi_task_id`. For each thread that + run on the current node. + +* a fourth type called :code:`__po_hi_entity_server_t`. For each node + that may communicate with the current node, we add a value in this + enum. It will be used by the transport layer. Please note that at least + one server is declared : the value :code:`invalid_server`. + +* a fifth type called :code:`__po_hi_port_t` that contains all global port + identifier. + +More, this file contains the following maccros : + +* :code:`__PO_HI_NB_ENTITIES` is the number of entities in + the whole distributed system. + +* :code:`__PO_HI_NB_TASKS` is the number of the tasks that will + be started on the current node + +* :code:`__PO_HI_NB_NODES` is the number of nodes in the + distributed system. + +* :code:`__PO_HI_PROTECTED` is the number of protected objects + use on the current node. + +* :code:`__PO_HI_NB_PORTS` that represent the total number of ports + in the whole distributed system. + +* :code:`__PO_HI_NB_DEVICES` that represent the total number of devices + in the whole distributed system. + +The file :file:`deployment.c` contains the following variables : + +* :code:`mynode` variable which has the value of the + handled node. + +* :code:`__po_hi_entity_table` variable is used to know on + which node an entity runs. + +* :code:`__po_hi_port_global_to_local` variable is used + to convert a global port identifier to a local port identifier + +* :code:`__po_hi_port_global_to_entity` variable is used + to know on which entity a given port is. This table is used + convert a global port identifier to an entity identifier. + +* :code:`__po_hi_uint8_t __po_hi_deployment_endiannesses` + variable details which the endianess of each node. It is an array + which size is :code:`__PO_HI_NB_NODES`. + +* :code:`__po_hi_port_to_device` is an array which size is + :code:`__PO_HI_NB_PORTS`. For each port, it indicates the + value of the device identifier that handles it. + +* :code:`__po_hi_port_global_model_names` is an array which size is + :code:`__PO_HI_NB_PORTS`. For each port, it contains the name of the + port. + +* :code:`__po_hi_port_global_names` is an array which size is + :code:`__PO_HI_NB_PORTS`. For each port, it contains the name + generated by the code generator. + +* :code:`__po_hi_devices_naming` is an array which size is + :code:`__PO_HI_NB_DEVICES`. For each deivce, it contains all relevant + information for their configuration. The configuration string is + deduced from the :code:`Configuration` property associated with the + device. + +The following example shows the :code:`Deployment` package relative to +the node :code:`A` of the :code:`Ping` example: + +.. literalinclude:: source/ping/deployment.h + :language: c + +OS Configuration +^^^^^^^^^^^^^^^^ + +A host is the set formed by a processor and an operating system (or +real-time kernel). + +To model both the processor and the OS, we use the :code:`processor` +AADL component. The characteristics of the processor are defined using +AADL properties. For example, if our distributed application uses +an IP based network to make its node communicate, then each host must +have an IP address. Each host must also precise its platform (native, +LEON...). The listing following example shows how to express this +using a custom property set. + +.. literalinclude:: source/ping/hardware.aadl + :language: aadl + +To map an application node (processor) to a particular host, we use +the :code:`Actual_Processor_Binding` property. The following example +shows how the node :code:`Node_A` is mapped to the processor +:code:`Proc_A` in the :code:`Ping` example. + +.. literalinclude:: source/ping/processor_binding.aadl + :language: aadl + +.. :lines: 3,5 + +The C generated code concerning the code generation to model host +mapping is located in the :file:`naming.c` file. More precisely, the +:code:`node_addr` and :code:`node_port` contains, for each node, the +information related to its host. These information are dependant on +the transport mechanism used in the distributed application. + +Mapping AADL :code:`threads` +---------------------------- + +The threads are the active part of the distributed application. A node +must contain at least one thread and may contain more than one +thread. In this section, we give the AADL entities used to model +threads. Then, we give the mapping rule to generate C code +corresponding to the periodic and aperiodic threads. + +The rules are listed relatively to the packages generated for the +nodes and for the distributed application (see @ref{Distributed +application nodes} and @ref{Whole distributed application}). Only +rules that are related directly to a thread as a whole subsystem are +listed here. + +AADL entities +^^^^^^^^^^^^^ + +AADL :code:`thread` components are used to model execution flows. + +The :code:`features` subclause of the thread component declaration +describes the thread interface. The ports that may be connected to the +ports of other threads, enclosing process, etc. + +The :code:`properties` subclause of the thread implementation lists +the properties of the thread such as its priority, its nature +(periodic, sporadic) and many other properties ares expressed using +AADL properties. + +The :code:`calls` subclause of the thread implementation contains the +sequences of subprograms the thread may call during its job (see +@ref{Subprograms} for more details on the subprogram mapping). If the +thread job consist of calling more than one subprogram, it is +**mandatory** to encapsulate these calls inside a single subprogram +which will consist the thread job. + +The :code:`connections` section of a thread implementation connects +the parameters of the subprograms called by the thread to the ports of +the threads or to the parameters of other called subprograms in the +same thread. + +.. literalinclude:: source/ping/thread_a.aadl + :language: aadl + +The listing above shows the thread :code:`P` which belongs to the +process :code:`A.impl` in the :code:`Ping` example. We can see that +:code:`P` is a periodic thread with a period of 1000ms, that this +thread has a unique :code:`out event data port` and that at each +period, the thread performs a call to the :code:`Do_Ping_Spg` +subprogram whose :code:`out parameter` is connected to the thread port. + +Mapping rules for periodic threads +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Periodic threads are cyclic threads that are triggered by and only by +a periodic time event. between two time events the periodic threads do +a non blocking job and then they sleep waiting for the next time +event. + +The majority of the code generated for the periodic threads is put in +the :file:`activity.c` file generated for the application node +containing the handled thread. Each periodic thread is created in the +main function (:file:`main.c` file) with the +:code:`__po_hi_create_periodic_task` function-call. + +The generated code in the :file:`activity.c` file is a parameterless +function that represents the thread job. The defining identifier of +the function is mapped from the thread instance name in the process +that models the node, to which we append the string +:code:`_job`. All the naming rules listed in @ref{Whole distributed +application} have to be respected. The body of this subprogram calls +the subprograms mapped from the subprogram calls the thread +performs. Then, it sends the request to the remote threads it may be +connected to. Finally, at the end of the function, we make a call to +the :code:`__po_hi_wait_next_period()` with the task identifier as +parameter. This call ensure that we wait the next period before we +start the function again. + +The generated code in :file:`main.c` file is a function call that creates +a periodic task. The task is created with the function +:code:`__po_hi_create_periodic_task`. This creates a periodic task with +the wanted properties at the elaboration time of the node. The package +instantiation name is mapped from the thread instance name in the process +that model the node, to which we append the string :code:`_k`. All the +naming rules listed in @ref{Whole distributed application} have to be +respected. The function-call takes the following parameters: + +* the enumerator corresponding to the thread + +* the task period, + +* the task priority. If the user did not specify a priority, then + :code:`__PO_HI_DEFAULT_PRIORITY` is used, + +* the task job which corresponds to the subprogram :code:`_job`. + +The following example shows the generated code for the periodic thread +:code:`Pinger` from the node :code:`Node_A` of the :code:`Ping` example: + +.. literalinclude:: source/ping/activity.c + :language: c + +Mapping rules for sporadic threads +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sporadic threads are cyclic threads that are triggered by the arrival +of a sporadic event. The minimum inter-arrival time between two +sporadic events is called the period of the sporadic thread. + +The majority of the code generated for the sporadic threads is put in +the :file:`activity.c` file generated for the application node +containing the handled thread. Each periodic thread is created in the +main function (:file:`main.c` file) with the +:code:`__po_hi_create_sporadic_task` function-call. + +The generated code in the :file:`activity.c` file is a parameterless function +that represents the thread job. The defining identifier of the function +is mapped from the thread instance name in the process that models the node, +to which we append the string :code:`_job`. All the naming rules listed +in @ref{Whole distributed application} have to be respected. In the body +of the function, the thread will wait for an event (most of the time : a +message from another entity). + +The generated code in :file:`main.c` file is a function-call that creates +the sporadic task. The task is created with the function +:code:`__po_hi_create_sporadic_task`. This creates a sporadic task with +the wanted properties at the elaboration time of the node. The package +instantiation name is mapped from the thread instance name in the process +that model the node, to which we append the string :code:`_k`. All the +naming rules listed in @ref{Whole distributed application} have to be +respected. The function-call takes the following parameters: + +* the enumerator corresponding to the thread + +* the task priority. If the user did not specify a priority, then + :code:`__PO_HI_DEFAULT_PRIORITY` is used, + +* the task job which corresponds to the subprogram + :code:`_job`. + +The following example shows the generated code for the sporadic thread +:code:`Ping_Me` from the node :code:`Node_B` of the :code:`Ping` example. + +.. literalinclude:: source/ping/node_b_activity.c + :language: c + +Deployment information +---------------------- + +As said in @ref{Distributed application nodes}, the files +:file:`deployment.h` and :file:`deployment.c` are generated for each +node in the distributed application. For each thread port in the whole +distributed application, we declare an enumerator in this type. The +defining identifier of the enumerator is mapped from the process +subcomponent name and the thread subcomponent name as follows: +:code:`__K`. + +For each that that may communicate, we generate the following elements + +* A variable called :code:`__po_hi__local_to_global` (in + :code:`deployment.c`) that is used to convert a local port identifier + of the thread to a global one. + +* A type :code:`__po_hi__t` that will contain + on local port identifier. + +* A macro :code:`__po_hi__nb_ports` that will contain + the number of ports for the thread. + +For these elements, all the naming rules listed in @ref{Whole +distributed application} must be respected. + +.. literalinclude:: source/ping/deployment.h + :language: c + +.. literalinclude:: source/ping/deployment_c.c + :language: c + +The listing above shows the generated :code:`__po_hi_entity_server_t` and +:code:`entity_table` for the nodes :code:`B` from the +:code:`Ping` example. + +Mapping of AADL :code:`ports` +----------------------------- + +Threads can contain one or several ports. To handle them, we declared several +arrays in the :file:`activity.c` + +* :code:`__po_hi__destinations` : array for each port of + the thread which contains all destinations of the port. + +* :code:`__po_hi__woffsets` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__offsets` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__used_size` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__empties` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__first` : array (size = number of ports + in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__recent` : array (size = number of ports + in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__queue` : array (size = size of the + global queue for the thread) used by \pohic to handle the global + queue. + +* :code:`__po_hi__total_fifo_size` : variable that + contains the size of the global queue. It is the sum of all port + size for the thread. + +* :code:`__po_hi__history` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__n_dest` : array (size = number of ports + in the thread) used by \pohic for the global queue of the + thread. It contains the number of destinations for each port of + the thread. + +* :code:`__po_hi__fifo_size` : array (size = number of + ports in the thread) used by \pohic for the global queue of the + thread. + +* :code:`__po_hi__destinations` : array (size = number of ports + in the thread) that contains all destinations for each port. + +Mapping of AADL :code:`Connections` +----------------------------------- + +The connections are entities that support communication between the +application nodes. In this section, we present the AADL entities used +to model connection between nodes. + +A connection between two nodes of the system is modeled by: + +* The :code:`ports` features that exist on each one of the nodes. Ports + can be declared inside processes or threads. The direction of the + port (:code:`in`, :code:`out` or :code:`in out`) indicates the + direction of the information flow. + +* The :code:`connections` section in the system implementation + relative to the distributed application and in the process and + thread implementations. + +.. literalinclude:: source/ping/port_cnx.aadl + :language: aadl + +The listing above shows the connection between the node :code:`A` and +:code:`B` in the system implementation. + +The nature of the :code:`port` (*event port*, *data port* or *event +data port*) depends on the nature of the connection between the two +nodes: + +* if the message sent from one node to another node is only a + triggering event and contains no data, we create an *event* port. + +* if the message sent from one node to another node is a data message + but it does not trigger the receiver thread, we create a *data* + port. + +* if the message sent from one node to another node is a data message + that triggers the receiver thread, we create an @i{event data} port. + +In a distributed system, when we send any data to a node, we need to +put them in a stream. We call that the marshall operation. On the +other hand, find data in a stream is called the unmarshall +operation. In each distributed application, we generate marshallers +for each types and request. These functions will marshall/unmarshall +data in/from a message. + +All marshallers functions are generated in a file called +:file:`marshallers.c`. The marshall (or unmarshall) functions for +request are prefixed by the string :code:`__po_hi_marshall_request_` +(or :code:`__po_hi_unmarshall_request_`). Marshall (or unmarshall) +functions for types are prefixed by the string +:code:`__po_hi_marshall_type_` (or +:code:`__po_hi_unmarshall_type_`). Each function has the name of the +type or the request it marshalls. + +Finally, a function :code:`__po_hi_marshall_request` and +:code:`__po_hi_unmarshall_request` is generated to handle all +requests. Then, is called the appropriate function to call to marshall +or unmarshall the data. + +.. literalinclude:: source/ping/marshallers.c + :language: c + +Mapping of AADL :code:`Subprograms` +----------------------------------- + +Subprograms are used to encapsulate behavioural aspects of the +application. + +To model a subprogram, we use the :code:`subprogram` AADL component +category. The parameters of the subprogram are specified in the +:code:`features` subclausen of the component declaration. If the +subprogram does only the job of calling other declared subprograms, +then the :code:`calls` subclause of the subprogram implementation has +to contain such calls. To point to the actual implementation of the +subprogram, we use the AADL properties. + +The following example shows the AADL model for the :code:`Do_Ping_Spg` +from the :code:`Ping` example. It precises that the C implementation of +the subprogram is located in the function :code:`user_ping`. The file +which contains this function must be stored with the aadl model. + +Subprograms are generally called by threads or by other subprograms. +To express this, we use the :code:`calls` subclause of a component +implementation. Then we perform all the connections between the called +subprograms parameters and the caller components ports (or parameters +if the caller is a subprogram). + +The following listing shows the calls and connections sections of the +periodic thread :code:`P` in the :code:`Ping` example. + +.. literalinclude:: source/ping/do_ping_spg.aadl + :language: aadl + +Each subprogram instance model a hand-written function. In the +:file:`subprograms.c` file, we declare the definition of this function +and we generate a new one that will call the one provided by the user. + +The following listing shows the calls and connections sections of the +subprogram :code:`ping_spg` in the :code:`Ping` example. + +.. literalinclude:: source/ping/subprograms.c + :language: c + +For each subprogram call in a thread, we generate an C subprogram call +to the subprogram implementing the thread and given by mean of the +AADL properties. + +On the client side, the function :code:`sth_Job` begins by calling the +subprogram in its call sequence. then it calls the stubs of all the +subprogram it is connected to. + +On the server side, and in the function of the +:code:`process_request`, the subprogram implementation corresponding +to the operation (coded in the message) is called. + +Mapping of AADL :code:`data` +---------------------------- + +The data are the messages exchanged amongst the nodes of the +application. + +AADL :code:`data` components are used to model data exchanged in the +distributed application. Properties are used to precise the nature of +the data. To model a data structure (which contains fields of others +data types) we use data component implementation and we add a +subcomponent for each field of the structure. + +The simple data types that can be modeled using AADL are + +* boolean, +* integer, +* fixed point types, +* characters, +* wide characters + +.. literalinclude:: source/ping/simple_types.aadl + :language: aadl + +The complex data types that can be modeled using AADL are + +* Bounded strings +* Bounded wide strings +* Bounded arrays of a type that can be modeled +* Structure where the fields types are types that can be + modeled + +.. literalinclude:: source/ping/complex_types.aadl + :language: aadl + +Data components may also contain subprogram features. Depending on +the AADL properties given by the user. These component may denote a +protected object or a non protected object. In either case, they are +used to model a data structure that can be handled only by the +subprograms it exports (which are the feature of the data structure). + +@include protected_object_types.texi + +The example above shows an example of +a protected data component (@code{Protected_Object.Impl}). +The object has a single field (subcomponent) which is a simple data +component. Note that the description of the feature subprograms of +these data component is a little bit different from the description of +classic subprograms: each feature subprogram must have a full access +to the internal structure of the object type. To achieve this, we use +the @code{require data access} facility of AADL. To model a non +protected data component, user should simply change the +@code{ARAO::Object_Kind => Protected;} into +@code{ARAO::Object_Kind => Non_Protected;} in the implementation +of data component. + +@subsection C mapping rules + +Data component declaration are mapped into C type declaration in the +file @code{types.h}. +In the following we give the C type corresponding to each data component +type that could be modeled. + +@subsubsection Simple types + +Simple data components are mapped into an C type definition whose +defining identifier is mapped from the component declaration +identifier (with respect to the naming rules listed +in @ref{Whole distributed application}) and whose parent subtypes is: +@itemize @bullet + @item @code{int} for boolean data types + @item @code{int} for integer data types + @item @code{float} for fixed point types + @item @code{chat} for character data types +@end itemize + +@subsubsection Bounded strings and wide strings + +Bounded strings and wide strings are not supported in the C generator at this +time. + + +@subsubsection Bounded arrays + +Bounded arrays and wide strings are not supported in the C generator at this +time. + + +@subsubsection Data structures + +Data structures are mapped into a C structure defined in the file @file{types.h}. +The identifier of the record type is mapped from the data component name +with respect to the naming rules given in @ref{Whole distributed +application}. Each field defining identifier is mapped from the +subcomponent name given in the data component implementation with the +same naming rules. The type of the field is the C type mapped from +the data corresponding component. The following example shows the C +mapping of the data structure defined given earlier in this part. + +@include data_struct.h.texi + +@subsubsection Object types + +Protected object types are mapped into an a C structure. We add automatically a +member in the structure with the type @code{__po_hi_protected_id} and the name +@code{protected_id}. This member +will identify the protected type in the distributed system. All other members of +the object are declared as in Data Structures (see previous subsection). The +features subprograms of the object types are declared in the @file{types.h} +file, whereas the body of these functions are defined in the @file{types.c} +file. Moreover, the value of the @code{protected_id} must be initialized. This +is done in the main function (@file{main.c}), before the initialization. +All the naming conventions given in @ref{Whole distributed application} have to +be respected. The following example shows the specification of the protected type +mapped from the @code{Protected_Object.Impl} shown earlier in this part. We show +the files @file{types.h}, @file{types.c} and @file{main.c} (that initialize the +@code{protected_id} member of the structure. + +@include toy_types.h.texi +@include toy_types.c.texi +@include toy_main.c.texi + +Non protected object types are mapped similarly to protected object +types. The only difference, is that instead of creating a protected +type, we create a generic parameterless nested package. diff --git a/doc/python.rst b/doc/python.rst index 11de409e..16df59fe 100644 --- a/doc/python.rst +++ b/doc/python.rst @@ -21,7 +21,8 @@ At run-time, the following environment variables must be set up:: Example ####### -Here is a small examples illustrating Python API capabilities +The following example illustrates the capabilities of the Python API, +it implements a visitor that iterates of the AADL model elements: .. literalinclude:: ../resources/runtime/python/test/visitor.py :language: python @@ -34,8 +35,5 @@ The following lists all functions defined in the `ocarina` module .. automodule:: ocarina.ocarina :members: -.. automodule:: lmp - :members: - -.. automodule:: ocarina_common_tools +.. automodule:: ocarina.lmp :members: diff --git a/doc/scenario.rst b/doc/scenario.rst new file mode 100644 index 00000000..6b3424ea --- /dev/null +++ b/doc/scenario.rst @@ -0,0 +1,36 @@ +.. _scenariofiles: + +============== +Scenario files +============== + +AADL scenario files are a very simple way to set build options when +using Ocarina. AADL scenario may consist of more than one AADL file. + +Scenario files rely on the system component category to configure all +elements of the system to be processed. The following scenario file +illustrates this feature. It extends an existing scenario file (see +below) with project-specific configuration data: + +.. literalinclude:: source/scenario.aadl + :language: aadl + +Scenario files rely on specific properties: + +* property :code:`AADL_Files` lists all files that are part of the system; + +* property :code:`Root_System_Name` is the name of the Root System; + +* property :code:`Generator` is the name of the generator (or back-end) to use + +.. note:: The definition of scenario-specific properties may be found in section :ref:`ocarina_config`. + +:command:`ocarina -x ` will cause the scenario +file to be processed. In addition, the flag :code:`-b` will +compile generated source files. + +:file:`ocarina_library.aadl` +############################ + +.. literalinclude:: ../resources/AADLv2/ocarina_library.aadl + :language: aadl diff --git a/doc/source/example.aadl b/doc/source/example.aadl new file mode 100644 index 00000000..1397dd79 --- /dev/null +++ b/doc/source/example.aadl @@ -0,0 +1,13 @@ +package foo_pkg +public + -- sample AADL model + thread foo + features + a : in event data port; + properties + Dispatch_Protocol => Periodic; + Compute_Execution_Time => 5 ms .. 10 ms; + Source_Text => "foobar"; + end foo; + +end foo_pkg; \ No newline at end of file diff --git a/doc/source/ping/activity.c b/doc/source/ping/activity.c new file mode 100644 index 00000000..d5e04458 --- /dev/null +++ b/doc/source/ping/activity.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern __po_hi_entity_t __po_hi_port_global_to_entity[__PO_HI_NB_PORTS]; +extern __po_hi_port_t __po_hi_port_global_to_local[__PO_HI_NB_PORTS]; +__po_hi_int8_t __po_hi_data_source_local_destinations[1] = {ping_me_global_data_sink}; +__po_hi_uint8_t __po_hi_pinger_woffsets[__po_hi_pinger_nb_ports]; +__po_hi_uint8_t __po_hi_pinger_offsets[__po_hi_pinger_nb_ports]; +__po_hi_uint8_t __po_hi_pinger_used_size[__po_hi_pinger_nb_ports]; +__po_hi_uint8_t __po_hi_pinger_empties[__po_hi_pinger_nb_ports]; +__po_hi_uint8_t __po_hi_pinger_first[__po_hi_pinger_nb_ports]; +__po_hi_uint8_t __po_hi_pinger_recent[__po_hi_pinger_nb_ports * sizeof(__po_hi_request_t)]; +__po_hi_uint8_t __po_hi_pinger_queue[0 * sizeof(__po_hi_request_t)]; +__po_hi_uint16_t __po_hi_pinger_total_fifo_size = 0; +__po_hi_port_t __po_hi_pinger_history[0]; +__po_hi_uint8_t __po_hi_pinger_n_dest[__po_hi_pinger_nb_ports] = {1}; +__po_hi_int8_t __po_hi_pinger_fifo_size[__po_hi_pinger_nb_ports] = {__PO_HI_GQUEUE_FIFO_OUT}; +__po_hi_uint8_t* __po_hi_pinger_destinations[__po_hi_pinger_nb_ports] = {__po_hi_data_source_local_destinations}; +/* Periodic task : Pinger*/ + +/****************/ +/* pinger_job */ +/****************/ + +void* pinger_job () +{ + simple_type data_source_request_var; + __po_hi_request_t data_source_request; + + __po_hi_gqueue_init(node_a_pinger_k,__po_hi_pinger_nb_ports,__po_hi_pinger_queue,__po_hi_pinger_fifo_size,__po_hi_pinger_first,__po_hi_pinger_offsets,__po_hi_pinger_woffsets,__po_hi_pinger_n_dest,__po_hi_pinger_destinations,__po_hi_pinger_used_size,__po_hi_pinger_history,__po_hi_pinger_recent,__po_hi_pinger_empties,__po_hi_pinger_total_fifo_size); + __po_hi_wait_initialization(); + while (1) + { + /* Call implementation*/ + do_ping_spg(&(data_source_request_var)); + /* Set the OUT port values*/ + data_source_request.vars.pinger_global_data_source.pinger_global_data_source = data_source_request_var; + data_source_request.port = data_source_request_var; + __po_hi_gqueue_store_out(node_a_pinger_k,pinger_local_data_source,&(data_source_request)); + /* Send the OUT ports*/ + __po_hi_gqueue_send_output(node_a_pinger_k,pinger_global_data_source); + __po_hi_wait_for_next_period(node_a_pinger_k); + } +} + + +/**************************/ +/* __po_hi_main_deliver */ +/**************************/ + +void __po_hi_main_deliver + (__po_hi_msg_t* message) +{ + __po_hi_request_t request; + __po_hi_entity_t entity; + + __po_hi_unmarshall_request(&(request),message); + entity = __po_hi_port_global_to_entity[request.port]; + switch (entity) + { + default: + { + break; + } + } +} + + diff --git a/doc/source/ping/complex_types.aadl b/doc/source/ping/complex_types.aadl new file mode 100644 index 00000000..d93820d1 --- /dev/null +++ b/doc/source/ping/complex_types.aadl @@ -0,0 +1,42 @@ +-- Bounded string type + +data String_Data +properties + ARAO::Data_Type => String; + ARAO::Max_Length => ; +end String_Data; + +-- Bounded wide string type + +data W_String_Data +properties + ARAO::Data_Type => Wide_String; + ARAO::Max_Length => ; +end W_String_Data; + +-- Bounded array type: Only the component implementation should be +-- used in the ports or parameters! + +data Data_Array +properties + ARAO::Length => ; +end Data_Array; + +data implementation Data_Array.i; +subcomponents + -- Only one subcomponent + Element : data String_Data; +end Data_Array.i; + +-- Data structure type: Only the component implementation should be +-- used in the ports or parameters! + +data Data_Structure +end Data_Structure; + +data implementation Data_Structure.i; +subcomponents + Component_1 : data String_Data; + Component_2 : data W_String_Data; + Component_3 : data Data_Array.i; +end Data_Structure.i; \ No newline at end of file diff --git a/doc/source/ping/data_struct.h b/doc/source/ping/data_struct.h new file mode 100644 index 00000000..0c03e989 --- /dev/null +++ b/doc/source/ping/data_struct.h @@ -0,0 +1,6 @@ +typedef struct +{ + pos_internal_type field1; + pos_internal_type field2; + +} pos_impl; diff --git a/doc/source/ping/deployment.h b/doc/source/ping/deployment.h new file mode 100644 index 00000000..7a64b4af --- /dev/null +++ b/doc/source/ping/deployment.h @@ -0,0 +1,65 @@ +#ifndef __DEPLOYMENT_H_ +#define __DEPLOYMENT_H_ +#include +typedef enum +{ + pinger_local_data_source = 0 +} __po_hi_pinger_t; + +#define __po_hi_pinger_nb_ports 1 + +typedef enum +{ + ping_me_local_data_sink = 0 +} __po_hi_ping_me_t; + +#define __po_hi_ping_me_nb_ports 1 + +/* For each node in the distributed application add an enumerator*/ + +typedef enum +{ + node_a_k = 0, + node_b_k = 1 +} __po_hi_node_t; + +/* For each thread in the distributed application nodes, add an enumerator*/ + +typedef enum +{ + node_a_pinger_k_entity = 0, + node_b_ping_me_k_entity = 1 +} __po_hi_entity_t; + +typedef enum +{ + node_a_pinger_k = 0 +} __po_hi_task_id; + +#define __PO_HI_NB_TASKS 1 + +/* For each thread in the distributed application nodes THAT MAY COMMUNICATE*/ +/* with the current node, add an enumerator*/ + +typedef enum +{ + invalid_server = -1 +} __po_hi_entity_server_t; + +#define __PO_HI_NB_SERVERS 0 + +#define __PO_HI_NB_PROTECTED 0 + +#define __PO_HI_NB_NODES 2 + +#define __PO_HI_NB_ENTITIES 2 + +#define __PO_HI_NB_PORTS 2 + +typedef enum +{ + pinger_global_data_source = 0, + ping_me_global_data_sink = 1 +} __po_hi_port_t; + +#endif diff --git a/doc/source/ping/deployment_c.c b/doc/source/ping/deployment_c.c new file mode 100644 index 00000000..acd73066 --- /dev/null +++ b/doc/source/ping/deployment_c.c @@ -0,0 +1,5 @@ +#include +__po_hi_entity_server_t server_entity_table[__PO_HI_NB_ENTITIES] = {invalid_server,invalid_server}; +__po_hi_node_t entity_table[__PO_HI_NB_ENTITIES] = {node_a_k,node_b_k}; +__po_hi_node_t mynode = node_a_k; + diff --git a/doc/source/ping/devices.aadl b/doc/source/ping/devices.aadl new file mode 100644 index 00000000..fdfaad15 --- /dev/null +++ b/doc/source/ping/devices.aadl @@ -0,0 +1,77 @@ +package devices + +device serial_port_raw +features + serial_line : requires bus access buses::serial.i; +properties + Provided_Virtual_Bus_Class => (classifier (protocols::dummy.i)); +end serial_port_raw; + +device implementation serial_port_raw.linux +properties + Deployment::Driver_Name => "serial_linux"; + Device_Driver => classifier (devices::serial_driver.linux); + Initialize_Entrypoint => classifier (devices::spg_serial_init_linux); +end serial_port_raw.linux; + + +subprogram spg_serial_poller_linux +properties + Source_Language => C; + Source_Name => "__po_hi_c_driver_serial_linux_poller"; +end spg_serial_poller_linux; + +subprogram spg_serial_sender_linux +properties + Source_Language => C; + Source_Name => "__po_hi_c_driver_serial_linux_sender"; +end spg_serial_sender_linux; + +subprogram spg_serial_init_linux +features + data_source : out parameter types::int.i; +properties + Source_Language => C; + Source_Name => "__po_hi_c_driver_serial_linux_init"; +end spg_serial_init_linux; + +thread serial_poller +end serial_poller; + +thread implementation serial_poller.linux +calls + mycall : { + pspg : subprogram spg_serial_poller_linux; + }; +properties + Period => 1000ms; + Dispatch_Protocol => Periodic; +end serial_poller.linux; + + +thread implementation serial_poller.rasta +calls + mycall : { + pspg : subprogram spg_serial_poller_rasta; + }; +properties + Period => 1000ms; + Dispatch_Protocol => Periodic; +end serial_poller.rasta; + +abstract serial_driver +end serial_driver; + +abstract implementation serial_driver.linux +subcomponents + receiver : thread serial_poller.linux; + sender : subprogram spg_serial_sender_linux; +end serial_driver.linux; + +abstract implementation serial_driver.rasta +subcomponents + receiver : thread serial_poller.rasta; + sender : subprogram spg_serial_sender_rasta; +end serial_driver.rasta; + +end devices; diff --git a/doc/source/ping/do_ping_spg.aadl b/doc/source/ping/do_ping_spg.aadl new file mode 100644 index 00000000..9326d105 --- /dev/null +++ b/doc/source/ping/do_ping_spg.aadl @@ -0,0 +1,8 @@ +subprogram Do_Ping_Spg +features + Data_Source : out parameter Simple_Type; +properties + source_language => C; + source_name => "user_ping"; +end Do_Ping_Spg; + diff --git a/doc/source/ping/hardware.aadl b/doc/source/ping/hardware.aadl new file mode 100644 index 00000000..3f69e0fb --- /dev/null +++ b/doc/source/ping/hardware.aadl @@ -0,0 +1,5 @@ +processor the_processor +properties + ARAO::location => "127.0.0.1"; + ARAO::Execution_Platform => Native; +end the_processor; diff --git a/doc/source/ping/main.c b/doc/source/ping/main.c new file mode 100644 index 00000000..eda4bfcd --- /dev/null +++ b/doc/source/ping/main.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include +/***********************/ +/* __PO_HI_MAIN_NAME */ +/***********************/ + +__PO_HI_MAIN_TYPE __PO_HI_MAIN_NAME () +{ + + __po_hi_initialize(); + __po_hi_create_periodic_task(node_a_pinger_k,__po_hi_milliseconds(5000),2,pinger_job); + __po_hi_wait_initialization(); + __po_hi_wait_for_tasks(); + return (__PO_HI_MAIN_RETURN); +} + + diff --git a/doc/source/ping/marshallers.c b/doc/source/ping/marshallers.c new file mode 100644 index 00000000..18ddd62f --- /dev/null +++ b/doc/source/ping/marshallers.c @@ -0,0 +1,156 @@ +#include +#include +#include + +/***************************************/ +/* __po_hi_marshall_type_simple_type */ +/***************************************/ + +void __po_hi_marshall_type_simple_type + (simple_type value, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_marshall_int(value,message,offset); +} + + +/*****************************************/ +/* __po_hi_unmarshall_type_simple_type */ +/*****************************************/ + +void __po_hi_unmarshall_type_simple_type + (simple_type* value, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_unmarshall_int(value,message,offset); +} + + +/************************************************/ +/* __po_hi_marshall_request_ping_me_data_sink */ +/************************************************/ + +void __po_hi_marshall_request_ping_me_data_sink + (__po_hi_request_t* request, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_marshall_type_simple_type(request->vars.ping_me_global_data_sink.ping_me_global_data_sink,message,offset); +} + + +/**************************************************/ +/* __po_hi_unmarshall_request_ping_me_data_sink */ +/**************************************************/ + +void __po_hi_unmarshall_request_ping_me_data_sink + (__po_hi_request_t* request, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_unmarshall_type_simple_type(&(request->vars.ping_me_global_data_sink.ping_me_global_data_sink),message,offset); +} + + +/*************************************************/ +/* __po_hi_marshall_request_pinger_data_source */ +/*************************************************/ + +void __po_hi_marshall_request_pinger_data_source + (__po_hi_request_t* request, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_marshall_type_simple_type(request->vars.pinger_global_data_source.pinger_global_data_source,message,offset); +} + + +/***************************************************/ +/* __po_hi_unmarshall_request_pinger_data_source */ +/***************************************************/ + +void __po_hi_unmarshall_request_pinger_data_source + (__po_hi_request_t* request, + __po_hi_msg_t* message, + __po_hi_uint16_t* offset) +{ + + __po_hi_unmarshall_type_simple_type(&(request->vars.pinger_global_data_source.pinger_global_data_source),message,offset); +} + + +/******************************/ +/* __po_hi_marshall_request */ +/******************************/ + +void __po_hi_marshall_request + (__po_hi_request_t* request, + __po_hi_msg_t* message) +{ + __po_hi_uint16_t offset; + + offset = 0; + __po_hi_marshall_port(request->port,message); + switch (request->port) + { + case ping_me_global_data_sink: + { + __po_hi_marshall_request_ping_me_data_sink(request,message,&(offset)); + + break; + } + case pinger_global_data_source: + { + __po_hi_marshall_request_pinger_data_source(request,message,&(offset)); + + break; + } + default: + { + break; + } + } +} + + +/********************************/ +/* __po_hi_unmarshall_request */ +/********************************/ + +void __po_hi_unmarshall_request + (__po_hi_request_t* request, + __po_hi_msg_t* message) +{ + __po_hi_uint16_t offset; + + offset = 0; + __po_hi_unmarshall_port(&(request->port),message); + switch (request->port) + { + case ping_me_global_data_sink: + { + __po_hi_unmarshall_request_ping_me_data_sink(request,message,&(offset)); + + break; + } + case pinger_global_data_source: + { + __po_hi_unmarshall_request_pinger_data_source(request,message,&(offset)); + + break; + } + default: + { + break; + } + } +} + + diff --git a/doc/source/ping/naming.c b/doc/source/ping/naming.c new file mode 100644 index 00000000..5df8eb4f --- /dev/null +++ b/doc/source/ping/naming.c @@ -0,0 +1,6 @@ +#include +#include +/* Naming Table*/ +__po_hi_inetport_t node_port[__PO_HI_NB_NODES] = {__PO_HI_NOPORT,12002}; +__po_hi_inetaddr_t node_addr[__PO_HI_NB_NODES] = {__PO_HI_NOADDR,"127.0.0.1"}; + diff --git a/doc/source/ping/node_a_model.aadl b/doc/source/ping/node_a_model.aadl new file mode 100644 index 00000000..2d60b72e --- /dev/null +++ b/doc/source/ping/node_a_model.aadl @@ -0,0 +1,11 @@ +process A +features + Out_Port : out event data port Simple_Type; +end A; + +process implementation A.Impl +subcomponents + Pinger : thread P.Impl; +connections + C1 : event data port Pinger.Data_Source -> Out_Port; +end A.Impl; diff --git a/doc/source/ping/node_b_activity.c b/doc/source/ping/node_b_activity.c new file mode 100644 index 00000000..a7411954 --- /dev/null +++ b/doc/source/ping/node_b_activity.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +extern __po_hi_entity_t __po_hi_port_global_to_entity[__PO_HI_NB_PORTS]; +extern __po_hi_port_t __po_hi_port_global_to_local[__PO_HI_NB_PORTS]; +__po_hi_uint8_t __po_hi_ping_me_woffsets[__po_hi_ping_me_nb_ports]; +__po_hi_uint8_t __po_hi_ping_me_offsets[__po_hi_ping_me_nb_ports]; +__po_hi_uint8_t __po_hi_ping_me_used_size[__po_hi_ping_me_nb_ports]; +__po_hi_uint8_t __po_hi_ping_me_empties[__po_hi_ping_me_nb_ports]; +__po_hi_uint8_t __po_hi_ping_me_first[__po_hi_ping_me_nb_ports]; +__po_hi_uint8_t __po_hi_ping_me_recent[__po_hi_ping_me_nb_ports * sizeof(__po_hi_request_t)]; +__po_hi_uint8_t __po_hi_ping_me_queue[16 * sizeof(__po_hi_request_t)]; +__po_hi_uint16_t __po_hi_ping_me_total_fifo_size = 16; +__po_hi_port_t __po_hi_ping_me_history[16]; +__po_hi_uint8_t __po_hi_ping_me_n_dest[__po_hi_ping_me_nb_ports] = {0}; +__po_hi_int8_t __po_hi_ping_me_fifo_size[__po_hi_ping_me_nb_ports] = {16}; +__po_hi_uint8_t* __po_hi_ping_me_destinations[__po_hi_ping_me_nb_ports] = {NULL}; + +/*********************/ +/* ping_me_deliver */ +/*********************/ + +void ping_me_deliver + (__po_hi_request_t* request) +{ + + switch (request->port) + { + case ping_me_global_data_sink: + { + __po_hi_gqueue_store_in(node_b_ping_me_k,ping_me_local_data_sink,request); + + break; + } + default: + { + break; + } + } +} + +/* Sporadic task : Ping_Me*/ +/* Get the IN ports values*/ + +/*****************/ +/* ping_me_job */ +/*****************/ + +void* ping_me_job () +{ + __po_hi_port_t port; + __po_hi_request_t data_sink_request; + + __po_hi_gqueue_init(node_b_ping_me_k,__po_hi_ping_me_nb_ports,__po_hi_ping_me_queue,__po_hi_ping_me_fifo_size,__po_hi_ping_me_first,__po_hi_ping_me_offsets,__po_hi_ping_me_woffsets,__po_hi_ping_me_n_dest,__po_hi_ping_me_destinations,__po_hi_ping_me_used_size,__po_hi_ping_me_history,__po_hi_ping_me_recent,__po_hi_ping_me_empties,__po_hi_ping_me_total_fifo_size); + __po_hi_wait_initialization(); + while (1) + { + __po_hi_gqueue_wait_for_incoming_event(node_b_ping_me_k,&(port)); + __po_hi_compute_next_period(node_b_ping_me_k); + if (__po_hi_gqueue_get_count(node_b_ping_me_k,ping_me_local_data_sink)) + { + __po_hi_gqueue_get_value(node_b_ping_me_k,ping_me_local_data_sink,&(data_sink_request)); + __po_hi_gqueue_next_value(node_b_ping_me_k,ping_me_local_data_sink); + + } + /* Call implementation*/ + ping_spg(data_sink_request.vars.ping_me_global_data_sink.ping_me_global_data_sink); + __po_hi_wait_for_next_period(node_b_ping_me_k); + } +} + + +/**************************/ +/* __po_hi_main_deliver */ +/**************************/ + +void __po_hi_main_deliver + (__po_hi_msg_t* message) +{ + __po_hi_request_t request; + __po_hi_entity_t entity; + + __po_hi_unmarshall_request(&(request),message); + entity = __po_hi_port_global_to_entity[request.port]; + switch (entity) + { + case node_b_ping_me_k_entity: + { + ping_me_deliver(&(request)); + + break; + } + default: + { + break; + } + } +} + + diff --git a/doc/source/ping/ping.aadl b/doc/source/ping/ping.aadl new file mode 100644 index 00000000..ed70682b --- /dev/null +++ b/doc/source/ping/ping.aadl @@ -0,0 +1,16 @@ +system PING +end PING; + +system implementation PING.Impl +subcomponents + -- Nodes + Node_A : process A.Impl; + Node_B : process B.Impl {ARAO::port_number => 12002;}; + + -- Processors + -- ... +connections + -- ... +properties + -- ... +end PING.Impl; diff --git a/doc/source/ping/po_hi_common.h b/doc/source/ping/po_hi_common.h new file mode 100644 index 00000000..41d3dfa4 --- /dev/null +++ b/doc/source/ping/po_hi_common.h @@ -0,0 +1,208 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2018 ESA & ISAE. + */ + +#ifndef __PO_HI_COMMON_H__ +#define __PO_HI_COMMON_H__ + +#include +/* deployment.h sets macro on required drivers, this file is generated + by Ocarina */ + +#if (defined (RTEMS_POSIX) || defined (__PO_HI_RTEMS_CLASSIC_API)) + #if defined (__PO_HI_NEED_DRIVER_ETH_LEON) || \ + defined (__PO_HI_NEED_DRIVER_ETH_LEON_SENDER) || \ + defined (__PO_HI_NEED_DRIVER_ETH_LEON_RECEIVER) + #define RTEMS_BSP_NETWORK_DRIVER_ATTACH RTEMS_BSP_NETWORK_DRIVER_ATTACH_SMC91111 + #endif +#endif + +/******************************************************************************/ +/* Configure RTEMS/POSIX executive. */ + +#if defined(RTEMS_POSIX) + + #include + #include + +#if defined GRLEON3 && defined RTEMS412 + #include + #include + #include + #include +#endif + + #define CONFIGURE_INIT + + #include + + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + + #define CONFIGURE_MAXIMUM_TASKS 20 + #define CONFIGURE_MAXIMUM_POSIX_THREADS __PO_HI_NB_TASKS + 10 + + #define CONFIGURE_MAXIMUM_SEMAPHORES 20 // GRSPW1 IRQ layer needs one semaphore + #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20 + #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 + #define CONFIGURE_MAXIMUM_DRIVERS 32 + #define CONFIGURE_MAXIMUM_PERIODS 1 + + #define CONFIGURE_POSIX_INIT_THREAD_TABLE + + #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT + #define CONFIGURE_EXTRA_TASK_STACKS (40 * RTEMS_MINIMUM_STACK_SIZE) + #define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (40 * RTEMS_MINIMUM_STACK_SIZE) + +#if defined (AIR_HYPERVISOR) + #define CONFIGURE_MICROSECONDS_PER_TICK 5000 +#else + #define CONFIGURE_MICROSECONDS_PER_TICK RTEMS_MILLISECONDS_TO_MICROSECONDS(2) +#endif + +/*****************************************************************************/ +/* Driver Manager configuration for RTEMS 5 */ + +/* Important note: some RTEMS CONFIGURE macros above must be completed + * with specific driver configuration, otherwise some features will + * not work, e.g. CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER requires + * CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER + */ + +#if defined GRLEON3 && defined RTEMS412 + +#ifdef __PO_HI_NEED_DRIVER_ETH_LEON + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRETH /* GRETH Driver enabled*/ +#endif + +#ifdef __PO_HI_NEED_DRIVER_SPACEWIRE_RASTA + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW /* GRSPW Driver enabled*/ +#endif + +/* Configure Driver manager */ +#if defined(RTEMS_DRVMGR_STARTUP) && defined(LEON3) +/* if --drvmgr was given to RTEMS configure */ + + /* Clock driver */ + #ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER + #endif + + #ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART + #endif + + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_SPW_ROUTER /* SpaceWire Router */ + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW2 /* SpaceWire Packet driver */ + + #ifdef __PO_HI_NEED_DRIVER_GRETH + #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRETH /* GRETH Driver enabled*/ + #define CONFIGURE_DRIVER_PCI_GR_LEON4_N2X /* GR-CPCI-LEON4-N2X has two GRETH network MACs */ + #define ENABLE_NETWORK + #endif + +#endif /* defined(RTEMS_DRVMGR_STARTUP) && defined(LEON3) */ + +#endif /*GRLEON3 && RTEMS412*/ + +void *POSIX_Init (void); + +#include + +#if defined(RTEMS_DRVMGR_STARTUP) && defined(LEON3) +#include + +/* config.c is directly provided by RCC1.3 and initialized drivers per + * drvmgr convention for RASTA (LEON3), N2X and GR740 boards + */ + +#include "../src/config.c" +#endif /* defined(RTEMS_DRVMGR_STARTUP) && defined(LEON3) */ + +#endif /* RTEMS_POSIX */ + +/******************************************************************************/ +#if defined(__PO_HI_RTEMS_CLASSIC_API) + #include + #include + #define CONFIGURE_INIT + #define CONFIGURE_INIT_TASK_STACK_SIZE 2*RTEMS_MINIMUM_STACK_SIZE + #define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \ + RTEMS_NO_TIMESLICE | \ + RTEMS_NO_ASR | \ + RTEMS_INTERRUPT_LEVEL(0)) + #include + + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER +// #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER + #define CONFIGURE_MAXIMUM_DRIVERS 10 + #define CONFIGURE_MAXIMUM_TIMERS 40 + +#ifndef XM3_RTEMS_MODE + #define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024) //either RAM SIZE or Stack_extras Macro should be present Rtems4.12 +#endif + /* + #define CONFIGURE_MAXIMUM_SEMAPHORES __PO_HI_NB_TASKS + (__PO_HI_NB_PORTS + 1) * 2 + __PO_HI_NB_PROTECTED + 1 + */ + #define CONFIGURE_MAXIMUM_SEMAPHORES 20 + #define CONFIGURE_MAXIMUM_TASKS __PO_HI_NB_TASKS + 5 + #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20 + #define CONFIGURE_MAXIMUM_PERIODS __PO_HI_NB_TASKS + 5 + /* + * We put __PO_HI_NB_TASKS + 5 because we may have additional tasks + * from the driver. Originally, it was +2 for the main thread and a + * potential network thread. Since, other drivers take additional + * tasks and so, we increase it to 5. We would do a better + * integration by filtering the use of each driver. + */ + +#ifndef RTEMS411 + rtems_task Init (rtems_task_argument no_argument); +#endif + #define CONFIGURE_STACK_CHECKER_ENABLED + #define CONFIGURE_EXTRA_TASK_STACKS __PO_HI_TASKS_STACK + + #define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + #define CONFIGURE_RTEMS_INIT_TASKS_TABLE + #define CONFIGURE_MAXIMUM_BARRIERS 1 + __PO_HI_NB_PORTS + 1 + + #include +#endif /* __PO_HI_RTEMS_CLASSIC_API */ + +#if defined (X86_RTEMS) && defined (__PO_HI_USE_TRANSPORT) && __PO_HI_NB_DEVICES > 1 +#include +#include + + +/* +int rtems_bsdnet_loopattach(struct rtems_bsdnet_ifconfig*, int); + +static struct rtems_bsdnet_ifconfig loopback_config = + {"lo0", rtems_bsdnet_loopattach, NULL, "127.0.0.1", "255.0.0.0", }; +#undef RTEMS_BSP_NETWORK_DRIVER_NAME +#undef RTEMS_BSP_NETWORK_DRIVER_ATTACH +#define RTEMS_BSP_NETWORK_DRIVER_NAME "ne1" +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_ne_driver_attach + +struct rtems_bsdnet_ifconfig netdriver_config = + {RTEMS_BSP_NETWORK_DRIVER_NAME,RTEMS_BSP_NETWORK_DRIVER_ATTACH, + &loopback_config,"192.168.0.1","255.255.255.0", + (char[]){ 0x00, 0x1F, 0xC6, 0xBF, 0x74, 0x06}, + 0,0,0,0,0,9}; + +struct rtems_bsdnet_config rtems_bsdnet_config = + {&netdriver_config,NULL,0,256 * 1024,256 * 1024,}; +*/ + + +#endif /*(defined (X86_RTEMS) */ + +#endif /* __COMMON_H__ */ diff --git a/doc/source/ping/po_hi_debug.h b/doc/source/ping/po_hi_debug.h new file mode 100644 index 00000000..056ada02 --- /dev/null +++ b/doc/source/ping/po_hi_debug.h @@ -0,0 +1,59 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2016 ESA & ISAE. + */ + +#ifndef __PO_HI_DEBUG_H__ + +#include +#include + + +#define __PO_HI_DEBUG_LEVEL_INFO 12 +#define __PO_HI_DEBUG_LEVEL_DEBUG 10 +#define __PO_HI_DEBUG_LEVEL_WARNING 6 +#define __PO_HI_DEBUG_LEVEL_CRITICAL 4 +#define __PO_HI_DEBUG_LEVEL_NONE 0 + +#ifndef __PO_HI_DEBUG_LEVEL + #define __PO_HI_DEBUG_LEVEL __PO_HI_DEBUG_LEVEL_CRITICAL +#endif + + +#if __PO_HI_DEBUG_LEVEL > __PO_HI_DEBUG_LEVEL_NONE + #include +#endif + +#if __PO_HI_DEBUG_LEVEL >= __PO_HI_DEBUG_LEVEL_CRITICAL + #define __PO_HI_DEBUG_CRITICAL(s, args...) fprintf(stderr, s, ##args); fflush (stderr); +#else + #define __PO_HI_DEBUG_CRITICAL(s, args...) +#endif + +#if __PO_HI_DEBUG_LEVEL >= __PO_HI_DEBUG_LEVEL_WARNING + #define __PO_HI_DEBUG_WARNING(s, args...) fprintf(stderr, s, ##args); fflush (stderr); +#else + #define __PO_HI_DEBUG_WARNING(s, args...) +#endif + +#if __PO_HI_DEBUG_LEVEL >= __PO_HI_DEBUG_LEVEL_DEBUG + #define __PO_HI_DEBUG_DEBUG(s, args...) fprintf(stderr, s, ##args); fflush (stderr); +#else + #define __PO_HI_DEBUG_DEBUG(s, args...) +#endif + +#if __PO_HI_DEBUG_LEVEL >= __PO_HI_DEBUG_LEVEL_INFO + #define __PO_HI_DEBUG_INFO(s, args...) fprintf(stderr, s, ##args); fflush (stderr); + #define __DEBUGMSG(s, args...) fprintf(stderr, s, ##args); fflush (stderr); +#else + #define __PO_HI_DEBUG_INFO(s, args...) + #define __DEBUGMSG(s, args...) +#endif + + +#endif /* __DEBUG_H__ */ diff --git a/doc/source/ping/po_hi_giop.h b/doc/source/ping/po_hi_giop.h new file mode 100644 index 00000000..48c0b480 --- /dev/null +++ b/doc/source/ping/po_hi_giop.h @@ -0,0 +1,151 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2014 ESA & ISAE. + */ + +#ifdef __PO_HI_USE_GIOP + +#ifndef __PO_HI_GIOP_H__ +#define __PO_HI_GIOP_H__ + +#include +#include +#include +#include + +/* + * This file defines the structures and functions to support the GIOP + * protocol. The supported verrsion of GIOP is the 1.3. + * + * This implementation was made according to the CORBA 3.1, Part 2, + * chapter 9 specifications. + */ + +#define __PO_HI_GIOP_MSGTYPE_REQUEST 0 +#define __PO_HI_GIOP_MSGTYPE_REPLY 1 +#define __PO_HI_GIOP_MSGTYPE_CANCELREQUEST 2 +#define __PO_HI_GIOP_MSGTYPE_LOCATEREQUEST 3 +#define __PO_HI_GIOP_MSGTYPE_LOCATEREPLY 4 +#define __PO_HI_GIOP_MSGTYPE_CLOSECONNECTION 5 +#define __PO_HI_GIOP_MSGTYPE_MESSAGEERROR 6 +#define __PO_HI_GIOP_MSGTYPE_FRAGMENT 7 + +#define __PO_HI_GIOP_VERSION_MAJOR 1 +#define __PO_HI_GIOP_VERSION_MINOR 3 + +#define __PO_HI_GIOP_MAGIC "GIOP" + +#define __PO_HI_GIOP_OPERATION_MAX_SIZE 100 + +#define __PO_HI_GIOP_MAGIC_SIZE 4 + +#define __PO_HI_GIOP_DISPOSITION_KEY 0 +#define __PO_HI_GIOP_DISPOSITION_PROFILE 1 +#define __PO_HI_GIOP_DISPOSITION_REFERENCE 2 + +#define __PO_HI_GIOP_HAS_MORE_MESSAGES 300 + +typedef struct +{ + char magic[4]; + struct { + __po_hi_uint8_t major; /* __PO_HI_GIOP_VERSION_MAJOR */ + __po_hi_uint8_t minor; /* __PO_HI_GIOP_VERSION_MINOR */ + } version; + __po_hi_uint8_t flags; + __po_hi_uint8_t message_type; + __po_hi_uint32_t message_size; +}__po_hi_giop_msg_hdr_t; + +/* The __po_hi_giop_msg_hdr_t gives a structure to fill a message header */ +/* for the GIOP protocol. The flags (8 bits) are organized like this : */ +/* 0 0 0 0 0 0 0 0 */ +/* | |----- byte order : 1 for little-endian */ +/* | 0 for big-endian */ +/* The message_type should be a value of __PO_HI_GIOP_MSGTYPE* */ + +typedef struct +{ + __po_hi_uint16_t disposition; + union + { + struct + { + __po_hi_uint32_t object_size; + __po_hi_uint32_t object_addr; + }key; + + struct + { + __po_hi_uint32_t profile_id; + __po_hi_uint32_t profile_length; + __po_hi_uint32_t profile_data; + }profile; + + struct + { + __po_hi_uint32_t profile_index; + __po_hi_uint32_t full_ior; + }reference; + } values; +}__po_hi_giop_request_target_t; +/* + * Note: for now, we only support object target. The object-id will + * always be set to 0. + */ + +typedef struct +{ + __po_hi_uint32_t request_id; + __po_hi_uint8_t response_flags; + __po_hi_uint8_t reserved[3]; + __po_hi_giop_request_target_t target; + __po_hi_uint32_t operation_length; + char operation[__PO_HI_GIOP_OPERATION_MAX_SIZE]; + __po_hi_uint32_t nb_scontext; +}__po_hi_giop_request_hdr_t; +/* + * The operation is set the a maximum length of 100 + */ + +void __po_hi_giop_msg_hdr_init (__po_hi_giop_msg_hdr_t* msg_hdr); +/* + * Initialize the message header, set the magic number, the version + * and all other needed variables + */ + +void __po_hi_giop_msg_hdr_set_message_type (__po_hi_giop_msg_hdr_t* msg_hdr, + __po_hi_uint8_t msg_type); +/* + * Set the message type in the header. We only support request, so the + * type should be always __PO_HI_GIOP_MSG_REQUEST + */ + +void __po_hi_giop_msg_hdr_set_message_size (__po_hi_giop_msg_hdr_t* msg_hdr, + __po_hi_uint32_t msg_size); + +void __po_hi_giop_request_hdr_init (__po_hi_giop_request_hdr_t* request_hdr); + +void __po_hi_giop_request_hdr_set_operation (__po_hi_giop_request_hdr_t* request_hdr, + const char* request_name); + +int __po_hi_giop_send (__po_hi_entity_t from, + __po_hi_entity_t to, + __po_hi_msg_t* msg); + +int __po_hi_giop_decode_msg (__po_hi_msg_t* network_flow, + __po_hi_msg_t* output_msg, + __po_hi_uint32_t* has_more); + +#ifdef __PO_HI_DEBUG +void __po_hi_giop_print_msg( __po_hi_msg_t* msg); +#endif + +#endif /* __PO_HI_GIOP_H__ */ + +#endif /* __PO_HI_USE_GIOP */ diff --git a/doc/source/ping/po_hi_gqueue.h b/doc/source/ping/po_hi_gqueue.h new file mode 100644 index 00000000..96078e62 --- /dev/null +++ b/doc/source/ping/po_hi_gqueue.h @@ -0,0 +1,231 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2017 ESA & ISAE. + */ + +#ifndef __PO_HI_GQUEUE_H__ +#define __PO_HI_GQUEUE_H__ + +#define __PO_HI_GQUEUE_FULL 10 + +#define __PO_HI_GQUEUE_FIFO_INDATA -1 +#define __PO_HI_GQUEUE_FIFO_OUT -2 + +#define __PO_HI_GQUEUE_INVALID_PORT invalid_port_t +#define __PO_HI_GQUEUE_INVALID_LOCAL_PORT invalid_local_port_t + +#include +#include +#include + +/** + * \brief Initialize a global queue. + * + * In a distributed system, each task has + * its own global queue. This function is invoked by each thead to + * create its global queue, according to its information (number of + * ports, destination of each port ...). + + * \param id id of the task associated to this queue. + * \param nb_ports number of ports for task 'id'. + * \param queue XXX. + * \param sizes size of the FIFO for each port, or __PO_HI_GQUEUE_FIFO_OUT if this is an out port. + * \param first XXX. + * \param offsets offset position for each queue in the global queue. + * \param woffsets + * \param n_dest number of destinations for each port. + * \param destinations destination for each port. + * \param used_size XXX. + * \param history XXX. + * \param recent XXX. + * \param empties XXX. + * \param total_fifo_sizes XXX. + */ +void __po_hi_gqueue_init (__po_hi_task_id id, + __po_hi_port_id_t nb_ports, + __po_hi_request_t queue[], + __po_hi_port_id_t sizes[], + __po_hi_port_id_t first[], + __po_hi_port_id_t offsets[], + __po_hi_port_id_t woffsets[], + __po_hi_port_id_t n_dest[], + __po_hi_port_t* destinations[], + __po_hi_port_id_t used_size[], + __po_hi_local_port_t history[], + __po_hi_request_t recent[], + __po_hi_port_id_t empties[], + __po_hi_uint32_t total_fifo_size); + + + +/** + * \brief Store a value for an OUT port. + * + * \param id task-id which owns the global queue. + * \param port port that store the value (local). + * \param request pointer towards the request to store in the queue. + */ +void __po_hi_gqueue_store_out (__po_hi_task_id id, + __po_hi_local_port_t port, + __po_hi_request_t* request); + + + +/* + * \brief Send a value for an out port. + * + * \param id task-id which has the global queue. + * \param port number of the port that will send the data. + * \param request pointer towards the request to store in the queue. + */ +/* +int __po_hi_gqueue_send_output (__po_hi_task_id id, + __po_hi_port_t port); +*/ + + +/** + * \brief Get the value on the specified port. + * + * If the port is an output, this function will return nothing, + * but will not produce an error. + * + * If the port is an *IN* event port, this function will return + * the last value received in the request parameter, or block until an event arrives. + * + * \param id task-id which owns the global queue. + * \param port number of port that received the data. + * \param request pointer to store the received data. + * \return 0 if there is no error in the assert. + */ +int __po_hi_gqueue_get_value(__po_hi_task_id id, + __po_hi_local_port_t port, + __po_hi_request_t* request); + +/** + * \brief Dequeue the value on a port. + * + * This function should not be called several times, until + * you know what you do. + * + * \param id task-id in the local process. + * \param port port number. + * \return __PO_HI_SUCCESS if there is no error in the assert. + */ +int __po_hi_gqueue_next_value(__po_hi_task_id id, + __po_hi_local_port_t port); + +/** + * \brief Return the number of events that are pending of a port. + * + * \param id task-identifier in the local process. + * \param port port identifier (or port number) for the thread. + * \return the number of events that are pending of a port. + */ +int __po_hi_gqueue_get_count(__po_hi_task_id id, + __po_hi_local_port_t port); + +/** + * \brief Wait until an event is received on any port for a given thread. + * + * When the function returns, the port argument will contrain the port-id that received the event. + * + * \param id thread identifier in the local process. + * \param port pointer to a port value. + */ +void __po_hi_gqueue_wait_for_incoming_event(__po_hi_task_id id, + __po_hi_local_port_t* port); + +/** + * \brief Store a value in a IN port. + * + * The request argument contrains the request that will be stored in the queue. + * + * \param id task identifier in the local process. + * \param port port identifier for the local thread. + * \param request pointer towards what will be stored in the queue. + * \return the number of events that are pending of a port. + */ +__po_hi_port_id_t __po_hi_gqueue_store_in (__po_hi_task_id id, + __po_hi_local_port_t port, + __po_hi_request_t* request); + +/** + * \brief Access the most recent value queued. + * + * The program fetches the most recent value on this port in the __po_hi_gqueue_get_most_recent_value array. + * It gives the result in the form of a request. + * WARNING the function doesn't take into account whether the port is an output or input, if the port is empty or not. + * For this details, see the function get_value. + * + * \param task_id task identifier in the local process. + * \param local_port port identifier for the local thread. + * \return the request. + */ +__po_hi_request_t* __po_hi_gqueue_get_most_recent_value + (const __po_hi_task_id task_id, + const __po_hi_local_port_t local_port); + +/** + * \brief Access the destination port thanks to the destination number. + * + * The program fetches the destination port. + * \param task_id task identifier in the local process. + * \param local_port port identifier for the local thread. + * \param destination_number the number of the destination (__po_hi_gqueue_get_destinations_number function). + * \return the port. + */ +__po_hi_port_t __po_hi_gqueue_get_destination (const __po_hi_task_id task_id, + const __po_hi_local_port_t local_port, + const uint8_t destination_number); + +/** + * \brief Access the destination number (for a specified port). + * + * The program fetches the destination number in the __po_hi_gqueues_n_destinations array. + * It gives the destination number in the form of a __po_hi_port_id_t. + * It can be used then to get the destination port with the get_destination function. + * + * \param task_id task identifier in the local process. + * \param local_port port identifier for the local thread. + * \return the number. + */ +__po_hi_port_id_t __po_hi_gqueue_get_destinations_number (const __po_hi_task_id task_id, + const __po_hi_local_port_t local_port); + + +/** + * \brief Access the size of a port. + * + * \param id task identifier in the local process. + * \param port port identifier for the local thread. + * \return size of port. + */ +__po_hi_port_id_t __po_hi_gqueue_get_port_size(const __po_hi_task_id id, + const __po_hi_local_port_t port); + +/** + * \brief Access the used size of a port. + * + * \param id task identifier in the local process. + * \param port port identifier for the local thread. + * \return size of port. + */ +__po_hi_port_id_t __po_hi_gqueue_used_size( __po_hi_task_id id, __po_hi_local_port_t port); + +/** + * \brief Check whether the queue belonging to the id task is empty. + * + * The program checks the array __po_hi_gqueues_queue_is_empty. + * \param id task identifier in the local process. + * \return the value in the array. + * \return 0 and 1 if the queue is not empty because of array construction. + */ +__po_hi_port_id_t po_hi_gqueues_queue_is_empty(__po_hi_task_id id); + +#endif /* __PO_HI_GQUEUE_H__ */ diff --git a/doc/source/ping/po_hi_main.h b/doc/source/ping/po_hi_main.h new file mode 100644 index 00000000..92767e7b --- /dev/null +++ b/doc/source/ping/po_hi_main.h @@ -0,0 +1,52 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2014 ESA & ISAE. + */ + +#ifndef __PO_HI_MAIN__ +#define __PO_HI_MAIN__ + +int __po_hi_initialize (void); +/* + * Invoke all functions to initialize tasks + * and network. Return __PO_HI_SUCCESS if there + * is no error. Else, it can return the value + * __PO_HI_ERROR_PTHREAD_BARRIER. + */ + +void __po_hi_initialize_add_task (void); +/* + * Declare that another task has to be initialized + */ + +int __po_hi_wait_initialization (void); +/* + * Invoked by each node to wait initialization + * of other node. It is used by synchronize all + * processes. + * Return __PO_HI_SUCCESS value is there is no + * error. Return __PO_HI_ERROR_PTHREAD_BARRIER + * if there is an error. + */ + +#ifdef __PO_HI_USE_GPROF +void __po_hi_wait_end_of_instrumentation (void); +/* + * Wait a certain amount of time to finish the + * execution of the system. + */ +#endif + +int __po_hi_initialize_early (void); +/* + * __po_hi_initialize_earlier() is used to perform + * some early initialization, before device + * init functions are invoked. + */ + +#endif /* __PO_HI_MAIN__ */ diff --git a/doc/source/ping/po_hi_marshallers.h b/doc/source/ping/po_hi_marshallers.h new file mode 100644 index 00000000..f0e3a60b --- /dev/null +++ b/doc/source/ping/po_hi_marshallers.h @@ -0,0 +1,82 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2014 ESA & ISAE. + */ + +#ifndef __PO_HI_MARSHALLERS_H_ +#define __PO_HI_MARSHALLERS_H_ + +#include +#include +#include + +/* + * Basic marshallers functions. These functions are then + * reused in the generated code to marshall application data. + */ + +void __po_hi_marshall_port (__po_hi_port_t value, __po_hi_msg_t* msg); +void __po_hi_unmarshall_port (__po_hi_port_t* value, __po_hi_msg_t* msg); + +void __po_hi_marshall_array (void* value, __po_hi_msg_t* msg,__po_hi_uint32_t size, __po_hi_uint32_t* offset); +void __po_hi_unmarshall_array (void* value, __po_hi_msg_t* msg,__po_hi_uint32_t size, __po_hi_uint32_t* offset); + +void __po_hi_marshall_bool (__po_hi_bool_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_bool (__po_hi_bool_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_char (char value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_char (char* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_int (int value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_int (int* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_float (float value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_float (float* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_float32 (__po_hi_float32_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_float32 (__po_hi_float32_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_float64 (__po_hi_float64_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_float64 (__po_hi_float64_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_int8 (__po_hi_int8_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_int8 (__po_hi_int8_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_int16 (__po_hi_int16_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_int16 (__po_hi_int16_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_int32 (__po_hi_int32_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_int32 (__po_hi_int32_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +#ifndef COMPCERT +void __po_hi_marshall_int64 (__po_hi_int64_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_int64 (__po_hi_int64_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +#endif + +void __po_hi_marshall_uint8 (__po_hi_uint8_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_uint8 (__po_hi_uint8_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_uint16 (__po_hi_uint16_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_uint16 (__po_hi_uint16_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +void __po_hi_marshall_uint32 (__po_hi_uint32_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_uint32 (__po_hi_uint32_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); + +#ifndef COMPCERT +void __po_hi_marshall_uint64 (__po_hi_uint64_t value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +void __po_hi_unmarshall_uint64 (__po_hi_uint64_t* value, __po_hi_msg_t* msg,__po_hi_uint32_t* offset); +#endif + +#ifdef PO_HI_USE_ASN1 +#include +#define __PO_HI_ASN1_PKT_SIZE Pkt_REQUIRED_BYTES_FOR_ENCODING +#define __po_hi_asn1_buffer_t __po_hi_byte_t* +#define __po_hi_asn1_pkt_t Pkt +#endif + +#endif /* __PO_HI_MARSHALLERS_H_ */ diff --git a/doc/source/ping/po_hi_messages.c b/doc/source/ping/po_hi_messages.c new file mode 100644 index 00000000..f29083bb --- /dev/null +++ b/doc/source/ping/po_hi_messages.c @@ -0,0 +1,184 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2017 ESA & ISAE. + */ + +#include +#include +#include + +/* Headers from PolyORB-HI-C */ + +#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (RTEMS_POSIX) || defined (__PO_HI_RTEMS_CLASSIC_API) || defined (FREERTOS) +#else +#include +#endif +#include + +/* Headers from the executive */ + +#ifdef __PO_HI_DEBUG +#include +#endif + + +void __po_hi_msg_reallocate (__po_hi_msg_t* message) +{ + message->length = 0; + message->flags = 0; + memset (message->content, 0, __PO_HI_MESSAGES_MAX_SIZE); +} + +void __po_hi_msg_write (__po_hi_msg_t* msg, + void* data, + __po_hi_uint32_t len) +{ + memcpy (msg->content, data, len); + msg->length = len; +} +int __po_hi_msg_length (__po_hi_msg_t* msg) +{ + return (msg->length); +} + + +void __po_hi_msg_copy (__po_hi_msg_t* dest, + __po_hi_msg_t* src) +{ + memcpy (dest->content, + src->content, + __PO_HI_MESSAGES_MAX_SIZE); + dest->length = src->length; +} + +void __po_hi_msg_append_data (__po_hi_msg_t* msg, void* data, __po_hi_uint32_t length) +{ + memcpy (msg->content + msg->length, data, length); + msg->length = msg->length + length; +} + +void __po_hi_msg_append_msg (__po_hi_msg_t* dest, __po_hi_msg_t* source) +{ + memcpy (&(dest->content[dest->length]), source->content, source->length); + dest->length = dest->length + source->length; +} + +void __po_hi_msg_get_data (void* dest, __po_hi_msg_t* source, __po_hi_uint32_t index, __po_hi_uint32_t size) +{ + memcpy (dest, &(source->content[index]), size); +} + +void __po_hi_msg_move (__po_hi_msg_t* msg, __po_hi_uint32_t length) +{ + __po_hi_uint32_t tmp; + for (tmp=length; tmp < msg->length ; tmp++) + { + msg->content[tmp-length] = msg->content[tmp]; + } + msg->length = msg->length - length; +} + +int __po_hi_msg_should_swap (__po_hi_msg_t* msg) +{ +#ifdef WORDS_BIGENDIAN + if (msg->flags == __PO_HI_MESSAGES_CONTENT_LITTLEENDIAN) + { + return 1; + } +#else + if (msg->flags == __PO_HI_MESSAGES_CONTENT_BIGENDIAN) + { + return 1; + } +#endif + return 0; +} + +void __po_hi_msg_swap_value (void* from, void* dest, __po_hi_uint32_t size) +{ + __po_hi_uint32_t tmp; + __po_hi_uint8_t* udest; + __po_hi_uint8_t* ufrom; + + ufrom = (__po_hi_uint8_t*)from; + udest = (__po_hi_uint8_t*)dest; + + for (tmp=0 ; tmp < size ; tmp++) + { + udest[tmp] = ufrom[size-tmp - 1]; + } +} + +#ifdef __PO_HI_DEBUG +void __po_hi_messages_debug (__po_hi_msg_t* msg) +{ + uint32_t length; + char Hexa [50]; + char ASCII [17]; + int Index_Hexa = 0; + int Index_ASCII = 0; + int i; + + for (i = 0 ; i < 50 ; i++) + Hexa[i] = ' '; + + for (i = 0 ; i < 17 ; i++) + ASCII[i] = ' '; + + printf ("Length: %u\n", (unsigned int) msg->length); + + for (length = 0 ; length < msg->length ; length++) + { + Hexa [Index_Hexa] = ' '; + + if ((msg->content[length]/16) > 9) + Hexa [Index_Hexa + 1] = 'A' -10 + (msg->content[length] / 16); + else + Hexa [Index_Hexa + 1] = '0' + (msg->content[length] / 16); + + if ((msg->content[length] % 16) > 9) + Hexa [Index_Hexa + 2] = 'A' - 10 + (msg->content[length] % 16); + else + Hexa [Index_Hexa + 2] = '0' + (msg->content[length] % 16); + + Index_Hexa += 3; + + if ((msg->content[length] < 32) || (msg->content[length] > 127)) + ASCII [Index_ASCII] = '.'; + else + ASCII [Index_ASCII] = msg->content[length]; + + Index_ASCII++; + + if (Index_Hexa >= 45) + { + Hexa[Index_Hexa] = '\0'; + ASCII[Index_ASCII] = '\0'; + printf ("%s || %s\n", Hexa, ASCII); + Index_Hexa = 0; + Index_ASCII = 0; + for (i = 0 ; i < 50 ; i++) + Hexa[i] = ' '; + + for (i = 0 ; i < 17 ; i++) + ASCII[i] = ' '; + } + } + if (Index_Hexa > 0) + { + for (i = Index_Hexa ; i<44 ; i++) + Hexa[i] = ' '; + Index_Hexa = 45; + + Hexa[Index_Hexa] = '\0'; + ASCII[Index_ASCII] = '\0'; + printf ("%s || %s\n", Hexa, ASCII); + } + +} +#endif diff --git a/doc/source/ping/po_hi_messages.h b/doc/source/ping/po_hi_messages.h new file mode 100644 index 00000000..967ccb2f --- /dev/null +++ b/doc/source/ping/po_hi_messages.h @@ -0,0 +1,113 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2017 ESA & ISAE. + */ + +#ifndef __PO_HI_MESSAGES_H_ +#define __PO_HI_MESSAGES_H_ + +#include +#include + +#include +/* This file may not be generated. However, using messages implies + using request. */ + +#ifdef __PO_HI_USE_GIOP +#define __PO_HI_MESSAGES_MAX_SIZE (int) sizeof(__po_hi_request_t) + 200 +#else +#define __PO_HI_MESSAGES_MAX_SIZE (int) sizeof(__po_hi_request_t) + 4 +/* XXX Why + 4 ? to be investigated */ +#endif + +#define __PO_HI_MESSAGES_CONTENT_BIGENDIAN 1 +#define __PO_HI_MESSAGES_CONTENT_LITTLEENDIAN 2 + +typedef struct +{ + __po_hi_uint8_t content[__PO_HI_MESSAGES_MAX_SIZE]; /* Content of the message */ + __po_hi_uint32_t length; + __po_hi_uint8_t flags; +} __po_hi_msg_t; + + +void __po_hi_msg_reallocate (__po_hi_msg_t* message); +/* + * Reset the message given in parameter + */ + +void __po_hi_msg_write (__po_hi_msg_t* msg, + void* data, + __po_hi_uint32_t len); +/* + * Write the data at the beginning of the specified message. Length + * of the data are specified by the parameter len + */ + + +int __po_hi_msg_length (__po_hi_msg_t* msg); +/* + * Return the length is the message + */ + +void __po_hi_msg_copy (__po_hi_msg_t* dest, + __po_hi_msg_t* src); +/* + * Copy a message. The first argument is the message destination + * whereas the second argument is the message source + */ + +void __po_hi_msg_append_data (__po_hi_msg_t* msg, void* data, __po_hi_uint32_t length); +/* + * Append data to a message. The first argument is the message which + * will contain all the data. The second argument is a pointer to the + * data and the third argument (length) is the size of the data in + * byte. + */ + +void __po_hi_msg_append_msg (__po_hi_msg_t* dest, __po_hi_msg_t* source); +/* + * Append a message to another message. The first argument is the + * message in which we will append the data. The second argument is + * the source of the data. + */ + +void __po_hi_msg_get_data (void* dest, __po_hi_msg_t* source, + __po_hi_uint32_t index, + __po_hi_uint32_t size); +/* + * Get data from a message at index 'index', and copy it to the dest + * argument It will copy size bytes from the messages. + */ + +void __po_hi_msg_move (__po_hi_msg_t* msg, __po_hi_uint32_t length); +/* + * Move a part of the message to the beginning. This function will put + * the part (starting from the length argument) to the beginning of + * the message. + */ + +int __po_hi_msg_should_swap (__po_hi_msg_t* msg); +/* + * The __po_hi_msg_should_swap return 1 if the endianness of the + * current processor differs with the endianness of the message. Else, + * it returns 0. + */ + +void __po_hi_msg_swap_value (void* from, void* dest, __po_hi_uint32_t size); +/* + * The function __po_hi_msg_swap_value swap the bytes of the from + * value and put it to the dest argument. The size of the value is + * designed by the third argument. + */ + +#ifdef __PO_HI_DEBUG +void __po_hi_messages_debug (__po_hi_msg_t* msg); +#endif + +#endif /* __PO_HI_MESSAGES_H_ */ diff --git a/doc/source/ping/po_hi_protected.h b/doc/source/ping/po_hi_protected.h new file mode 100644 index 00000000..0efdb299 --- /dev/null +++ b/doc/source/ping/po_hi_protected.h @@ -0,0 +1,161 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2018 ESA & ISAE. + */ + +#ifndef __PO_HI_PROTECTED_H__ +#define __PO_HI_PROTECTED_H__ + + +#include +#include + +#define __PO_HI_PROTECTED_TYPE_REGULAR 0 +#define __PO_HI_PROTECTED_TYPE_PIP 1 +#define __PO_HI_PROTECTED_TYPE_PCP 2 + +#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX) + #include + #include + #include + #include +#endif + +#if defined (__PO_HI_RTEMS_CLASSIC_API) + #include +#endif + +#if defined (XENO_NATIVE) + #include +#endif + +#ifdef _WIN32 +#include +#endif + +typedef enum +{ + __PO_HI_PROTECTED_REGULAR = 1, + __PO_HI_MUTEX_REGULAR = 1, + __PO_HI_PROTECTED_PIP = 2, + __PO_HI_MUTEX_PIP = 2, + __PO_HI_PROTECTED_PCP = 3, + __PO_HI_MUTEX_PCP = 3, + __PO_HI_PROTECTED_IPCP = 4, + __PO_HI_MUTEX_IPCP = 4, + __PO_HI_PROTECTED_INVALID = 1 +}__po_hi_protected_protocol_t; + +typedef __po_hi_protected_protocol_t __po_hi_mutex_protocol_t; + +typedef struct +{ + __po_hi_mutex_protocol_t protocol; + int priority; +#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX) + pthread_mutex_t posix_mutex; + pthread_mutexattr_t posix_mutexattr; +#endif +#if defined (__PO_HI_RTEMS_CLASSIC_API) + rtems_id rtems_mutex; +#endif +#if defined (XENO_NATIVE) + RT_MUTEX xeno_mutex; +#endif +#if defined (_WIN32) + HANDLE win32_mutex; +#endif +}__po_hi_mutex_t; + +typedef uint8_t __po_hi_protected_t; + +/* + * \fn __po_hi_protected_lock + * + * \brief Lock the variable which has he id given by the argument. + * + * Return __PO_HI_SUCCESS if it is successfull. If there is an error, + * it can return __PO_HI_ERROR_PTHREAD_MUTEX value + */ +int __po_hi_protected_lock (__po_hi_protected_t protected_id); + +/** + * \fn __po_hi_protected_lock + * + * Unlock the variable which has he id given + * by the argument. + * Return __PO_HI_SUCCESS if it is successfull. + * If there is an error, it can return + * __PO_HI_ERROR_PTHREAD_MUTEX value + */ +int __po_hi_protected_unlock (__po_hi_protected_t protected_id); + +/** + * \fn __po_hi_protected_init + * + * \brief Initialize all variables to handle protected objects in PolyORB-HI-C + */ +int __po_hi_protected_init (void); + + +/** + * \fn __po_hi_mutex_init + * + * \brief Initialize a mutex no matter the underlying executive + * + * This function allocate all the resources to the mutex so that it can be + * used with __po_hi_mutex_lock() and __po_hi_mutex_unlock(). The second + * parameter is the locking protocol of the mutex that is mapped on the + * appropriate underlyign OS directives if supported. The third argument + * is the priority ceiling used, only relevant if the protocol + * needs such an option. Otherwise, any value can be used. + * + * Upon success, the function returns __PO_HI_SUCCESS. + * It returns the following potential values: + * - __PO_HI_SUCCESS: successful operation + * - __PO_HI_TOOMANY: too many resources allocated at this time + * - __PO_HI_INVALID: supplied argument value (memory error) + */ +int __po_hi_mutex_init (__po_hi_mutex_t* mutex, const __po_hi_mutex_protocol_t protocol, const int priority); + +/** + * \fn __po_hi_mutex_lock + * + * \brief Lock a mutex no matter the underlying executive + * + * This function locks the mutex so that it ensures that only one task + * acquired it. Note that if the mutex was previously acquired, the caller + * will be blocked until the mutex is released. + * + * Upon success, the function returns __PO_HI_SUCCESS. + * It returns the following potential values: + * - __PO_HI_SUCCESS: successful operation + * - __PO_HI_INVALID: supplied argument value (memory error) + * - __PO_HI_NOTINITALIZED: supplied resources was not initialized + */ +int __po_hi_mutex_lock (__po_hi_mutex_t* mutex); + +/** + * \fn __po_hi_mutex_unlock + * + * \brief Unlock a mutex no matter the underlying executive + * + * This function unlocks the mutex so that other tasks can acquire it + * again. + * + * Upon success, the function returns __PO_HI_SUCCESS. + * It returns the following potential values: + * - __PO_HI_SUCCESS: successful operation + * - __PO_HI_INVALID: supplied argument value (memory error) + * - __PO_HI_NOTINITALIZED: supplied resources was not initialized + */ + +int __po_hi_mutex_unlock (__po_hi_mutex_t* mutex); + + +#endif /* __PO_HI_PROTECTED_H__ */ diff --git a/doc/source/ping/po_hi_returns.h b/doc/source/ping/po_hi_returns.h new file mode 100644 index 00000000..fa958c25 --- /dev/null +++ b/doc/source/ping/po_hi_returns.h @@ -0,0 +1,64 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2018 ESA & ISAE. + */ + +#ifndef __PO_HI_RETURNS_H__ +#define __PO_HI_RETURNS_H__ + +/* Success return code */ +#define __PO_HI_SUCCESS 1 +#define __PO_HI_UNAVAILABLE 2 +#define __PO_HI_INVALID 5 +#define __PO_HI_TOOMANY 6 + +#define __PO_HI_NOTIMPLEMENTED 8 + +#define __PO_HI_NOTINITIALIZED 9 + +/* Errors from the API */ +#define __PO_HI_ERROR_CREATE_TASK -10 +#define __PO_HI_ERROR_TASK_PERIOD -11 +#define __PO_HI_ERROR_CLOCK -15 +#define __PO_HI_ERROR_QUEUE_FULL -20 + +#define __PO_HI_ERROR_UNKNOWN -30 + +/* Errors related to the pthread library */ +#define __PO_HI_ERROR_PTHREAD_COND -50 +#define __PO_HI_ERROR_PTHREAD_MUTEX -51 +#define __PO_HI_ERROR_PTHREAD_CREATE -52 +#define __PO_HI_ERROR_PTHREAD_ATTR -53 +#define __PO_HI_ERROR_PTHREAD_SCHED -54 +#define __PO_HI_ERROR_TRANSPORT_SEND -55 +#define __PO_HI_ERROR_PTHREAD_BARRIER -56 + +/* Errors related to the protected and semaphore API */ +#define __PO_HI_ERROR_PROTECTED_LOCK -60 +#define __PO_HI_ERROR_PROTECTED_UNLOCK -61 +#define __PO_HI_ERROR_PROTECTED_CREATE -62 + +#define __PO_HI_ERROR_MUTEX_LOCK -60 +#define __PO_HI_ERROR_MUTEX_UNLOCK -61 +#define __PO_HI_ERROR_MUTEX_CREATE -62 + +#define __PO_HI_ERROR_SEM_WAIT -60 +#define __PO_HI_ERROR_SEM_RELEASE -61 +#define __PO_HI_ERROR_SEM_CREATE -62 + +/* GIOP error code */ +#define __PO_HI_GIOP_INVALID_SIZE -100 +#define __PO_HI_GIOP_INVALID_VERSION -120 +#define __PO_HI_GIOP_INVALID_REQUEST_TYPE -150 +#define __PO_HI_GIOP_INVALID_OPERATION -180 +#define __PO_HI_GIOP_UNSUPPORTED -200 + +#define __PO_HI_ERROR_EXISTS -80 +#define __PO_HI_ERROR_NOEXISTS -81 + +#endif /* __RETURNS_H__ */ diff --git a/doc/source/ping/po_hi_task.h b/doc/source/ping/po_hi_task.h new file mode 100644 index 00000000..645ee6d2 --- /dev/null +++ b/doc/source/ping/po_hi_task.h @@ -0,0 +1,231 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2010-2017 ESA & ISAE. + */ + +#ifndef __PO_HI_TASK_H__ +#define __PO_HI_TASK_H__ + +/* + * Define some values that are dependant of the + * underlying executive. + */ +#if defined (POSIX) || defined (XENO_POSIX) || defined (SIMULATOR) + #include + #include +#if defined (DLL) + #define __PO_HI_MAIN_NAME aadl_start +#else + #define __PO_HI_MAIN_NAME main +#endif + #define __PO_HI_MAIN_TYPE int + #define __PO_HI_MAIN_ARGS int argc , char *argv[] , char **arge + #define __PO_HI_MAIN_RETURN EXIT_SUCCESS + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) + +#elif defined(_WIN32) + #include + #include + #include + #include + #define __PO_HI_MAIN_NAME _tmain + #define __PO_HI_MAIN_TYPE int + #define __PO_HI_MAIN_ARGS + #define __PO_HI_MAIN_RETURN EXIT_SUCCESS + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) + +#elif defined (XENO_NATIVE) + #include + #include + #define __PO_HI_MAIN_NAME main + #define __PO_HI_MAIN_TYPE int + #define __PO_HI_MAIN_ARGS int argc , char *argv[] , char **arge + #define __PO_HI_MAIN_RETURN 0 + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) + +#elif defined(__PO_HI_RTEMS_CLASSIC_API) + #define __PO_HI_MAIN_NAME Init + #define __PO_HI_MAIN_TYPE rtems_task + #define __PO_HI_MAIN_ARGS rtems_task_argument argument + #define __PO_HI_MAIN_RETURN 0 + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) + +#elif defined(RTEMS_POSIX) + #define __PO_HI_MAIN_NAME POSIX_Init + #define __PO_HI_MAIN_TYPE int + #define __PO_HI_MAIN_ARGS + #define __PO_HI_MAIN_RETURN 0 + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) + +#elif defined (FREERTOS) + #define __PO_HI_MAIN_NAME main + #define __PO_HI_MAIN_TYPE int + #define __PO_HI_MAIN_ARGS int argc , char *argv[] , char **arge + #define __PO_HI_MAIN_RETURN 0 + #define __ERRORMSG(s, args...) fprintf(stderr, s, ##args) +#endif + +#if defined(POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX) + #include + #include + #include + #include + #define __PO_HI_MAX_PRIORITY sched_get_priority_max(SCHED_FIFO) + #define __PO_HI_MIN_PRIORITY sched_get_priority_min(SCHED_FIFO) + #define __PO_HI_DEFAULT_PRIORITY ((sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO))/2) + +#elif defined (SIMULATOR) + #include + #define __PO_HI_MAX_PRIORITY 255 + #define __PO_HI_MIN_PRIORITY 1 + #define __PO_HI_DEFAULT_PRIORITY 128 + +#elif defined(_WIN32) + #include + #include + #define __PO_HI_DEFAULT_PRIORITY 0 + #define __PO_HI_MAX_PRIORITY 2 + #define __PO_HI_MIN_PRIORITY 0 + +#elif defined(__PO_HI_RTEMS_CLASSIC_API) + #include + #include + #include + #define __PO_HI_DEFAULT_PRIORITY RTEMS_NO_PRIORITY + #define __PO_HI_MAX_PRIORITY RTEMS_NO_PRIORITY + #define __PO_HI_MIN_PRIORITY RTEMS_NO_PRIORITY +#elif defined(XENO_NATIVE) + #include + #include + #define __PO_HI_DEFAULT_PRIORITY 50 + #define __PO_HI_MAX_PRIORITY 99 + #define __PO_HI_MIN_PRIORITY 0 +#elif defined(FREERTOS) + #include + #define __PO_HI_DEFAULT_PRIORITY 50 + #define __PO_HI_MAX_PRIORITY 99 + #define __PO_HI_MIN_PRIORITY 0 +#endif + +#include + +#include +#include + +typedef __po_hi_uint16_t __po_hi_priority_t; +typedef size_t __po_hi_stack_t; + +/* + * Initialize tasking entities + * Returns SUCCESS if there is no error. + */ +int __po_hi_initialize_tasking(void); + +/* + * Get the id of a task + */ +__po_hi_task_id __po_hi_get_task_id (void); + +/* + * Create a periodic task. + * + * The task created have the identifier given by the first + * parameter. It is created according to the period created + * with __po_hi_* functions (like __po_hi_milliseconds()) + * and priority parameters (use the OS priority). The task execute + * periodically start_routine. + * + * This function returns SUCCESS if there is no error. Else, + * it returns the negative value ERROR_CREATE_TASK. + */ +int __po_hi_create_periodic_task (const __po_hi_task_id id, + const __po_hi_time_t* period, + const __po_hi_priority_t priority, + const __po_hi_stack_t stack_size, + const __po_hi_int8_t core_id, + void* (*start_routine)(void)); + +/* + * Create a sporadic task. + * + * The identifier of the task is the first parameter. The period and + * the priority of the task are stored in the second and third + * parameter. The code executed by the task is stored in the + * start_routine pointer. + * + * Returns SUCCESS value if there is no error. Else, returns the negative + * value ERROR_CREATE_TASK + */ +int __po_hi_create_sporadic_task (const __po_hi_task_id id, + const __po_hi_time_t* period, + const __po_hi_priority_t priority, + const __po_hi_stack_t stack_size, + const __po_hi_int8_t core_id, + void* (*start_routine)(void)); + +/* + * Create a generic task + * + * The identifier of the task is the first parameter. The period and + * the priority of the task are stored in the second and third + * parameter. The code executed by the task is stored in the + * start_routine pointer. + * + * Returns SUCCESS value if there is no error. Else, returns the negative + * value ERROR_CREATE_TASK + */ +int __po_hi_create_generic_task (const __po_hi_task_id id, + const __po_hi_time_t* period, + const __po_hi_priority_t priority, + const __po_hi_stack_t stack_size, + const __po_hi_int8_t core_id, + void* (*start_routine)(void), + void* arg); + +/* + * Wait the end of all tasks. + * This function typically never ends, because all tasks + * are doing an infinite loop and never ends. It just + * used to avoid an infinite loop in the main thread. + */ +void __po_hi_wait_for_tasks (void); + +/* + * Called by a periodic task, to wait for its next period + * The argument is the task identifier + * Returns SUCCESS value, and if fails, returns a negative value + */ +int __po_hi_wait_for_next_period (__po_hi_task_id task); + +/* + * Sleep until the time given in argument. The second + * argument is the task identifier which will sleep. + * Return SUCCESS if there is no error. Else, it returns + * a negative value : ERROR_CLOCK or ERROR_PTHREAD_COND + */ + int __po_hi_task_delay_until (__po_hi_time_t* time, __po_hi_task_id task); + +/* + * Computer the next period for a task, according to the period + * argument given at initialization time. The argument task + * is the task-identifier in the node (__po_hi_task_id type). + */ + int __po_hi_compute_next_period (__po_hi_task_id task); + + /* + * Delete all the tasks that were created within the system. + */ +void __po_hi_tasks_killall (void); + + /* + * Wait a given amount of time. + */ +void __po_hi_task_wait_offset (const __po_hi_time_t* time); + + +#endif /* __PO_HI_TASK_H__ */ diff --git a/doc/source/ping/po_hi_time.h b/doc/source/ping/po_hi_time.h new file mode 100644 index 00000000..9ecaeae2 --- /dev/null +++ b/doc/source/ping/po_hi_time.h @@ -0,0 +1,154 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2014 ESA & ISAE. + */ + +#ifndef __PO_HI_TIME_H__ +#define __PO_HI_TIME_H__ + +#include + +#ifndef HAVE_CLOCK_GETTIME +#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (RTEMS_POSIX) || defined (__PO_HI_RTEMS_CLASSIC_API) +#else +#include +#endif + +#include +#endif + +#ifdef XENO_NATIVE +#include +#include +#endif + + +#ifdef _WIN32 +#include +#include + +/* + * Win32 helper functions to convert __po_hi_time_t to a representation + * that would be suitable for Windows. + */ +unsigned __po_hi_windows_tick_to_unix_seconds(long long win_ticks); +LARGE_INTEGER __po_hi_unix_seconds_to_windows_tick(unsigned sec, unsigned nsec); +#endif + + +typedef struct +{ + __po_hi_uint32_t sec; /* amount of second */ + __po_hi_uint32_t nsec; /* amount of nanosecond */ +}__po_hi_time_t; +/* + * Represent the time in PolyORB-HI. + * + * The value stored in this type depends on the system : on POSIX, it + * is the epoch (time since 1970), on other systems, it can be the + * number of elapsed ticks since the beginning of the program. + * + * The granularity of the time is in microsecond (10^-6) + */ + +#define ORIGIN_OF_TIME ((__po_hi_time_t) { 0, 0 }) + +__po_hi_time_t get_epoch(void); +void set_epoch (void); +int milliseconds_since_epoch (void); +/* Set/get PolyORB-HI/C runtime epoch: the common starting date of all + tasks. Note: the epoch should be set relative to the completion of + the initialization of the runtime and all threads. See po_hi_main.h + for details. + */ + +#define __PO_HI_TIME_TO_US(value) ((value.sec*1000000)+(value.nsec / 1000)) + +#define __PO_HI_TIME_TO_MS(value) ((value.sec*1000)+(value.nsec / 1000000)) + +int __po_hi_get_time (__po_hi_time_t* mytime); +/* + * Get the current time and store informations + * in the structure mytime. + * If there is an error, returns a negative value + * (ERROR_CLOCK). Else, returns a positive value. + */ + +int __po_hi_add_times (__po_hi_time_t* result, + const __po_hi_time_t* left, + const __po_hi_time_t* right); +/* + * Add the two structures given in parameter. The returned + * value is the result of the operation. + */ + +int __po_hi_seconds (__po_hi_time_t* time, + const __po_hi_uint32_t seconds); +/* + * Build a __po_hi_time_t value which contains the + * amount of time (in seconds) represented by the + * argument seconds. + */ + +int __po_hi_milliseconds (__po_hi_time_t* time, + const __po_hi_uint32_t milliseconds); +/* + * Build a __po_hi_time_t value which contains the + * amount of time (in milliseconds) represented by the + * argument milliseconds. + */ + +int __po_hi_microseconds (__po_hi_time_t* time, + const __po_hi_uint32_t microseconds); +/* + * Build a __po_hi_time_t value which contains the + * amount of time (in microseconds) represented by the + * argument microseconds. + */ + +int __po_hi_delay_until (const __po_hi_time_t* time); +/* + * sleep until the time given in argument. + * Return SUCCESS if there is no error. Else, it returns + * a negative value : ERROR_CLOCK or ERROR_PTHREAD_COND + */ + +int __po_hi_time_copy (__po_hi_time_t* dst, const __po_hi_time_t* src); +/* + * Copy a time value from src to dst. + * Returns __PO_HI_SUCCESS if successful. + */ + + +#ifdef NEED_CLOCK_GETTIME +#define CLOCK_REALTIME 0 +int clock_gettime(int clk_id, struct timespec *tp); +#endif +/* + * If the system doesn't support the clock_gettime function, we + * emulate it. For example, Darwin does not support it + */ + + +int __po_hi_time_is_greater (const __po_hi_time_t* value, const __po_hi_time_t* limit); +/* + * Indicates if a time value is greater than an other. + * Returns 1 if value is greater than limit. + * Returns 0 otherwise. + */ + +#include +#ifndef ETIMEDOUT +#define ETIMEDOUT 60 +#endif +/* + * Ensure that ETIMEDOUT is defined + * Workaround for bug #286 + */ + +#endif /* __PO_HI_TIME_H__ */ diff --git a/doc/source/ping/po_hi_transport.h b/doc/source/ping/po_hi_transport.h new file mode 100644 index 00000000..0ea0a5df --- /dev/null +++ b/doc/source/ping/po_hi_transport.h @@ -0,0 +1,315 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2018 ESA & ISAE. + */ + +#ifndef __PO_HI_TRANSPORT__ +#define __PO_HI_TRANSPORT__ + +#include +#include +#include + +#define __PO_HI_BIGENDIAN 0 +#define __PO_HI_LITTLEENDIAN 1 + +#ifndef __PO_HI_NB_PROTOCOLS +#define __PO_HI_NB_PROTOCOLS 0 +#endif + +typedef struct +{ + void (*marshaller) (void*, void*, int*); + void (*unmarshaller) (void*, void*, int); +}__po_hi_protocol_conf_t; + + +#if __PO_HI_NB_PORTS > 0 + +typedef int (*__po_hi_transport_sending_func)(__po_hi_task_id, __po_hi_port_t); + +typedef uint8_t __po_hi_queue_id; + +/** + * \fn __po_hi_transport_get_n_accessed_buses + * + * \brief Return the number of buses associated with a device. + * If no bus is connected to the device or if the device + * is invalid, the function returns 0. Otherwise, a positive value is + * returned. + */ +uint32_t __po_hi_transport_get_n_accessed_buses (const __po_hi_device_id device); + +/** + * \fn __po_hi_transport_get_accessed_buses + * + * \brief Return a pointer to an array that contains all buses identifiers + * accessed by the device passed as argument. If the argument is an invalid + * device-id or if the device does not access any bus, NULL is returned. + * The size of the array can be retrieved by the __po_hi_get_n_accessed_buses + * function. + */ +__po_hi_bus_id* __po_hi_transport_get_accessed_buses (const __po_hi_device_id device); + + +/** + * \fn __po_hi_transport_share_bus + * + * \brief Returns 1 if two devices share a common bus, 0 otherwise. + */ +int __po_hi_transport_share_bus (const __po_hi_device_id, const __po_hi_device_id); + +/** + * \fn __po_hi_get_node_from_entity + * + * \brief Returns the node identifier that corresponds to an entity. + */ +__po_hi_node_t __po_hi_transport_get_node_from_entity (const __po_hi_entity_t entity); + +/* + * \fn __po_hi_get_entity_from_global_port + * + * \brief Return the entity identifier that own the port in parameters. + */ +__po_hi_entity_t __po_hi_get_entity_from_global_port (const __po_hi_port_t port); + +/* + * \fn __po_hi_transport_send_default + * \brief Default transport layer function. + */ +int __po_hi_transport_send (__po_hi_task_id id, __po_hi_port_t port); + +#define __po_hi_transport_send_default __po_hi_transport_send +#define __po_hi_send_output __po_hi_transport_send + +/* + * \fn __po_hi_get_port_name + * \brief Return the name of the port similar to the name within the AADL model. + */ +char* __po_hi_get_port_model_name (const __po_hi_port_t port); + +/* + * \fn __po_hi_get_port_name + * \brief Return the name of the port according to mapping rules. + */ +char* __po_hi_get_port_name (const __po_hi_port_t port); + +/* + * \fn __po_hi_get_local_port_from_local_port + * \brief Return the local port identifier of the given global port to handle data on the node. + */ + +__po_hi_local_port_t __po_hi_get_local_port_from_global_port (const __po_hi_port_t global_port); + +/* + * \fn __po_hi_get_endianness + * \brief Return the endianness of the node given in parameter. + * + * The resulting value is either __PO_HI_BIGENDIAN or __PO_HI_LITTLEENDIAN. + */ +__po_hi_uint8_t __po_hi_get_endianness (const __po_hi_node_t node); + +/* + * \fn __po_hi_get_device_from_port + * \brief Return the device associated with a given port. + * + * The resulting value is a device identifier generated in deployment.h. + * If no device is associated with the port, it returns the constant + * value invalid_device_id. + */ +__po_hi_device_id __po_hi_get_device_from_port (const __po_hi_port_t port); + + +char* __po_hi_get_device_naming (const __po_hi_device_id dev); + +/* + * \fn __po_hi_get_device_configuration + * \brief Returns a pointer to the configuration data of the device. + * + * The configuration data can be either a string of a more complex + * data structure, such as an instance of an ASN1 type. + */ +void* __po_hi_get_device_configuration (const __po_hi_device_id); + + +/* + * \fn __po_hi_transport_get_data_size + * \brief Returns the size of the data stored in the port given as parameter. + */ +__po_hi_uint32_t __po_hi_transport_get_data_size (const __po_hi_port_t portno); + + +/* + * \fn __po_hi_transport_get_queue_size + * \brief Return the size of the queue associated with the port. + * + * The size if specified as the number of request the port can store, + * this is NOT the number of bytes that can be stored. + */ +__po_hi_uint32_t __po_hi_transport_get_queue_size (const __po_hi_port_t portno); + +/* + * \fn __po_hi_transport_get_port_kind + * \brief Indicate the kind of the port given in parameter or __PO_HI_INVALID_PORT_KIND when not appropriate. + * + * The values that are returned indicate if the port is a pure event + * port, if it has a data associated and if it is an inter-process + * port or not. + * + * Potential return values are: + * + * __PO_HI_IN_DATA_INTER_PROCESS + * __PO_HI_OUT_DATA_INTER_PROCESS + * __PO_HI_IN_DATA_INTRA_PROCESS + * __PO_HI_OUT_DATA_INTRA_PROCESS + * __PO_HI_IN_EVENT_DATA_INTER_PROCESS + * __PO_HI_OUT_EVENT_DATA_INTER_PROCESS + * __PO_HI_IN_EVENT_DATA_INTRA_PROCESS + * __PO_HI_OUT_EVENT_DATA_INTRA_PROCESS + * __PO_HI_IN_EVENT_INTER_PROCESS + * __PO_HI_OUT_EVENT_INTER_PROCESS + * __PO_HI_IN_EVENT_INTRA_PROCESS + * __PO_HI_OUT_EVENT_INTRA_PROCESS + * __PO_HI_INVALID_PORT_KIND + */ +__po_hi_port_kind_t __po_hi_transport_get_port_kind (const __po_hi_port_t portno); + + +/* + * \fn __po_hi_transport_get_model_name + * \brief Return the name of the port given in parameter. + */ + +char* __po_hi_transport_get_model_name (const __po_hi_port_t portno); + + +/* \fn __po_hi_transport_get_mynode + * \brief Return the node identifier of the node that executes the current system. + */ +__po_hi_node_t __po_hi_transport_get_mynode (void); + +/* \fn __po_hi_transport_get_node_from_device + * \brief Return the node identifier associated with the device given in parameter. + */ +__po_hi_node_t __po_hi_transport_get_node_from_device (const __po_hi_device_id device); + + +/* \fn __po_hi_transport_associate_port_bus + * \brief Associate a port to a bus. Return 1 on success, 0 otherwise. + * + * When calling this function, you have to be very careful and make sure + * that the bus you are passing by argument is connected to the node + * that actually host this port. + * Definition of port and bus values are enclosed in the deployment.h + * file generated by Ocarina. + */ + +int __po_hi_transport_associate_port_bus (const __po_hi_port_t port, const __po_hi_bus_id bus); + +/* + * \fn __po_hi_transport_get_protocol + * \brief Return the protocol identifier that is used between port src and port dst. + * + * Get the protocol identifier used to communicate + * between port src and port dst. It returns a protocol + * identifier generated in deployment.h. + * If no specific protocol is used, it returns the value + * invalid_protocol. + */ +__po_hi_protocol_t __po_hi_transport_get_protocol (const __po_hi_port_t src, const __po_hi_port_t dst); + +/* + * \fn __po_hi_transport_get_protocol_configuration + * \brief Retrieve the configuration of the given protocol identifier. Returns a pointer on the conf or NULL. + * + * + * Protocol identifier can be retrieve in the generated deployment.h file + * under the type __po_hi_protocol_t. Invalid protocol identifier + * will result in returning NULL. + */ +__po_hi_protocol_conf_t* __po_hi_transport_get_protocol_configuration (const __po_hi_protocol_t p); + + +/* + * \fn __po_hi_transport_set_sending_func + * \brief Set the sending function to be called to send data using a particular device. + * + * + * The first argument is device that would be used to send the data while the + * second is the function that would be called. + * + * The function returns __PO_HI_SUCCESS when the new calling function + * is successfully set. Otherwise, returns __PO_HI_UNAVAILABLE. + */ +int __po_hi_transport_set_sending_func (const __po_hi_device_id device, const __po_hi_transport_sending_func func); + +/* + * \fn __po_hi_transport_call_sending_func_by_device + * \brief Call the sending function to send data from a port associated to a + * task. + * + * First argument is the device that would be used to send the data. The second + * argument is the task that is sending the data while th third argument + * is the port identifier that contain the data to be sent. + * + * The function returns __PO_HI_UNAVAILABLE is no sending function + * has been set for this device or if the device identifier is invalid. + * Otherwise, it returns the value returned by the sending function + * associated to the device. + */ +int __po_hi_transport_call_sending_func_by_device (const __po_hi_device_id, __po_hi_task_id, __po_hi_port_t); + +/* + * \fn __po_hi_transport_call_sending_func + * \brief Call the sending function to send data from a port associated to a + * task. The function to call is retrieved using the port. + * + * First argument is the task that is sending the data. The second + * is the port associated with the task and the device. The device + * to call is deduced from the port. + * + * The function returns __PO_HI_UNAVAILABLE is no sending function + * has been set for this device or if the device identifier is invalid. + * Otherwise, it returns the value returned by the sending function + * associated to the device. + */ +int __po_hi_transport_call_sending_func_by_port (__po_hi_task_id, __po_hi_port_t); + + + +/* + * \fn __po_hi_transport_get_sending_func + * \brief Get the sending function to be called to send data using a device + * + * + * The first argument is device that would be used to send the data. + * Returns NULL if the device identifier is incorrect or no function + * has been set. + */ + +__po_hi_transport_sending_func __po_hi_transport_get_sending_func (const __po_hi_device_id device); + +/* + * These functions map PolyORB-HI/C ports to Xtratum (resp. AIR) ones + */ + +#ifdef XM3_RTEMS_MODE +void __po_hi_transport_xtratum_port_init (const __po_hi_port_t portno, int val); +int __po_hi_transport_xtratum_get_port (const __po_hi_port_t portno); +#endif + +#ifdef AIR_HYPERVISOR +void __po_hi_transport_air_port_init (const __po_hi_port_t portno, long int val); +long int __po_hi_transport_air_get_port (const __po_hi_port_t portno); +#endif + +#endif /* __PO_HI_NB_PORTS > 0 */ + + + +#endif /* __PO_HI_TRANSPORT__ */ diff --git a/doc/source/ping/po_hi_types.h b/doc/source/ping/po_hi_types.h new file mode 100644 index 00000000..bc5cd1bd --- /dev/null +++ b/doc/source/ping/po_hi_types.h @@ -0,0 +1,109 @@ +/* + * This is a part of PolyORB-HI-C distribution, a minimal + * middleware written for generated code from AADL models. + * You should use it with the Ocarina toolsuite. + * + * For more informations, please visit http://taste.tuxfamily.org/wiki + * + * Copyright (C) 2007-2009 Telecom ParisTech, 2010-2017 ESA & ISAE. + */ + +#ifndef __PO_HI_TYPES_H_ +#define __PO_HI_TYPES_H_ + +#include"po_hi_config.h" + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_STDBOOL_H +#include +#endif + +#define __PO_HI_UNUSED_NODE -1 + +/* + * Types are configured according to the ones available + * on the target host. + */ + +#ifdef HAVE_STDBOOL_H +typedef bool __po_hi_bool_t; +#else +#error This configuration is not supported, PolyORB-HI/C requires a C compiler supporting the "bool" type. +#endif + +typedef float __po_hi_float32_t; +typedef double __po_hi_float64_t; + +#ifdef HAVE_STDINT_H + typedef int8_t __po_hi_int8_t; + typedef int16_t __po_hi_int16_t; + typedef int32_t __po_hi_int32_t; +#ifndef COMPCERT + typedef int64_t __po_hi_int64_t; +#endif + typedef uint8_t __po_hi_uint8_t; + typedef uint16_t __po_hi_uint16_t; + typedef uint32_t __po_hi_uint32_t; +#ifndef COMPCERT + typedef uint64_t __po_hi_uint64_t; +#endif +#else + +/* + * Most modern compilers have stdint.h header file. + */ + +#error This configuration is not supported, PolyORB-HI/C requires a C compiler with support for the stdint.h header file. + + #if SIZEOF_INT == 4 + typedef int __po_hi_int32_t; + #elif SIZEOF_LONG_INT == 4 + typedef long int __po_hi_int32_t; + #elif SIZEOF_SHORT_INT == 4 + typedef short int __po_hi_int32_t; + #endif + + #if SIZEOF_INT == 2 + typedef int __po_hi_int16_t; + typedef unsigned int __po_hi_uint16_t; + #elif SIZEOF_SHORT_INT == 2 + typedef short int __po_hi_int16_t; + typedef unsigned short int __po_hi_uint16_t; + #elif SIZEOF_LONG_INT == 2 + typedef long int __po_hi_int16_t; + typedef unsigned long int __po_hi_uint16_t; + #endif + + #if SIZEOF_CHAR == 1 + typedef char __po_hi_int8_t; + typedef unsigned char __po_hi_uint8_t; + #endif +#endif + +typedef unsigned char __po_hi_byte_t; + +typedef __po_hi_int32_t __po_hi_port_id_t; + +typedef enum +{ + __PO_HI_IN_DATA_INTER_PROCESS = 0, + __PO_HI_OUT_DATA_INTER_PROCESS = 2, + __PO_HI_IN_DATA_INTRA_PROCESS = 4, + __PO_HI_OUT_DATA_INTRA_PROCESS = 6, + __PO_HI_IN_EVENT_DATA_INTER_PROCESS = 8, + __PO_HI_OUT_EVENT_DATA_INTER_PROCESS = 10, + __PO_HI_IN_EVENT_DATA_INTRA_PROCESS = 12, + __PO_HI_OUT_EVENT_DATA_INTRA_PROCESS = 14, + __PO_HI_IN_EVENT_INTER_PROCESS = 16, + __PO_HI_OUT_EVENT_INTER_PROCESS = 18, + __PO_HI_IN_EVENT_INTRA_PROCESS = 20, + __PO_HI_OUT_EVENT_INTRA_PROCESS = 22, + __PO_HI_INVALID_PORT_KIND = 50 +}__po_hi_port_kind_t; + +void __po_hi_copy_array (void* dst, void* src, __po_hi_uint32_t size); + +#endif /* __PO_HI_TYPES_H_ */ diff --git a/doc/source/ping/port_cnx.aadl b/doc/source/ping/port_cnx.aadl new file mode 100644 index 00000000..1ef250a9 --- /dev/null +++ b/doc/source/ping/port_cnx.aadl @@ -0,0 +1,20 @@ +system PING +end PING; + +system implementation PING.Impl +subcomponents + -- Nodes + Node_A : process A.Impl; + Node_B : process B.Impl {ARAO::port_number => 12002;}; + + -- Processors + CPU_A : processor the_processor; + CPU_B : processor the_processor; +connections + -- Port connections + event data port Node_A.Out_Port -> Node_B.In_Port; +properties + -- Processor bindings + actual_processor_binding => reference CPU_A applies to Node_A; + actual_processor_binding => reference CPU_B applies to Node_B; +end PING.Impl; diff --git a/doc/source/ping/processor_binding.aadl b/doc/source/ping/processor_binding.aadl new file mode 100644 index 00000000..9f0bedc8 --- /dev/null +++ b/doc/source/ping/processor_binding.aadl @@ -0,0 +1,19 @@ +system PING +end PING; + +system implementation PING.Impl +subcomponents + -- Nodes + Node_A : process A.Impl; + Node_B : process B.Impl {ARAO::port_number => 12002;}; + + -- Processors + CPU_A : processor the_processor; + CPU_B : processor the_processor; +connections + -- ... +properties + -- Processor bindings + actual_processor_binding => reference CPU_A applies to Node_A; + actual_processor_binding => reference CPU_B applies to Node_B; +end PING.Impl; diff --git a/doc/source/ping/protected_object_types.aadl b/doc/source/ping/protected_object_types.aadl new file mode 100644 index 00000000..74f4ba5c --- /dev/null +++ b/doc/source/ping/protected_object_types.aadl @@ -0,0 +1,46 @@ +-- Data type of object field + +data Field_Type +properties + ARAO::Data_Type => Integer; +end Field_Type; + +-- Protected data type + +data Protected_Object +features + Update : subprogram Protected_Update; + Read : subprogram Protected_Read; +properties + ARAO::Object_Kind => Protected; + -- This property tells that we have a protected object type +end Protected_Object; + +-- The implementation of the protected object + +data implementation Protected_Object.Impl +subcomponents + Field : data Field_Type; +end Protected_Object.Impl; + +-- Subprograms + +subprogram Protected_Update +features + this : requires data access Protected_Object.Impl + {required_access => access Read_Write;}; -- Mandatory + P : in parameter Field_Type; +properties + source_language => Ada95; + source_name => "Repository"; +end Protected_Update; + +subprogram Protected_Read +features + this : requires data access Protected_Object.Impl + {required_access => access Read_Only;}; -- Mandatory + P : out parameter Field_Type; +properties + source_language => Ada95; + source_name => "Repository"; +end Protected_Read; diff --git a/doc/source/ping/scenario_sample.aadl b/doc/source/ping/scenario_sample.aadl new file mode 100644 index 00000000..a6f95fb5 --- /dev/null +++ b/doc/source/ping/scenario_sample.aadl @@ -0,0 +1,11 @@ +system mysystem +properties + Ocarina_Config::AADL_Files => + ("mymodel1.aadl", "mymodel2.aadl"); + Ocarina_Config::Generator => polyorb_hi_c; + Ocarina_Config::Needed_Property_Sets => + (ARAO, Cheddar_Properties); +end mysystem; + +system implementation mysystem.Impl +end mysystem.Impl; diff --git a/doc/source/ping/simple_types.aadl b/doc/source/ping/simple_types.aadl new file mode 100644 index 00000000..7ccb1c28 --- /dev/null +++ b/doc/source/ping/simple_types.aadl @@ -0,0 +1,41 @@ +-- Boolean type + +data Boolean_Data +properties + ARAO::Data_Type => Boolean; +end Boolean_Data; + +-- Integer type + +data Integer_Data +properties + ARAO::Data_Type => Integer; +end Integer_Data; + +-- Fixed point type + +data Fixed_Point_Type +properties + ARAO::Data_Type => Fixed; + + ARAO::Data_Digits => 10; + -- The total number of digits is 10 + + ARAO::Data_Scale => 4; + -- The precision is 10**(-4) +end Fixed_Point_Type; + +-- Character type + +data Character_Data +properties + ARAO::Data_Type => Character; +end Character_Data; + +-- Wide character type + +data W_Character_Data +properties + ARAO::Data_Type => Wide_Character; +end W_Character_Data; + diff --git a/doc/source/ping/subprograms.c b/doc/source/ping/subprograms.c new file mode 100644 index 00000000..67e3770f --- /dev/null +++ b/doc/source/ping/subprograms.c @@ -0,0 +1,16 @@ +#include +#include +void user_do_ping_spg + (simple_type* data_source); +/*****************/ +/* do_ping_spg */ +/*****************/ + +void do_ping_spg + (simple_type* data_source) +{ + + user_do_ping_spg(data_source); +} + + diff --git a/doc/source/ping/thread_a.aadl b/doc/source/ping/thread_a.aadl new file mode 100644 index 00000000..046def22 --- /dev/null +++ b/doc/source/ping/thread_a.aadl @@ -0,0 +1,16 @@ +thread P +features + Data_Source : event out data port Simple_Type; +end P; + +thread implementation P.Impl +calls { + -- ... +}; +connections + -- ... +properties + Dispatch_Protocol => Periodic; + Period => 1000 Ms; +end P.Impl; + diff --git a/doc/source/ping/thread_a_full.aadl b/doc/source/ping/thread_a_full.aadl new file mode 100644 index 00000000..f9990f53 --- /dev/null +++ b/doc/source/ping/thread_a_full.aadl @@ -0,0 +1,16 @@ +thread P +features + Data_Source : event out data port Simple_Type; +end P; + +thread implementation P.Impl +calls { + P_Spg : subprogram Do_Ping_Spg; +}; +connections + parameter P_Spg.Data_Source -> Data_Source; +properties + Dispatch_Protocol => Periodic; + Period => 1000 Ms; +end P.Impl; + diff --git a/doc/source/ping/toy_main.c b/doc/source/ping/toy_main.c new file mode 100644 index 00000000..62fb2bff --- /dev/null +++ b/doc/source/ping/toy_main.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +extern pos_impl pos_data; +/***********************/ +/* __PO_HI_MAIN_NAME */ +/***********************/ + +__PO_HI_MAIN_TYPE __PO_HI_MAIN_NAME () +{ + + __po_hi_initialize(); + __po_hi_create_periodic_task(gnc_tmtc_pos_gnc_th_k,__po_hi_milliseconds(1000),250,gnc_th_job); + __po_hi_create_periodic_task(gnc_tmtc_pos_tmtc_th_k,__po_hi_milliseconds(100),190,tmtc_th_job); + pos_data.protected_id = 0; + __po_hi_wait_initialization(); + __po_hi_wait_for_tasks(); + return (__PO_HI_MAIN_RETURN); +} + + diff --git a/doc/source/ping/toy_types.c b/doc/source/ping/toy_types.c new file mode 100644 index 00000000..e9a3c0f4 --- /dev/null +++ b/doc/source/ping/toy_types.c @@ -0,0 +1,29 @@ +#include +#include +/*********************/ +/* pos_impl_update */ +/*********************/ + +void pos_impl_update + (pos_impl* value) +{ + + __po_hi_protected_lock(value->protected_id); + update(&(value->field)); + __po_hi_protected_unlock(value->protected_id); +} + +/*******************/ +/* pos_impl_read */ +/*******************/ + +void pos_impl_read + (pos_impl* value) +{ + + __po_hi_protected_lock(value->protected_id); + read(&(value->field)); + __po_hi_protected_unlock(value->protected_id); +} + + diff --git a/doc/source/ping/toy_types.h b/doc/source/ping/toy_types.h new file mode 100644 index 00000000..50e55dc6 --- /dev/null +++ b/doc/source/ping/toy_types.h @@ -0,0 +1,21 @@ +#ifndef __TYPES_H_ +#define __TYPES_H_ +#include +#include +typedef int pos_internal_type; + +typedef struct +{ + __po_hi_protected_t protected_id; + + pos_internal_type field; + +} pos_impl; + +void pos_impl_update + (pos_impl* value); + +void pos_impl_read + (pos_impl* value); + +#endif diff --git a/doc/source/scenario.aadl b/doc/source/scenario.aadl new file mode 100644 index 00000000..64c3133d --- /dev/null +++ b/doc/source/scenario.aadl @@ -0,0 +1,19 @@ +package Scenario +public + with Ocarina_Config; + with Ocarina_Library; + + system producer_consumer extends Ocarina_Library::Default_PolyORB_HI_C_Config + properties + Ocarina_Config::Referencial_Files => + ("pr_a", "pr_a.ref", + "pr_b", "pr_b.ref"); + Ocarina_Config::AADL_Files +=> + ("producer_consumer.aadl", "software.aadl"); + Ocarina_Config::Root_System_Name => "PC_Simple.impl"; + end producer_consumer; + + system implementation producer_consumer.Impl + end producer_consumer.Impl; + +end scenario; \ No newline at end of file diff --git a/doc/usage.rst b/doc/usage.rst index e8add159..668b157f 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -1,18 +1,145 @@ - .. _usage: ===== Usage ===== +.. _ocarinacli: + Ocarina command-line #################### Ocarina has a rich command-line interface, covering all required steps to parse, instantiate, analyze or generate code from AADL models. -.. include:: ocarina_man.txt - :literal: +.. program:: ocarina + +.. option:: -h, --help + + Display help and exit + +.. option:: --version + + Display version and exit + +.. option:: -v, --verbose + + Output extra verbose information + +.. option:: -q + + Quiet mode (default) + +.. option:: -d + + Debug mode + +.. option:: -s + + Output default search directory, then exit + +.. option:: -aadlv[ARG] + + AADL version, ARG = 1 for AADL 1.0, 2 for AADL 2.x + +.. option:: -f + + Parse predefined non-standard property sets + +.. option:: -disable-annexes=ARG + + Deactivate annex ARG + +.. option:: -r ARG + + Use ARG as root system + +.. option:: -o ARG + + Specify output file/directory + +.. option:: -y + + Automatically load AADL files + +.. option:: -I ARG + + Add ARG to the directory search list + +.. option:: -p + + Parse and instantiate the model + +.. option:: -i + + Instantiate the model + +.. option:: -x + + Parse AADL file as an AADL scenario file + +.. option:: -g ARG + + Generate code using Ocarina backend 'ARG' + +.. option:: --list-backends + + List available backends + +.. option:: --spark2014 + + Generate SPARK2014 annotations + +.. option:: -b + + Compile generated code + +.. option:: -z + + Clean code generated + +.. option:: -k ARG + + Set POK flavor (arinc653/deos/pok/vxworks) + +.. option:: -t + + Run Ocarina in terminal interactive mode + +.. option:: -real_theorem ARG + + Name of the main REAL theorem to evaluate + +.. option:: -real_lib ARG + + Add external library of REAL theorems + +.. option:: -real_continue_eval + + Continue evaluation of REAL theorems after first failure (REAL backend) + +.. option:: -boundt_process ARG + + Generate .tpo file for process ARG (Bound-T backend) + +.. option:: -ec + + Compute coverage metrics + +.. option:: -er + + Execute system + +.. option:: -asn1 + + Generate ASN1 deployment file (PolyORB-HI-C only) + +.. option:: -perf + + Enable profiling with gprof (PolyORB-HI-C only) + + +.. note:: A man page is also installed in Ocarina installation path, in :file:`$OCARINA_PATH/share/man/man1/`. ocarina-config ############## @@ -23,7 +150,3 @@ uses Ocarina's API. .. include:: ocarina_config.txt :literal: - - - - diff --git a/doc/util/AADLLexer.py b/doc/util/AADLLexer.py new file mode 100644 index 00000000..1b40ac6f --- /dev/null +++ b/doc/util/AADLLexer.py @@ -0,0 +1,313 @@ +"""Implementation of a Pygments Lexer for the AADL language.""" + +""" +* Copyright (c) 2018 Contributors +* +* This program and the accompanying materials are made +* available under the terms of the Eclipse Public License 2.0 +* which is available at https://www.eclipse.org/legal/epl-2.0/ +* +* SPDX-License-Identifier: EPL-2.0 +""" + +""" +Original implementation: Sam Procter +Updates: Jerome Hugues, Alexey Khoroshilov +""" + +import sys +import re + +from pygments.lexer import RegexLexer, include, bygroups +from pygments.token import Error, Punctuation, Literal, Token, \ + Text, Comment, Operator, Keyword, Name, String, Number, Generic, \ + Whitespace + +__all__ = ['AADLLexer'] + +class AADLLexer(RegexLexer): + """ + Pygments parser for AADL models. See for + more details. + """ + + name = 'AADL' + aliases = ['aadl'] + filenames = ['*.aadl'] + mimetypes = ['text/x-aadl'] + + flags = re.MULTILINE | re.DOTALL | re.IGNORECASE + + iden_rex = r'[a-zA-Z_][a-zA-Z0-9_\.]*' + class_iden_rex = r'(' + iden_rex + r')(::)('+ iden_rex + r')' + definition_rex = r'(' + iden_rex + r')' + r'(\s*:\s*)\b' + component_category = r'(abstract|data|subprogram|subprogram\s+group|thread|thread\s+group|process|memory|processor|bus|device|virtual\s+processor|virtual\s+bus|system)\b' + + with_tuple = (r'(with)(\s+)', bygroups(Keyword, Whitespace), 'with-list') + text_tuple = (r'([^\S\n]+)', Text) + terminator_tuple = (r'(;)(\s*)', bygroups(Punctuation, Whitespace), '#pop') + comment_tuple = (r'(--[^\n]*\n)', Comment.Single) + comment_whitespace_tuple = (r'(--[^\n]*\n)(\s+)', bygroups(Comment.Single, Whitespace)) + accesses_tuple = (r'(bus|subprogram|subprogram\s+group|data)(\s+)(access)\b', bygroups(Keyword, Whitespace, Keyword)) + features_tuple = (r'(feature|port|event\s+port|data\s+port|event\s+data\s+port|feature\s+group)\b', Keyword) + + tokens = { + 'packageOrSystem': [ + text_tuple, + (r'(implementation)(\s+)(' + iden_rex + r')', bygroups(Name.Class, Whitespace, Name.Class), '#pop'), + (iden_rex, Name.Class, '#pop'), + ], + 'annex': [ + (r'(\s*)(' + iden_rex + r')(\s*)({\*\*.*\*\*})(\s*)(;)', + bygroups(Whitespace, Name.Class, Whitespace, Comment.Multiline, Whitespace, Punctuation)), + ], + 'with-list' : [ + (r'\s*(,)\s*', Punctuation), + (r'[a-zA-Z_]\w*', Name.Namespace), + terminator_tuple, + ], + 'alias-body' : [ + (component_category, Keyword.Declaration), + (r'(\s+)', Whitespace), + (class_iden_rex, bygroups(Name.Class, Punctuation, Name.Entity)), + terminator_tuple, + ], + 'package-declaration' : [ + text_tuple, + (r'(implementation)', Keyword.Declaration), + (r'(' + iden_rex + r')(;)', bygroups(Name.Class, Punctuation), '#pop'), + (class_iden_rex + r'(;)', bygroups(Name.Class, Punctuation, Name.Entity, Punctuation), '#pop'), + (r'(' + iden_rex + r')(\s*)(extends)(\s*)', bygroups(Name.Class, Whitespace, Keyword.Declaration, Whitespace)), + (class_iden_rex, bygroups(Name.Class, Punctuation, Name.Entity), '#pop'), + (iden_rex, Name.Class, '#pop'), + ], + 'declaration' : [ + text_tuple, + (r'(in|out|event|data)', Keyword), + (r'(provides|requires)', Keyword), + features_tuple, + accesses_tuple, + (r'(flow|path|thread|subprogram)', Keyword), + (component_category, Keyword), + (class_iden_rex, bygroups(Name.Class, Punctuation, Name)), + (r'(' + iden_rex + r')(\s*)(->|<-|<->)(\s*)('+ iden_rex + r')', bygroups(Name, Whitespace, Operator, Whitespace, Name.Variable)), + (iden_rex, Name.Function), + (r'({)(\s+)', bygroups(Punctuation, Whitespace), 'property-constant-declaration'), + (r'}', Punctuation), + terminator_tuple, + ], + 'applies-to' : [ + text_tuple, + (r'\(', Punctuation), + (r'\s*(,)\s*', Punctuation), + (r'\s*(\*\*)\s*', Operator), + features_tuple, + accesses_tuple, + (component_category, Keyword), + (class_iden_rex, bygroups(Name.Class, Punctuation, Name.Entity)), + (r'(' + iden_rex + r')', Name.Class), + (r'(\{)(' + iden_rex + r')(\})', bygroups(Punctuation, Name.Class, Punctuation)), + (r'\)', Punctuation), + (r';', Punctuation, '#pop:2'), + ], + 'property-value' : [ + (r'(true|false)', Keyword.Constant), + (r'\(', Punctuation), + (r'\)', Punctuation), + (r',', Punctuation), + (r'[0-9]+\.[0-9]*', Number.Float), + (r'[0-9]+', Number.Integer), + (r'(reference)(\s*)(\()(' + iden_rex + ')(\))', + bygroups(Keyword.Declaration, Whitespace, Punctuation, Name.Variable.Instance, Punctuation)), + (r'"[^"]*"', Literal.String.Double), + (r'(\s*)(\.\.)(\s+)', bygroups(Whitespace, Operator, Whitespace)), + (class_iden_rex, bygroups(Name.Class, Punctuation, Name.Variable)), + (r'(\s*)(applies)(\s+)(to)(\s+)', bygroups(Whitespace, Keyword.Declaration, Whitespace, Keyword.Declaration, Whitespace), 'applies-to'), + (r'(' + iden_rex +r')', Name.Constant), + (r'(\[)(\s*)', bygroups(Punctuation, Whitespace), 'record_term'), + (r'(\s+)', Whitespace), + terminator_tuple, + ], + 'record_term' : [ + (r'(' + iden_rex + r')(\s*)(=>)(\s*)', bygroups(Name.Class, Whitespace, Operator, Whitespace), 'property-value'), + (r'(\])', Punctuation, '#pop'), + ], + 'property-section-property-value' : [ + include('property-value'), + terminator_tuple, + ], + 'property-constant-value' : [ + include('property-value'), + (r'(;)(\s+)', bygroups(Punctuation, Whitespace), '#pop:2') + ], + 'aggregate-property-constant-list' : [ + (r'(' + iden_rex + r')(\s*)(=>)(\s*)', bygroups(Name.Class, Whitespace, Operator, Whitespace)), + (r'\s*;\s*', Punctuation), + include('property-value'), + (r'(\]\s*;)(\s+)', bygroups(Punctuation, Whitespace), '#pop:2'), + ], + 'property-declaration' : [ + comment_tuple, + (r'(inherit|list\s+of)', Keyword.Declaration), + # aadl property types + (r'(aadlboolean|aadlinteger|aadlreal|aadlstring|enumeration|range\s+of|classifier|reference|record)', Keyword.Type), + (r'(,|\(|\)|\+|-|\.\.|:|;)', Punctuation), + (r'(units)(\s*)(\()', bygroups(Keyword.Declaration, Whitespace, Punctuation), 'units-list'), + (r'[0-9]+', Number.Integer), + features_tuple, + accesses_tuple, + (component_category, Keyword.Type), + (r'(=>)(\s*)', bygroups(Operator, Whitespace), 'applies-to-property-value'), + (r'(applies)(\s+)(to)(\s+)', bygroups(Keyword.Declaration, Whitespace, Keyword.Declaration, Whitespace), 'applies-to'), + (class_iden_rex, Name.Class), + (r'(' + iden_rex + r')', Name.Class), + (r'(\s+)', Whitespace), + ], + 'units-list' : [ + comment_tuple, + (r'(' + iden_rex + r')', Name.Class), + (r'(,|\*|=>)', Punctuation), + (r'(\s+)', Whitespace), + (r'(\))', Punctuation, '#pop'), + ], + 'applies-to-property-value' : [ + (r'(applies)(\s+)(to)(\s+)', bygroups(Keyword.Declaration, Whitespace, Keyword.Declaration, Whitespace), 'applies-to'), + include('property-value'), + ], + 'property-constant-declaration' : [ + text_tuple, + (class_iden_rex + r'(\s*)(=>)(\s*)(\[)(\s*)', bygroups(Name.Class, Punctuation, Name.Constant, Whitespace, Operator, Whitespace, Punctuation, Whitespace), 'aggregate-property-constant-list'), + (r'(' + iden_rex + r')(\s*)(=>)(\s*)(\[)(\s*)', bygroups(Name.Class, Whitespace, Operator, Whitespace, Punctuation, Whitespace), 'aggregate-property-constant-list'), + (class_iden_rex + r'(\s*)(=>)(\s*)', bygroups(Name.Class, Punctuation, Name.Constant, Whitespace, Operator, Whitespace), 'property-constant-value'), + (r'(' + iden_rex + r')(\s*)(=>)(\s*)', bygroups(Name.Class, Whitespace, Operator, Whitespace), 'property-constant-value'), + ], + 'property-set' : [ + comment_tuple, + with_tuple, + (r'(' + iden_rex + r')(\s+)(is)(\s+)', bygroups(Name.Class, Whitespace, Keyword.Namespace, Whitespace)), + (definition_rex + r'(constant)', bygroups(Name.Variable.Global, Punctuation, Keyword), 'property-constant-declaration'), + (definition_rex, bygroups(Name.Variable.Global, Punctuation), 'property-declaration'), + (r'(end)(\s+)(' + iden_rex + r')(;)', bygroups(Keyword.Namespace, Whitespace, Name.Class, Punctuation), '#pop'), + (r'(\s+)', Whitespace), + ], + 'property-section' : [ + text_tuple, + comment_whitespace_tuple, + (class_iden_rex + r'(\s*)(=>)(\s*)', + bygroups(Name.Class, Punctuation, Name.Entity, Whitespace, Operator, Whitespace), 'property-section-property-value'), + (r'(' + iden_rex + r')(\s*)(=>)(\s*)', + bygroups(Name.Class, Whitespace, Operator, Whitespace), 'property-section-property-value'), + (r'(\*\*})(\s*)(;)', bygroups(Punctuation, Whitespace, Punctuation), '#pop'), + (r'([\s+])', Whitespace), + (r'', Whitespace, '#pop'), + ], + 'call-section' : [ + text_tuple, + comment_whitespace_tuple, + (r'(' + iden_rex + r')(\s*)(:)(\s*)({)(\s*)', bygroups(Name.Class, Whitespace, Punctuation, Whitespace, Punctuation, Whitespace)), + (definition_rex, bygroups(Name.Variable, Punctuation), 'declaration'), + (r'}', Punctuation), + terminator_tuple, + ], + 'id-or-classid': [ + (class_iden_rex, bygroups(Name.Class, Punctuation, Name.Entity), '#pop'), + (r'(' + iden_rex + r')', Name.Entity, '#pop'), + ], + 'semicolon': [ + (r'(\s*)(;)', bygroups(Whitespace, Punctuation), '#pop'), + ], + 'emv2-annex': [ + (r'(use)(\s+)(types|type\s+equivalence|mappings|behavior)(\s+)', + bygroups(Keyword.Namespace, Whitespace, Keyword.Namespace, Whitespace), ('semicolon', 'id-or-classid')), + (r'(error\s+propagations)(\s+)', bygroups(Keyword.Namespace, Whitespace), 'emv2-propagations'), + (r'(component\s+error\s+behavior)(\s+)', bygroups(Keyword.Namespace, Whitespace), 'emv2-component'), + (r'(\*\*})(\s*)(;)', bygroups(Punctuation, Whitespace, Punctuation), '#pop'), + (r'(\s+)', Whitespace), + ], + 'emv2-propagations': [ + (r'(not|in|out|propagation)', Keyword.Namespace), + (r'(:|{|\*|::|}|;)', Punctuation), + (r'(end\s+propagations)(\s*)(;)', bygroups(Keyword.Namespace, Whitespace, Punctuation), '#pop'), + (r'(' + iden_rex + r')', Name.Entity), + (r'(\s+)', Whitespace), + ], + 'emv2-component': [ + (r'(use)(\s+)(transformations)(\s+)', + bygroups(Keyword.Namespace, Whitespace, Keyword.Namespace, Whitespace), ('semicolon', 'id-or-classid')), + (r'(events|transitions|propagations|detections|mode\s+mappings)', Keyword.Namespace), + (r'(all|noerror)', Keyword.Constant), + (r'(:|;|{|}|\(|\))', Punctuation), + (r'(-\[)(\s*)', bygroups(Punctuation, Whitespace), 'emv2-error-condition'), + (r'(end\s+component)(\s*)(;)', bygroups(Keyword.Namespace, Whitespace, Punctuation), '#pop'), + (r'(' + iden_rex + r')', Name.Entity), + (r'(\s+)', Whitespace), + ], + 'emv2-error-condition': [ + (r'(and|ormore|orless|or)', Keyword.Constant), + (r'(\(|\)|\{|\}|::)', Punctuation), + (r'[0-9]+', Number.Integer), + (r'(\]->)', Punctuation, '#pop'), + (r'(' + iden_rex + r')', Name.Entity), + (r'(\s+)', Whitespace), + ], + 'root': [ + (r'(\n\s*|\t)', Whitespace), + comment_tuple, + (r'(package)(\s+)', bygroups(Keyword.Namespace, Text), 'packageOrSystem'), + (r'(public|private)', Keyword.Namespace), + # import_declaration + with_tuple, + # alias_declaration + (r'(' + iden_rex + r')(\s+)(renames)(\s+)', bygroups(Name.Namespace, Whitespace, Keyword, Whitespace), 'alias-body'), + (r'(annex)(\s+)(EMV2)(\s*)({\*\*)', bygroups(Keyword.Namespace, Whitespace, Name.Namespace, Whitespace, Punctuation), + 'emv2-annex'), + (r'(annex)(\s+)', bygroups(Keyword.Namespace, Whitespace), 'annex'), + (component_category + r'(\s+)', bygroups(Keyword.Type, Whitespace), 'package-declaration'), + (r'(calls)(\s+)',bygroups(Keyword.Namespace, Whitespace),'call-section'), + (r'(subcomponents|connections|features|flows)(\s+)', bygroups(Keyword.Namespace, Whitespace)), + (definition_rex, bygroups(Name.Variable, Punctuation), 'declaration'), + (r'(properties)(\s*)', bygroups(Keyword.Namespace, Whitespace), 'property-section'), + (r'(end)(\s+)', bygroups(Keyword.Namespace, Whitespace), 'package-declaration'), + (r'(property\s+set)(\s+)', bygroups(Keyword.Namespace, Whitespace), 'property-set'), + (r'(\s+)', Whitespace), + ] + } + +class AADLPropertyLexer(AADLLexer): + """ + Pygments parser for AADL property declarations. + """ + + name = 'AADL Property' + aliases = ['aadlproperty'] + filenames = [] + mimetypes = [] + + flags = re.MULTILINE | re.DOTALL | re.IGNORECASE + tokens = AADLLexer.tokens.copy() + tokens['root'] = [ + (r'(' + AADLLexer.iden_rex + r')(\s*)(:)(\s*)', + bygroups(Name.Variable, Whitespace, Punctuation, Whitespace), 'property-declaration'), + ] + +class AADLIdLexer(AADLLexer): + """ + Pygments parser for AADL identifiers. + """ + + name = 'AADL Id' + aliases = ['aadlid'] + filenames = [] + mimetypes = [] + + flags = re.MULTILINE | re.DOTALL | re.IGNORECASE + tokens = AADLLexer.tokens.copy() + tokens['root'] = [ + AADLLexer.features_tuple, + AADLLexer.accesses_tuple, + (AADLLexer.component_category, Keyword), + (r'[0-9]+', Number.Integer), + (r'(' + AADLLexer.iden_rex + r')', Name.Variable), + (r'(::|,)', Punctuation), + (r'(\s+)', Whitespace), + ]