• Home
  • History
  • Annotate
  • only in this directory
NameDateSize

..25-Jul-201948

CMakeLists.txtH A D25-Jul-20191.1 KiB

easy-settings.cmakeH A D25-Jul-20191 KiB

griddleH A D21-Oct-201919.9 KiB

init-build.shH A D18-Sep-20191.8 KiB

kernel/H21-Oct-201927

projects/H25-Jul-201914

README.mdH A D25-Jul-2019112.8 KiB

settings.cmakeH A D22-Sep-20192.7 KiB

tools/H25-Jul-20197

README.md

1% CAmkES Manual
2
3<!--
4  Copyright 2017, Data61
5  Commonwealth Scientific and Industrial Research Organisation (CSIRO)
6  ABN 41 687 119 230.
7
8  This software may be distributed and modified according to the terms of
9  the BSD 2-Clause license. Note that NO WARRANTY is provided.
10  See "LICENSE_BSD2.txt" for details.
11
12     @TAG(DATA61_BSD)
13  -->
14
15This document describes the structure and functionality of CAmkES, a platform
16for building componentised systems for embedded platforms. The documentation is
17broken into sections for users, template authors and developers. The
18[Usage](#usage) section is for people wanting to develop systems
19using CAmkES as a platform. The [Templating](#templating) section is
20for people wanting to write their own CAmkES templates and use more complex
21functionality. Finally the [Developers](#developers) section is for
22people wanting to modify the internals of CAmkES itself. If you are modifying
23the internals of CAmkES, it is recommended that you read the entirety of this
24documentation. Regardless of which section is most relevant for you, you should
25at least familiarise yourself with the [Terminology](#terminology) section.
26
27CAmkES' primary target platform is the
28[seL4 microkernel](http://sel4.systems/). The seL4 kernel and its functionality
29are not discussed in this document. It is assumed that the reader has read the
30seL4 programming references and is familiar with how this kernel operates and
31the mechanisms it provides.
32
33## Terminology
34
35Throughout this document some domain specific terminology is used that may have
36connotations outside CAmkES/component systems. To avoid confusion the meanings
37of these terms are made explicit below.
38
39**Abstract Syntax Tree (AST)**
40
41> An internal representation of the results of parsing a generalised grammar.
42  More thorough definitions of ASTs are provided
43  [elsewhere](https://en.wikipedia.org/wiki/Abstract_syntax_tree), but this is
44  noted here because the abbreviation 'AST' is used heavily in this
45  documentation.
46
47**Architecture Description Language (ADL)**
48
49> The CAmkES syntax for describing a component system. Most component platforms
50  have their own architecture description language for describing a set of
51  components and how they are wired together, but the term 'ADL' will be used
52  in this documentation to exclusively refer to the CAmkES input specification
53  language.
54
55**Assembly**
56
57> A top-level element that encapsulates a component system description. An
58  assembly can be thought of as a complete description of a full system.
59  A system must contain at least one assembly. A system with more than one
60  assembly is equivalent to a system with one assembly whose composition
61  and configuration sections are the concatenation of the composition and
62  configuration sections of each assembly.
63
64**Attribute**
65
66> Components and connectors can have extra data of an arbitrary type associated
67  with them. These are referred to as attributes. The description of a
68  component/connector must describe the name of the attribute and its type. The
69  value of the attribute itself is unspecified. It is assigned when the entity
70  is instantiated, and this assignment is referred to as a _setting_. Attributes
71  are generally used to specialise or differentiate a component at runtime.
72  The types of attributes can be constructed as a collection or _struct_ of
73  any of the basic CAmkES types: int, unsigned int, char, unsigned char, string.
74  It is possible to give an attribute a default value when it is declared.  If
75  there are no settings for an attribute, the default setting will be used.  If
76  an attribute is aliased to a different attribute that also has a default,
77  then the different attribute's default will override the original default.
78
79**Component**
80
81> A _type_ of functional entity. It is important to stress this distinction.
82  'Component' is used colloquially to refer to both types and instances, but in
83  a formal sense 'component' refers only to the type. To make this more
84  concrete, the statement `component foo f` describes a component _instance_ f,
85  whose _type_ is foo.
86
87**Composition**
88
89> A container for the component and connector instantiations that form a system.
90  This is essentially a syntactic element for delimiting sections in a
91  specification. It is contained by an assembly block, along with an optional
92  configuration.
93
94**Compound Component**
95
96> A component with a composition section, and optionally a configuration section.
97
98**Configuration**
99
100> A container for describing settings. This is a syntactic element to hold the
101  assignment of attributes for a given system. It is expressed inside an
102  assembly block.
103
104**Connection**
105
106> An instantiation of a connector. Connections connect two _instances_. Because
107  the instantiation of a connector does not really specialise the connector in
108  any particular way, it is easy to conflate the two. However, the sources make
109  important distinctions between connectors and connections.
110
111**Connector**
112
113> A _type_ of link between instances. The distinction between 'connector' and
114  'connection' is the same as that between 'component' and 'instance,' i.e. a
115  connection is an instantiation of a particular connector.
116
117**Consumes**
118
119> Event interfaces that are accepted by a component. If a component consumes a
120  particular event it means that it is expecting to receive and handle that
121  event.
122
123**Dataport**
124
125> Port interfaces that are used by a component. A component's dataports
126  are expected to be available to it at runtime as shared memory regions.
127
128**Direction**
129
130> The flow of a parameter of a procedure method. The only possible directions
131  are 'in' (caller to callee), 'out' (callee to caller), 'inout'
132  (bidirectional) and 'refin' (identical to 'in' except for the C backend where
133  this is optimised to pass-by-reference).
134
135**Emits**
136
137> Event interfaces that are expressed by a component. If a component emits a
138  given event it means that it produces events of this type.
139
140**Event**
141
142> An asynchronous signal interface of a component. Events are defined completely
143  by their identifier, a numerical value. It may be helpful to think of this
144  value as mapping to something like an interrupt number or a signal type,
145  although they do not necessarily represent hardware messages.
146
147**Exported Interface**
148
149> An interface of an internal instance that is presented under the name of an
150  identically typed interface in its containing component. The purpose of
151  exported interfaces is to expose a coherent outward-facing set of interfaces
152  from a component, while potentially implementing those interfaces within
153  nested components.
154
155**Instance**
156
157> An instantiation of a component type. Of course 'instance' can be used to
158  refer to an instantiation of any type, but when you see the term 'instance' in
159  the sources it is generally referring to the instantiation of a component. To
160  give a concrete example, in the statement `component foo f` f is an instance.
161
162**Interface**
163
164> An abstract exposed interaction point of a component. There could be a
165  distinction made here between type and instance of one of these interaction
166  points, but in practice this is not necessary and ambiguity rarely arises. The
167  subcategories of interface are _procedure_, _event_ and _port_.
168
169**Internal Instance**
170
171> A component instance declared inside a compound component's composition section.
172
173**Internal Connection**
174
175> A connection declared inside a compound component which connects two internal
176  instance interfaces. That is, any connection declared inside a compound
177  component.
178
179**Maybe**
180
181> Interfaces of components can be made optional using the `maybe` keyword. Optional
182  interfaces do not need to be connected to any other interfaces. C symbols associated
183  with optional interfaces (functions and dataport pointers) are declared as weak
184  symbols. If nothing is connected to an optional interface, its associated symbols
185  lack definitions. That is, functions and dataport pointers associated with unconnected
186  optional interfaces take the value `NULL` at runtime.
187
188**Method**
189
190> An item of a procedure. When targeting a conventional programming language,
191  methods usually map directly to generated functions.
192
193**Parameter**
194
195> A piece of data referenced by a procedure method. This can be thought of as an
196  argument to a function.
197
198**Port**
199
200> The interface type that represents shared memory semantics.
201
202**Procedure**
203
204> An interface with function call semantics. Procedures consist of a series of
205  methods that can be invoked independently.
206
207**Provides**
208
209> Procedure interfaces implemented by a component. When targeting a conventional
210  programming language this typically means that the component contains
211  functions that are implementations of each method in the procedures provided.
212
213**Setting**
214
215> An assignment of an attribute to a specific value. A setting does not specify
216  the type of the attribute, because this has already been described by the
217  attribute as specified in the component/connector description.
218
219**Struct**
220
221> A collection of named attribute fields that can be used as an attribute type
222  for a component _attribute_.
223
224**Type**
225
226> A procedure method's return type or parameter type. This information does not
227  include the direction of a parameter. An example type is something like
228  'string.'
229
230**Uses**
231
232> Procedure interfaces that are invoked by a component. When targeting a
233  conventional programming language this typically means that the component
234  contains calls to functions that are expected to implement each method in the
235  procedures used.
236
237**Virtual Interface**
238
239> An interface of a compound component that is not implemented by that
240  component, but is an alias for internal instance's interface.
241
242A concrete example:
243
244```camkes
245struct cat {
246    int paws;
247    string name;
248}
249
250procedure thing {
251  int func(in int x);
252}
253
254component foo {
255  control;
256  uses thing t1;
257  emits sig s1;
258  dataport buffer b1;
259  attribute cat kitty;
260}
261
262component bar {
263  provides thing t2;
264  consumes sig s2;
265  dataport buffer b2;
266}
267
268assembly {
269  composition {
270    component foo f;
271    component bar b;
272
273    connection RPC c1(from f.t1, to b.t2);
274    connection Notification c2(from f.s1, to b.s2);
275    connection SharedData c3(from f.b1, to b.b2);
276  }
277  configuration {
278      f.kitty = {"name": "meows", "paws": 4};
279  }
280}
281```
282
283* `thing` is a **procedure**
284* `int` is a **type**
285* `func` is a **method**
286* `in` is a **direction**
287* `x` is a **parameter**
288* `sig` is an **event**
289* `buffer` is a **port**
290* `foo` and `bar` are **component**s
291* `t1` is a **uses**
292* `s1` is a **emits**
293* `b1` and `b2` are **dataport**s
294* `t2` is a **provides**
295* `s2` is a **consumes**
296* `assembly { ... }` is an **assembly**
297* `composition { ... }` is a **composition**
298* `f` and `b` are **instance**s
299* `RPC`, `Notification` and `SharedData` are **connector**s
300* `c1`, `c2` and `c3` are **connection**s
301* `cat` is a **struct**
302* `kitty` is an **attribute**
303* `f.kitty` is a **setting**
304
305## Usage
306
307This section is targeted at people building systems on top of the CAmkES
308platform. It assumes a basic knowledge of C programming.
309
310### Dependencies
311
312Please see [the docsite](https://docs.sel4.systems/HostDependencies) for information about dependencies.
313
314To check you have the appropriate dependencies installed:
315
316```bash
317./tools/check_deps.py
318```
319
320### Tutorial
321
322This section is aimed at getting you up and running with CAmkES applications
323and increase your familiarity with the CAmkES environment. We assume you are
324working in the CAmkES project repository for this.
325
326#### Running a Simple Example
327
328There's an example application under apps/simple that involves two components,
329echo and client, communicating over a single interface.
330
331![Simple system](imgs/echo.png)
332
333To build this example, from the top-level directory run:
334
335```bash
336mkdir build-kzm
337cd build-kzm
338../init-build.sh -DPLATFORM=kzm -DCROSS_COMPILER_PREFIX=arm-none-eabi- -DCAMKES_APP=simple -DSIMULATE=1
339ninja
340```
341
342This produces an image images/simple-image-arm-imx31. To run this image in
343qemu:
344
345```bash
346./simulate
347```
348
349You should see debugging output from the system initialisation, followed by:
350
351```
352echo_int: 42 -> 42
353echo_float: 273421.437500 -> 273421.437500
354echo_double: 273421.427400 -> 273421.427400
355echo_mix: 273421.427400 -> 273421
356echo_string: "hello world" -> "hello world"
357echo_parameter: 123 -> 123 (returned = 123)
358increment_parameter: 100 -> 101
359After the client
360```
361
362To understand what this example is doing, open the files
363apps/simple/components/Echo/src/echo.c and
364apps/simple/components/Client/src/client.c. The implementations of the echo
365functions are in echo.c and they are called from client.c. The function call
366itself happens over a seL4 endpoint. The connection between the two components
367is described in apps/simple/simple.camkes, and the functional interface that
368echo is providing is described in apps/simple/interfaces/Simple.idl4.
369
370If you want to run this example on IA32, repeat the above procedure with a new build
371directory, replacing the configuration line with the following:
372
373```bash
374../init-build.sh -DPLATFORM=ia32 -DCAMKES_APP=simple -DSIMULATE=1
375```
376
377#### Creating An Application
378
379Let's create some simple hello world applications using the different interface
380types available in CAmkES. Create a new application directory with two component
381types:
382
383```bash
384mkdir -p apps/helloworld/components/Hello
385mkdir -p apps/helloworld/components/Client
386```
387
388Functional interfaces, referred to as procedures, are made up of a set of
389methods. Define an interface that the components will communicate over and save
390this under apps/helloworld/interfaces/MyInterface.idl4:
391
392```camkes
393/* apps/helloworld/interfaces/MyInterface.idl4 */
394
395procedure MyInterface {
396  void print(in string message);
397}
398```
399
400This interface consists of a single method, print that takes an input parameter
401of type string. Note that, although we are planning to implement this component
402in C, interfaces are defined with abstract types that have equivalents in all
403target languages. In the case of C, string maps to `char*`. Each component
404needs a description of the interfaces it exposes or needs in so-called
405Architecture Description Language. Create these in
406apps/helloworld/components/Hello/Hello.camkes and
407apps/helloworld/components/Client/Client.camkes.
408
409```camkes
410/* apps/helloworld/components/Hello/Hello.camkes */
411
412import "../../interfaces/MyInterface.idl4";
413
414component Hello {
415  provides MyInterface inf;
416}
417
418/* apps/helloworld/components/Client/Client.camkes */
419
420import "../../interfaces/MyInterface.idl4";
421
422component Client {
423  control;
424  uses MyInterface iface;
425}
426```
427
428Note that each component description needs to import the interface file we
429created above from apps/helloworld/interfaces. Import statements function
430similar to C's `#include`, in that they can be enclosed in double quotes and
431are relative to the source file, or enclosed in angle brackets and refer to a
432built-in file. The Hello component is to contain an implementation of
433MyInterface and the Client component will expect to be provided with an
434implementation of MyInterface. The `control` keyword indicates that Client is
435what is called an active component. This means it will contain a main function
436(prototyped as `run`) and have an active thread of control.
437
438Create a file to describe the instantiation and structure of the system at
439apps/helloworld/helloworld.camkes.
440
441```camkes
442/* apps/helloworld/helloworld.camkes */
443
444import <std_connector.camkes>;
445import "components/Hello/Hello.camkes";
446import "components/Client/Client.camkes";
447
448assembly {
449  composition {
450    component Hello h;
451    component Client c;
452    connection seL4RPCCall conn(from c.iface, to h.inf);
453  }
454}
455```
456
457This file begins with several import statements that reference other files.
458Hello.camkes and Client.camkes are the files we created above, while
459std_connector.camkes is a built-in file that defines the standard CAmkES
460connector types. The body of the system description instantiates each component
461once, `h` of type `Hello` and `c` of type `Client`. The components' interfaces
462are connected via a connection, `conn`, of type `seL4RPCCall`.
463
464Now for the implementation of the components. Create a single source file for
465Hello as apps/helloworld/components/Hello/src/hello.c:
466
467```c
468/* apps/helloworld/components/Hello/src/hello.c */
469
470#include <camkes.h>
471#include <stdio.h>
472
473void inf__init(void) {
474}
475
476void inf_print(const char *message) {
477  printf("Client says: %s\n", message);
478}
479```
480
481The header camkes.h is generated by the CAmkES build system and contains
482prototypes for functions related to MyInterface that this component needs to
483implement. Note that the actual implementations of interface functions are
484prefixed with the component-local name of the interface (inf from Hello.camkes
485above) and an underscore. The function `inf__init` is for this component to do
486any required initialisation. In the case of this example we have no
487initialisation to perform.
488
489Create a source file for Client as
490apps/helloworld/components/Client/src/client.c that calls these functions as if
491they are directly available to it:
492
493```c
494/* apps/helloworld/components/Client/src/client.c */
495
496#include <camkes.h>
497
498int run(void) {
499  const char *s = "hello world";
500  iface_print(s);
501  return 0;
502}
503```
504
505The entry point of a CAmkES component is `run`.
506
507The final thing is to add some build system boiler plate to be able to build
508the system.
509Copy one of the `CMakeLists.txt` files from another application or create
510`apps/helloworld/CMakeLists.txt` from scratch:
511
512```
513cmake_minimum_required(VERSION 3.7.2)
514
515project(helloworld C)
516
517DeclareCAmkESComponent(Client SOURCES components/Client/src/client.c)
518DeclareCAmkESComponent(Hello SOURCES components/Hello/src/hello.c)
519
520DeclareCAmkESRootserver(helloworld.camkes)
521```
522
523You're now ready to compile and run this application, by entering the `CAMKES_APP` value in the cmake configuration GUI:
524
525```bash
526cd build-kzm
527cmake . -DCAMKES_APP=helloworld # set `helloworld` as CAMKES_APP
528ninja
529./simulate
530```
531
532If all goes well you should see:
533
534```
535Client says: hello world
536```
537
538Congratulations, you've just made your first CAmkES application.
539
540#### Under the Hood
541
542We basically just wrote a verbose and roundabout Hello World example, so what
543benefit is CAmkES providing here? Note how the function call between the two
544components looks just like a normal function invocation in C, even though the
545two components are actually in different address spaces. During compilation
546so-called glue code is generated to connect the two components via a seL4
547endpoint and transparently pass the function invocation and return over this
548channel. The communication itself is abstracted in the ADL description in
549apps/helloworld/helloworld.camkes. The connection type we used was seL4RPCCall, but
550it is possible to use another connection type here without modifying the code of
551the components themselves.
552
553CAmkES provides some interface types for other modes of interaction than
554function calls. Events can be used for asynchronous communication and dataports
555for shared memory.
556
557#### An Example of Events
558
559Events are the CAmkES interface type for modelling asynchronous communication
560between components. Like procedures, events connect a single component to
561another single component, but the receiver of an event (called consumer in
562CAmkES parlance) has several ways of receiving the event. The following walks
563through an example demonstrating these.
564
565Create a new application directory with two components:
566
567```bash
568mkdir -p apps/helloevent/components/Emitter
569mkdir -p apps/helloevent/components/Consumer
570```
571
572Events, unlike procedures, do not need to be defined in a separate IDL file. You
573can simply refer to the event type in your component ADL files and CAmkES will
574infer an event type. Create the following description for Emitter:
575
576```camkes
577/* apps/helloevent/components/Emitter/Emitter.camkes */
578
579component Emitter {
580  control;
581  emits MyEvent e;
582}
583```
584
585This description says Emitter is an active component (the control keyword) and
586it emits a single event called e of type MyEvent. Create some basic source code
587for the component that does nothing except emit the event itself:
588
589```c
590/* apps/helloevent/components/Emitter/src/main.c */
591
592#include <camkes.h>
593
594int run(void) {
595  while (1) {
596    e_emit();
597  }
598  return 0;
599}
600```
601
602CAmkES provides an emit function to send the event.
603
604Now let's create a description of the Consumer that will handle this event:
605
606```camkes
607/* apps/helloevent/components/Consumer/Consumer.camkes */
608
609component Consumer {
610  control;
611  consumes MyEvent s;
612}
613```
614
615Note that this component consumes (handles) an event of the same type. Let's
616instantiate and connect these components together using another ADL file:
617
618```camkes
619/* apps/helloevent/helloevent.camkes */
620
621import <std_connector.camkes>;
622import "components/Emitter/Emitter.camkes";
623import "components/Consumer/Consumer.camkes";
624
625assembly {
626  composition {
627    component Emitter source;
628    component Consumer sink;
629    connection seL4Notification channel(from source.e, to sink.s);
630  }
631}
632```
633
634In this file, seL4Notification is a seL4 specific connector for transmitting
635asynchronous signals. The two instantiated components, source and sink are
636connected over the connection channel.
637
638As mentioned above, there are several ways for a component to receive an event.
639The consumer can register a callback function to be invoked when the event is
640received, they can call a blocking function that will return when the event is
641received or they can call a polling function that returns whether an event has
642arrived or not. Let's add some source code that uses all three:
643
644```c
645#include <camkes.h>
646#include <stdio.h>
647
648static void handler(void) {
649  static int fired = 0;
650  printf("Callback fired!\n");
651  if (!fired) {
652    fired = 1;
653    s_reg_callback(&handler);
654  }
655}
656
657int run(void) {
658  printf("Registering callback...\n");
659  s_reg_callback(&handler);
660
661  printf("Polling...\n");
662  if (s_poll()) {
663    printf("We found an event!\n");
664  } else {
665    printf("We didn't find an event\n");
666  }
667
668  printf("Waiting...\n");
669  s_wait();
670  printf("Unblocked by an event!\n");
671
672  return 0;
673}
674```
675
676Note that we re-register the callback during the first execution of the handler.
677Callbacks are deregistered when invoked, so if you want the callback to fire
678again when another event arrives you need to explicitly re-register it.
679
680We now have everything we need to run this system.
681
682Create the appropriate `apps/helloevent/CMakeLists.txt` as for the previous example. Compile the system and
683run it with the simulate script as per the previous example. If all goes well you
684should see something like the following:
685
686```
687Registering callback...
688Callback fired!
689Polling...
690We didn't find an event
691Waiting...
692Unblocked by an event!
693Callback fired!
694```
695
696Whether you find an event during polling will be a matter of the schedule that
697seL4 uses to run the components. This covers all the functionality available
698when using events. One final point that may not be obvious from the example is
699that callbacks will always be fired in preference to polling/waiting. That is,
700if a component registers a callback and then waits on an event to arrive, the
701callback will be fired when the first instance of the event arrives and the wait
702will return when/if the second instance of the event arrives.
703
704#### An Example of Dataports
705
706Dataports are CAmkES' abstraction of shared memory. All
707components participating in a connection involving dataports get read/write
708access to the dataport by default. The default dataport type is
709`Buf`, which is implemented as a byte array in C of size `PAGE_SIZE`.
710Alternatively you can specify a user-defined type for the shared memory region.
711This example will demonstrate both.
712
713Create two components that will use a pair of dataports for communication:
714
715```bash
716mkdir -p apps/hellodataport/components/Ping
717mkdir -p apps/hellodataport/components/Pong
718```
719
720Let's define a struct that will be used as one of the dataports:
721
722```c
723/* apps/hellodataport/include/porttype.h */
724
725#ifndef _PORTTYPE_H_
726#define _PORTTYPE_H_
727
728typedef struct MyData {
729  char data[10];
730  bool ready;
731} MyData_t;
732
733#endif
734```
735
736Now let's create an ADL description of the Ping component:
737
738```camkes
739/* apps/hellodataport/components/Ping/Ping.camkes */
740
741import "Porttype.idl4";
742
743component Ping {
744  include "porttype.h";
745  control;
746  dataport Buf d1;
747  dataport MyData_t d2;
748}
749```
750
751Note that we need to include the C header in the ADL. CAmkES does not actually
752parse this header, but it needs to know to `#include` it whenever it references
753the `MyData_t` type. Add a similar description for Pong:
754
755```camkes
756/* apps/hellodataport/components/Pong/Pong.camkes */
757
758import "Porttype.idl4";
759
760component Pong {
761  include "porttype.h";
762  control;
763  dataport Buf s1;
764  dataport MyData_t s2;
765}
766```
767
768Now we'll create some basic code for each component to use the dataports:
769
770```c
771/* apps/components/Ping/src/main.c */
772
773#include <camkes.h>
774#include <porttype.h>
775#include <stdio.h>
776#include <string.h>
777
778// index in d1 to use to signal pong
779#define D1_READY_IDX 20
780
781int run(void) {
782  char *hello = "hello";
783
784  printf("Ping: sending %s...\n", hello);
785  strncpy((char*)d1, hello, D1_READY_IDX - 1);
786
787  d1_release(); // ensure the assignment below occurs after the strcpy above
788  ((*char)d1)[D1_READY_IDX] = 1;
789
790  /* Wait for Pong to reply. We can assume d2_data is
791   * zeroed on startup by seL4.
792   */
793  while (!d2->ready) {
794    d2_acquire(); // ensure d2 is read from in each iteration
795  }
796
797  printf("Ping: received %s.\n", d2->data);
798
799  return 0;
800}
801```
802
803```c
804/* apps/components/Pong/src/main.c */
805
806#include <camkes.h>
807#include <porttype.h>
808#include <stdio.h>
809#include <string.h>
810
811// index in s1 to use to signal ping
812#define S1_READY_IDX 20
813
814int run(void) {
815  char *world = "world";
816
817  /* Wait for Ping to message us. We can assume s1_data is
818   * zeroed on startup by seL4.
819   */
820  while (!((char*)s1)[S1_READY_IDX]) {
821    s1_acquire(); // ensure s1 is read from in each iteration
822  }
823
824  printf("Pong: received %s\n", (char*)s1);
825
826  printf("Pong: sending %s...\n", world);
827  strcpy(s2->data, world);
828
829  s2_release(); // ensure the assignment below occurs after the strcpy above
830  s2->ready = true;
831
832  return 0;
833}
834```
835
836Note the use of `*_acquire()` and `*_release()` functions. These are used to maintain
837coherency of shared memory between components. Call `*_acquire()` between multiple
838reads from a dataport, where the correct behaviour of the program depends on the
839contents of the dataport possibly changing between reads. Call `*_release()` between
840multiple writes to a dataport, where the correct behaviour of the program depends
841on writes preceding the `*_release()` in the program code being performed strictly
842before the writes following it.
843
844Typically, a real system would have a more complete communication protocol between
845the two components, but for the purposes of this example spinning until a byte
846changes is good enough. We're ready to connect all these sources together with a
847top-level ADL file:
848
849```camkes
850/* apps/hellodataport/hellodataport.camkes */
851
852import <std_connector.camkes>;
853import "components/Ping/Ping.camkes";
854import "components/Pong/Pong.camkes";
855
856assembly {
857  composition {
858    component Ping ping;
859    component Pong pong;
860
861    connection seL4SharedData channel1(from ping.d1, to pong.s1);
862    connection seL4SharedData channel2(from ping.d2, to pong.s2);
863  }
864}
865```
866
867Add the now familiar `apps/hellodataport/CMakeLists.txt`:
868
869```cmake
870cmake_minimum_required(VERSION 3.7.2)
871
872project(hellodataport C)
873
874# Interface library for our dataport
875add_library(MyData INTERFACE)
876target_include_directories(MyData INTERFACE "${CMAKE_CURRENT_LIST_DIR}/include")
877
878DeclareCAmkESComponent(Ping SOURCES components/Ping/src/main.c LIBS MyData)
879DeclareCAmkESComponent(Pong SOURCES components/Pong/src/main.c LIBS MyData)
880
881DeclareCAmkESRootserver(hellodataport.camkes)
882
883```
884We added an interface library containing the shared header file. The LIBS field in DeclareCAmkESComponent can be
885used to specify any argument that can be ordinarily given to CMake's `target_link_libraries()`.
886
887If you now compile and run the resulting
888image you should see some output like the following:
889
890```
891Ping: sending hello...
892Pong: received hello
893Pong: sending world...
894Ping: received world.
895```
896#### An example of structs and arrays for collections
897
898A struct can be defined with the `struct` keyword.  The attributes that make
899up the struct are listed in a `type` `name` format (similar to C).
900
901Arrays are specified by appending the attribute name with a `[]`.  The size of
902an array is set at code generation time when the setting for the attribute is
903specified.
904
905This is an example of a valid camkes specification.  The corresponding C file
906is shown after.  To find a size of an attribute array, the sizeof macro can be
907used as shown in the example.
908
909```camkes
910struct client_config {
911    string name;
912    int age;
913    int height;
914}
915struct cat {
916    int b[];
917    int c;
918}
919
920component Client {
921    control;
922    attribute client_config config;
923    attribute cat array_in_struct;
924}
925
926assembly {
927    composition {
928        component Client client;
929    }
930
931    configuration {
932        client.config = {"name": "Zed","age": 39, "height": 34+4};
933        client.array_in_struct = {"b": [3,4,5,6], "c": 4};
934    }
935}
936
937```
938
939```c
940#include <camkes.h>
941#include <stdio.h>
942
943int run(void)
944{
945    printf("struct: %s: height plus age is %d\n", config.name, config.age + config.height);
946    printf("array_in_struct: array length: %d, first element %d\n", sizeof(array_in_struct.b) / sizeof(array_in_struct.b[0]), array_in_struct.b[0]);
947    return 0;
948}
949```
950
951#### Tutorial Summary
952
953You should now have a reasonably comprehensive understanding of the basic
954connector functionality available in CAmkES. The other apps in the CAmkES
955project repository provide some more diverse system examples.
956
957### Overview
958
959The various parts that comprise CAmkES can be used in several ways, including
960executing a standalone tool as an end user or importing a Python module to
961perform programmatic operations. These two uses are broken up into the sections
962below. [Command Line Arguments](#command-line-arguments) describes how to invoke
963standalone CAmkES functionality, and [Modules](#modules) describes how to import
964and use the various functional units. Importing CAmkES functionality as a module
965is strictly more powerful than running the command line tool, but usage
966is more complicated. Note that these sections only describe external
967interaction with these artefacts. If you are interested in the internals of
968these you will need to refer to the [Developers](#developers) section.
969
970### Command Line Arguments
971
972This section discusses the standalone tool that is part of the CAmkES
973ecosystem. This can be run from the command line with a shell script wrapper
974that checks its dependencies:
975
976```bash
977camkes.sh args...
978```
979
980The following command line arguments are available.
981
982**--cache**, **-c**
983**--cache-dir**
984
985> In a complicated system, the compilation itself can be quite time intensive.
986  CAmkES implements a template cache that reduces recompilation time within and
987  across builds. The --cache option enables it.
988
989**--cpp**
990**--nocpp**
991
992> Whether or not to run the C pre-processor over the ADL input specification
993  before processing it. The ADL input specification, strictly, is not C source
994  code, but sometimes it can be useful to have the ability to pre-process it as
995  if it was. The CAmkES ADL grammar is sufficiently similar to C that you are
996  unlikely to run into any problems in this respect.
997
998**-D**, **--debug**
999**-q**, **--quiet**
1000**-v**, **--verbose**
1001
1002> Set the level of information and error reporting emitted. The last one of
1003  these options encountered on the command line takes precedence. Note that
1004  there is no option to set the default verbosity (which is more than --quiet,
1005  but less than --verbose). The verbosity setting is applied globally during
1006  execution. For example, applying --debug to inspect a parsing problem in the
1007  runner will also generate debugging output from the lexing phase.
1008
1009**--default-priority**
1010
1011> Threads in a seL4 system are all configured with an initial priority. This
1012  can be tuned via attributes, but otherwise threads inherit a global default.
1013  This parameter allows you to set the global default.
1014
1015**--default-affinity**
1016
1017> Threads and sched-contexts in a seL4 system are all configured with an initial
1018  affinity. This can be tuned via attributes, but otherwise threads inherit a
1019  global default, which is CPU index 0.
1020
1021**--elf**, **-E**
1022
1023> Pass an ELF file that is to contribute to the final CapDL specification of a
1024  system. This parameter allows you to pass in the compiled ELF binary of one of
1025  your component instances. The CAmkES build system should take care of passing
1026  this option.
1027
1028**-f FILE**, **--file FILE**
1029
1030> This argument sets FILE as the input to parse. This argument is required and
1031  only a single input file is supported.
1032
1033**-h**, **--help**
1034
1035> Shows usage information and then exits.
1036
1037**-I PATH**, **--import-path**
1038
1039> CAmkES specifications can contain `import` statements that are either
1040  relative or builtin. Analogously to C pre-processor `#include` directives,
1041  builtin `import` statements use angle brackets, `import &lt;foo.camkes&gt;`.
1042  This option is similar to the C compiler flag, -I, and adds a directory to be
1043  searched for these builtin files. When resolving imports, directories will be
1044  searched in the order in which they are specified on the command line with
1045  the first match taking preference. Note, _unlike_ the C pre-processor this
1046  option _only_ affects searches for builtin imports. Relative imports are
1047  _always_ relative to the location they are included from.
1048
1049**--item**, **-T**
1050
1051> Specify the output you wish the runner to generate. The available options
1052  here are dependent on your input specification and it is best to look at
1053  examples to see what is expected following this option.
1054
1055**--largeframe**
1056
1057> Back large virtual address space regions with large frames when possible. On
1058  ARM and IA32 platforms, multiple frame sizes are supported for mapping
1059  physical memory into address spaces. It is more efficient to use a single
1060  large frame to cover a region than many small frames. This flag controls
1061  whether this promotion to large frames happens automatically. Note that this
1062  does not affect DMA pools, for which mappings are controlled by the
1063  --largeframe-dma option below.
1064
1065**--largeframe-dma**
1066
1067> Back components' DMA pools with large frames when possible. This works
1068  entirely independently to the --largeframe option. The reason for this
1069  separation is that large frame promotion of a DMA pool on ARM can be a
1070  little complicated to achieve. For more information, see
1071  [Efficient DMA](#efficient-dma).
1072
1073**--platform**, **-p**
1074
1075> The target output platform. This determines some aspects of the environment
1076  that the template being rendered is expected to function in. This option is
1077  only relevant to the runner. Valid platforms are "architecture-semantics",
1078  "autocorres", "CIMP", "GraphViz" and "seL4". The "GraphViz" option is for
1079  producing visual representations of a system and the "seL4" option is for
1080  producing binaries. All other platforms are verification frameworks.
1081
1082**--templates**, **-t**
1083
1084> You can use this option to add an extra directory to search for templates
1085  before the built-in location. This can allow you to extend the available
1086  templates or even override the built-in templates.
1087
1088**--version**
1089
1090> Print basic version information and then exit.
1091
1092The following options are all related to runtime optimisations within the
1093templates. Note that most of these are highly seL4 specific and would make no
1094sense in the context of another platform.
1095
1096**--frpc-lock-elision**
1097**--fno-rpc-lock-elision**
1098
1099> Locks are used within the seL4RPC connector templates to prevent threads
1100  interfering with each other's execution. When this option is enabled, CAmkES
1101  will determine when this lock is not required and remove it at compile-time.
1102
1103**--fcall-leave-reply-cap**
1104**--fno-call-leave-reply-cap**
1105
1106> The seL4RPCCall connector needs to save a so-called reply cap on the
1107  receiver's side to prevent accidental deletion in the presence of
1108  interference from other interfaces. In certain circumstances there is
1109  actually no risk of the reply cap being deleted. With this option enabled,
1110  CAmkES will detect these scenarios and operate on the reply cap in place to
1111  avoid extra syscalls.
1112
1113**--fspecialise-syscall-stubs**
1114**--fno-specialise-syscall-stubs**
1115
1116> In a system involving many small procedural interfaces which are individually
1117  providing so-called microservices, the overhead of seL4's syscall entry stubs
1118  becomes perceptible. In pathological cases they can even become a performance
1119  bottleneck. With this option enabled, CAmkES detects these small interfaces
1120  and emits a custom assembly syscall entry stub. Due to the extra knowledge of
1121  the execution environment that CAmkES has, these stubs can actually induce
1122  even lower overhead than optimal generalised stubs.
1123
1124The following options are all related to verification of templates outputs.
1125
1126**--fprovide-tcb-caps**
1127**--fno-provide-tcb-caps**
1128
1129> By default each thread gets a cap to its own TCB. The only purpose of this is
1130  to allow it to suspend itself when it exits. These TCBs can complicate
1131  reasoning about a generated CapDL specification. This option elides these TCB
1132  caps at the cost of threads messily VM faulting when they exit.
1133
1134### Modules
1135
1136Each subset of CAmkES functionality is encapsulated in a Python module that
1137defines exactly what functions and variables are exported. The APIs of these
1138are described below and usage should be reasonably straightforward. To import
1139any of these modules the top-level directory of this distribution should be in
1140your `PYTHONPATH` environment variable. The available modules are:
1141
1142**[camkes.ast](#camkes.ast)**
1143
1144> Definitions of objects that can appear in the result of parsing a CAmkES
1145  specification. If you want to reference the types of objects in a resulting
1146  AST you will need to import this.
1147
1148**camkes.internal**
1149
1150> Functionality used by other CAmkES modules. You should not import this
1151  module.
1152
1153**[camkes.parser](#camkes.parser)**
1154
1155> To parse an input specification in memory or to do post-processing
1156  manipulations on a specification-derived AST you will need to import this
1157  module. The [runner](#runner) imports this module to perform its job.
1158
1159**camkes.runner**
1160
1161> This module is available, but does not export any symbols. You should never
1162  need to import it.
1163
1164**[camkes.templates](#camkes.templates)**
1165
1166> If you need to lookup builtin templates you will need to import this module.
1167  Note that this module does not contain any template _instantiation_ logic.
1168
1169#### camkes.ast
1170
1171The result of parsing a CAmkES specification is an Abstract Syntax Tree (AST),
1172representing the input as a set of interconnected nodes. When using the default
1173parser, the object returned is of type, `LiftedAST`, which is defined in this
1174module. `LiftedAST` and its children all inherit from a base type, `ASTObject`,
1175that provides common functionality like traversal and comparison.
1176
1177One of the AST objects is a class, `Reference`. Objects of this class are used
1178in the AST to represent symbols that refer to entities that are defined
1179elsewhere. During parsing, references are removed from the AST as they are
1180resolved to the entities to which they refer. In particular, if you are using
1181the default parser, the returned AST will never contain any `Reference`
1182objects.
1183
1184In the code and in this document there is some discussion of 'collapsing' AST
1185references. This is meant to refer to replacing the `Reference` object in the
1186AST by the entity to which it refers. Note that this needs to be done by
1187reference so that you still only end up with a single copy of the entity, but
1188multiple pointers to it.
1189
1190If you are not using the default CAmkES parser, but are assembling your own
1191from the [parser module](#camkes.parser), it is important to note that objects
1192of the classes in the AST module are only created in the stage 3 parser. If you
1193are inspecting the output of any low-level parser prior to stage 3, you will
1194not see objects from camkes.ast.
1195
1196#### camkes.parser
1197
1198If you need to manipulate the AST, rather than just simply printing it
1199out, you will want to import the parser as a module into your own code. After
1200importing this module, you can interact with the parser through the following
1201high-level API.
1202
1203**`parse_file(filename, options=None)`**
1204
1205> Parse a file into a `LiftedAST`. The `options` arguments is expected to be a
1206  namespace as constructed by the runner. If you have non-standard parsing
1207  requirements, you may find this function is insufficiently flexible for your
1208  needs. In this case, you will need to compose the low-level parsers. You can
1209  see a rough guide of how to do this in camkes/parser/parser.py.
1210
1211**`parse_string(string, options=None)`**
1212
1213> Parse a string into a `LiftedAST`. This function works identically to the
1214  previous in all respects, except obviously you will not have accurate
1215  filename information.
1216
1217#### camkes.templates
1218
1219This module contains functionality for looking up builtin templates. The
1220templates themselves are actually stored in this directory (camkes/templates)
1221as well to reduce confusion. The description below only describes the externally
1222facing behaviour of this module. If you need to understand how template lookups
1223actually work you will need to read the source code and comments.
1224
1225The API only contains a single class through which all access is intended to
1226flow.
1227
1228`Templates.`**`__init__(self, platform)`**
1229
1230> Create a new template store in which templates can later be looked up. The
1231  category of templates that are available from this store is specialised via
1232  **`platform`**. At time of writing the valid values of **`platform`** are
1233  'seL4', 'CIMP' and 'GraphViz'.
1234
1235`Templates.`**`add_root(self, root)`**
1236
1237> Add a directory to be searched for templates when performing lookups. This
1238  directory is added _before_ existing directories, which allows you to
1239  overwrite builtin templates if you wish.
1240
1241`Templates.`**`get_roots(self)`**
1242
1243> Return the list of directories that are searched for templates. Note that if
1244  you are the only client operating on this `Templates` object you will know
1245  the contents of this list anyway, but this function is provided for
1246  convenience.
1247
1248`Templates.`**`add(self, connector_name, path, template)`**
1249
1250> Add a template to the lookup dictionary, such that it can later be returned
1251  in a template lookup. Only connector templates can be added currently (i.e.
1252  component templates and top-level templates cannot be added). The caller
1253  provides the **`connector_name`** this template applies to (e.g.
1254  'seL4MyConnector'), a partial lookup **`path`** to the template (e.g.
1255  'from.source') and a roots-relative path to the **`template`** itself. Again,
1256  this function is sufficiently complicated that it may be easier to comprehend
1257  its usage from reading `camkes/runner/__main__.py`.
1258
1259`Templates.`**`lookup(self, path, entity=None)`**
1260
1261> Locate and return a template. The **`path`** provided should be a full lookup
1262  path from the second-level of the lookup dictionary (i.e. not including the
1263  platform prefix). For example, a valid **`path`** might be
1264  'seL4RPCCall.from.source'. If you provide an **`entity`** this is used as a guard
1265  on the lookup. The guards come into play when looking up connector templates.
1266  In this situation the connector type of the connection you pass in as
1267  **`entity`** will be used to determine if a given template matches your
1268  lookup. This function returns `None` if a matching template can't be found.
1269
1270### Runtime API
1271
1272This section describes the environment in which you, as a user, will find
1273yourself writing code. Standard C library functionality is available, but as a
1274CAmkES application, there is also extra functionality provided by generated
1275code and supporting libraries. This extra functionality is what is documented
1276in this section.
1277
1278Parts of the functionality discussed below are provided by the library,
1279libsel4camkes. In a typical seL4 project the user would need to specify that
1280they want to link against this library. This is not required in CAmkES as it is
1281assumed you always want to link against this library. For more information from
1282a CAmkES developer's point of view, see [Core Libraries](#core-libraries). The
1283API is bidirectional in a sense, in that some of the functions below are called
1284by CAmkES code and expected to be provided by the user. This is noted in their
1285descriptions.
1286
1287The following types are available at runtime from the C context of a component:
1288
1289**`Buf`** (`#include <camkes/dataport.h>`)
1290
1291> The underlying type of a dataport. A user is never expected to instantiate
1292  one of these manually, but they are free to do so if they wish.
1293
1294**`camkes_error_handler_t`** (`#include <camkes/error.h>`)
1295> The type of an error handler for dealing with errors originating in glue
1296  code. For more information about this see
1297  [Error Handling](#error-handling).
1298
1299**`camkes_tls_t`** (`#include <camkes/tls.h>`)
1300
1301> Thread-local storage metadata. This captures some necessary information for
1302  constructing a thread context inside templates. A user is never expected to
1303  instantiate or deal with one of these, but they are free to do so if they
1304  wish.
1305
1306**`dataport_ptr_t`** (`#include <camkes/dataport.h>`)
1307
1308> A component-independent representation of a pointer into a dataport. This is
1309  intended to be an opaque type to the user that is only ever used via the
1310  `dataport_wrap_ptr` and `dataport_unwrap_ptr` functions.
1311
1312The following variables are available:
1313
1314**_`dataport`_** (`#include <camkes.h>`)
1315
1316> If a component has a dataport they will be provided with a symbol of the
1317  dataport's name that is a pointer of the type they specified in their CAmkES
1318  specification. As mentioned previously, the default type is `Buf`.
1319
1320The following functions are available at runtime:
1321
1322**`camkes_error_handler_t camkes_register_error_handler(camkes_error_handler_t handler)`** (`#include <camkes/error.h>`)
1323**`camkes_error_handler_t `&nbsp;_`interface`_`_register_error_handler(camkes_error_handler_t handler)`** (`#include <camkes/error.h>`)
1324
1325> Register a component-wide or interface-specific error handler, respectively.
1326  These functions return the previous error handler or `NULL` if there was no
1327  previously installed error handler. For more information see
1328  [Error Handling](#error-handling).
1329
1330**`dataport_ptr_t dataport_wrap_ptr(void *ptr)`** (`#include <camkes/dataport.h>`)
1331**`void *dataport_unwrap_ptr(dataport_ptr_t ptr)`** (`#include <camkes/dataport.h>`)
1332
1333> Utility functions for creating and destroying a component-independent
1334  representation of a pointer into a dataport. This `dataport_ptr_t` can be
1335  passed over a procedure interface to be unwrapped by the receiving component.
1336  Unwrapping will fail if the underlying pointer is not into a dataport that is
1337  shared with the receiver. `dataport_unwrap_ptr` returns `NULL` on failure.
1338
1339**`void`&nbsp;_`dataport`_`_acquire(void)`**
1340
1341> An acquire memory fence. Any read from the dataport preceding this fence in
1342  program order will take place before any read or write following this fence in
1343  program order. In uniprocessor environments, this is always a compiler memory
1344  fence. In multiprocessor environments, memory barrier instructions will be
1345  emitted if necessary, depending on the affinities of component instances
1346  connected by the dataport.
1347
1348**`void`&nbsp;_`dataport`_`_release(void)`**
1349
1350> A release memory fence. Any write to the dataport following this fence in
1351  program order will take place after any read or write preceding this fence in
1352  program order. In uniprocessor environments, this is always a compiler memory
1353  fence. In multiprocessor environments, memory barrier instructions will be
1354  emitted if necessary, depending on the affinities of component instances
1355  connected by the dataport.
1356
1357**`void *camkes_dma_alloc(size_t size, int align)`** (`#include <camkes/dma.h>`)
1358**`void camkes_dma_free(void *ptr, size_t size)`** (`#include <camkes/dma.h>`)
1359
1360> Allocator for DMA device operations. These are closely linked with the DMA
1361  pool functionality, as the allocation is backed by this pool.
1362
1363**`uintptr_t camkes_dma_get_paddr(void *ptr)`** (`#include <camkes/dma.h>`)
1364
1365> Translate a pointer into a DMA region into a physical address. This function
1366  assumes that the pointer you are passing in is to a byte within a region
1367  allocated to you by `camkes_dma_alloc_page`. The reason for needing to obtain
1368  the physical address of a pointer is typically to pass to a device that is
1369  going to access this region outside of the scope of the MMU. For more
1370  information, see the [DMA](#direct-memory-access) section below.
1371
1372**`void *camkes_io_map(void *cookie, uintptr_t paddr, size_t size, int cached, ps_mem_flags_t flags)`** (`#include <camkes/io.h>`)
1373
1374> Lookup the translation to virtual address from the physical address of a
1375  memory-mapped IO device. This function is primarily to ease interaction with
1376  libplatsupport infrastructure, so refer to its documentation where
1377  appropriate.
1378
1379**`int camkes_io_mapper(ps_io_mapper_t *mapper)`** (`#include <camkes/io.h>`)
1380
1381> Construct an IO mapping structure to pass to libplatsupport. See source
1382  comments for more information about how to use this.
1383
1384**`int camkes_io_ops(ps_io_ops_t *ops)`** (`#include <camkes/io.h>`)
1385
1386> Construct an IO operations structure to pass to libplatsupport. See source
1387  comments for more information about how to use this.
1388
1389**`int camkes_io_port_in(void *cookie, uint32_t port, int io_size, uint32_t *result)`** (`#include <camkes/io.h>`)
1390**`int camkes_io_port_out(void *cookie, uint32_t port, int io_size, uint32_t val)`** (`#include <camkes/io.h>`)
1391
1392> Read from or write to a hardware IO port. This function is primarily to ease
1393  interaction with libplatsupport infrastructure, so refer to its documentation
1394  where appropriate.
1395
1396**`int camkes_io_port_ops(ps_io_port_ops_t *ops)`** (`#include <camkes/io.h>`)
1397
1398> Construct an IO port access structure to pass to libplatsupport. See source
1399  comments for more information about how to use this.
1400
1401**`const char *get_instance_name(void)`** (`#include <camkes.h>`)
1402
1403> Returns the name of this component instance. This can be helpful if you want
1404  to write component functionality that has different behaviour depending on
1405  which instance it is.
1406
1407**`int`&nbsp;_`instance`_`_main(int thread_id)`**
1408
1409> A component instance's entry point. This is generated by the platform and
1410  invokes the user's `run` function when complete.
1411
1412**`int main(int thread_id)`** (in libsel4camkes.a)
1413
1414> This function &mdash; the C entry point to a component &mdash; is provided by
1415  the platform. Components should not provide their own `main`.
1416
1417**`int run(void)`**
1418
1419> This function is expected to be provided by the user in a control component.
1420  It is invoked by `main` after component initialisation is complete.
1421
1422**`NORETURN _start(int thread_id)`** (in libsel4camkes.a)
1423
1424> This function provides the assembly entry point of a component and consists
1425  of a brief trampoline to `main`. The user can override this if they wish, but
1426  it is unwise to do this unless you have a deep understanding of the runtime
1427  environment.
1428
1429**`void pre_init(void)`**
1430
1431> This function can be optionally provided by the user. If it is present, it
1432  will be invoked _before_ the component's interfaces' init functions have
1433  executed. Be aware that you will not have full runtime support in this
1434  function. For example, interfaces cannot be expected to be accessible.
1435
1436**`void`&nbsp;_`interface`_`__init(void)`**
1437
1438> For each incoming or outgoing interface a user can optionally provide this
1439  function. If it is present it will be invoked _after_ the component's
1440  pre-init function, but _before_ its post-init function. The same caveats about
1441  the runtime environment from above are applicable here.
1442
1443**`void post_init(void)`**
1444
1445> This function can be optionally provided by the user. If it is present, it
1446  will be invoked _after_ the component's pre-init function and after all
1447  interfaces' init functions, but _before_ any interface enters its run
1448  function.
1449
1450**`int`&nbsp;_`interface`_`__run(void)`**
1451
1452> This function can be provided for any incoming or outgoing interface. If it
1453  is present, it will be invoked after all pre- and post-init functions have
1454  run.
1455
1456**_`return`_&nbsp;_`procedure`_`_`_`method`_`(`_`args...`_`)`** (`#include <camkes.h>`)
1457
1458> In a component that provides a procedure interface, things are somewhat
1459  reversed and the implementation calls functions that you are expected to
1460  provide. For each method in the procedure you are expected to provide a
1461  matching implementation. In a component that uses a procedure interface,
1462  functions of this form are available for you to call.
1463
1464**`void`&nbsp;_`event`_`_emit(void)`** (`#include <camkes.h>`)
1465
1466> In a component that emits an event a function prefixed with the event's name
1467  is available that causes the event to be sent.
1468
1469**`void`&nbsp;_`event`_`_poll(void)`** (`#include <camkes.h>`)
1470
1471> In a component that consumes an event a function prefixed with the event's
1472  name is available that returns whether there is a pending event. Note, this
1473  function never blocks.
1474
1475**`int`&nbsp;_`event`_`_reg_callback(void (*callback)(void*), void *arg)`** (`#include <camkes.h>`)
1476
1477> In a component that consumes an event a function prefixed with the event's
1478  name is available for registering a callback for this event. When the event
1479  is received, the provided function will be invoked with the argument provided
1480  when registering the callback. Note that registered
1481  callbacks take precedence over threads blocked on calls to _`event`_`_wait`.
1482  _`event`_`_reg_callback` returns 0 on success and non-zero if the callback
1483  could not be registered.
1484
1485**`void`&nbsp;_`event`_`_wait(void)`** (`#include <camkes.h>`)
1486
1487> In a component that consumes an event a function prefixed with the event's
1488  name is available that blocks until the event is received.
1489
1490### Synchronization Primitives
1491
1492CAmkES provides three primitives for intra-component mutual exclusion and synchronization.
1493Mutexes, semaphores, and binary semaphores are declared similarly to properties of a component definition:
1494
1495```camkes
1496component Foo {
1497  has mutex m;
1498  has semaphore s;
1499  has binary_semaphore b;
1500}
1501```
1502
1503By default semaphores have a count (initial value) of 1, and binary semaphores have an initial value
1504of 0. This can be adjusted using an attribute:
1505
1506```camkes
1507assembly {
1508  composition {
1509    component Foo f;
1510    ...
1511  }
1512  configuration {
1513    f.s_value = 4;
1514    f.b_value = 1; // must be either 0 or 1
1515    ...
1516  }
1517}
1518```
1519
1520An application can lock or unlock a declared mutex and call post or wait on a
1521declared semaphore or binary semaphore. For example, for the above declarations, the following
1522functions are available at runtime:
1523
1524```c
1525/* Lock mutex m */
1526int m_lock(void);
1527
1528/* Unlock mutex m */
1529int m_unlock(void);
1530
1531/* Wait on semaphore s */
1532int s_wait(void);
1533
1534/* Try to wait on semaphore s */
1535int s_trywait(void);
1536
1537/* Post to semaphore s */
1538int s_post(void);
1539
1540/* Wait on a binary semaphore b */
1541int b_wait(void);
1542
1543/* Post to a binary semaphore b */
1544int b_post(void);
1545```
1546
1547The CAmkES mutexes and semaphores have the behaviour you would expect from an
1548seL4 or pthreads implementation.
1549
1550There is no native support for inter-component locks. However, it is possible
1551to construct these on top of the CAmkES platform. An example of how you would
1552do this is shown in the lockserver example application in the CAmkES project
1553repository.
1554
1555### Direct Memory Access
1556
1557Direct Memory Access (DMA) is a hardware feature that allows devices to read
1558and write memory without going via the CPU. It is intended to give a fast I/O
1559path to devices, for which memory access is usually the bottleneck.
1560
1561This only has specific relevance in the context of CAmkES because on platforms
1562without an [IOMMU](https://en.wikipedia.org/wiki/IOMMU) devices perform DMA
1563accesses on physical memory, rather than virtual memory. The implications of
1564this are that, when a device is being directed to perform I/O by a driver, it
1565needs to know the physical address(es) of the memory it is about to access. On
1566seL4 reversing a virtual memory mapping requires specific capability operations
1567and thus CAmkES needs to be aware of any memory region which you intend to use
1568for DMA transfers.
1569
1570To allocate some memory for DMA within a specific component instance you
1571describe a DMA pool with a size in bytes. For example,
1572
1573```camkes
1574assembly {
1575  composition {
1576    component Foo f;
1577    ...
1578  }
1579  configuration {
1580    f.dma_pool = 8192;
1581  }
1582}
1583```
1584
1585This declares an 8KB pool of memory that is available for DMA operations.
1586Within the component you must allocate and release pointers into this region
1587with the `camkes_dma_alloc` and `camkes_dma_free` functions described above.
1588The allocation function accepts a size and alignment constraint, but be aware
1589that allocation may not be efficient or guaranteed when requesting more than
15904Kb. Note that if you declare a DMA pool that is not page-aligned (4K on the
1591platforms we support) it will automatically be rounded up.
1592
1593#### Efficient DMA
1594
1595For components that need to perform large DMA operations, you will need to
1596allocate a large DMA pool. Backing the virtual address space mappings for such
1597a pool with 4KB frames can lead to performance issues. For this reason, you may
1598wish to use the command line option --largeframe-dma to back DMA pools with
1599large frames.
1600
1601This is relatively straightforward on IA32, but on an ARM platform you may run
1602into a limitation of the GNU Assembler that prevents the large alignments
1603required by the DMA pool. Support for working around this is provided by the
1604CAmkES build system, but is a little complicated, so the precise steps for
1605achieving this in a CAmkES project are documented below.
1606
1607Enable large frame promotion for the DMA pool in your build configuration:
1608
1609```bash
1610cmake . -DCAmkESDMALargeFramePromotion=ON
1611```
1612
1613On older versions of binutils, if you were using a large enough DMA pool
1614to get promoted to large frames with an alignment constraint that was rejected
1615by the GNU Assembler, you should see output like the following:
1616
1617```
1618/tmp/ccfGhK5Z.s: Assembler messages:
1619/tmp/ccfGhK5Z.s:1483: Error: alignment too large: 15 assumed
1620```
1621Updating binutils should fix this issue.
1622
1623### Error Handling
1624
1625Some runtime conditions can lead to an error in the glue code. For example, if
1626an interface accepts a string parameter and the caller passes a string that is
1627too large to fit in the IPC buffer. Errors can also arise in glue code if your
1628user code is not well-behaved and attempts to operate directly on capabilities.
1629The glue code attempts to handle all errors occurring from user mistakes and
1630malicious user code, to the best of its abilities. It also attempts to handle
1631errors that occur as a result of unexpected runtime conditions. For example,
1632accesses to a device that unexpectedly is not found at runtime.
1633
1634The mode of error handling can be configured at compile-time, but the default
1635mode is generally the only relevant one you will need. It allows for runtime
1636handling of errors. By default, all errors cause a diagnostic message and a
1637system halt on a debug kernel. To alter this behaviour, user code can call the
1638function `camkes_register_error_handler` (described in
1639[Runtime API](#runtime-api)) and provide their own error handling function.
1640The user's error handling will thenceforth be invoked by glue code whenever an
1641error is detected. The error handling function should return one of the
1642following values, documented further in `camkes/error.h`, that indicate to the
1643glue code how it should proceed:
1644
1645* `CEA_DISCARD` ��� Ignore whatever message or request was currently being
1646  handled and return to the original calling function of the user or an event
1647  loop as appropriate. This is typically the failure mode you want for servers
1648  that are intended to be robust against denial-of-service attacks from
1649  malicious clients.
1650
1651* `CEA_IGNORE` ��� Pretend the error was not detected and continue executing.
1652  This is almost never the response you want to take, but it can be useful for
1653  debugging or masking spurious errors.
1654
1655* `CEA_ABORT` ��� Terminate the current thread with failure status. This is a
1656  fail-stop response, though note it will not halt the rest of the system. If
1657  the glue code is currently handling a request on behalf of a client, the
1658  client will likely end up stuck blocked waiting for a response.
1659
1660* `CEA_HALT` ��� Halt the entire system. This is only possible on a debug
1661  kernel. On a release kernel it will act identically to `CEA_ABORT`.
1662
1663To conditionally determine which response to return, the error handler is
1664passed a structure that describes the error that was detected. For details on
1665this structure, refer to `camkes/error.h`.
1666
1667The mechanism just described allows for handling errors at a component-wide
1668level. In a more complicated component, there are often notional subsystems
1669that want to be able to handle their own errors independently. For this there
1670are interface-specific error handlers. Each interface has its own error handler
1671registration function as _`interface`_`_register_error_handler`. Any interface that
1672does not have a registered interface-specific error handler will default to the
1673component-wide error handler.
1674
1675### Custom Attributes
1676
1677CAmkES allows the programmer to define arbitrary attributes of components.
1678
1679```camkes
1680component Foo {
1681  attribute string a;
1682  attribute int b;
1683}
1684```
1685
1686These attributes are set in the configuration section of the assembly:
1687
1688```camkes
1689assembly {
1690  composition {
1691    component Foo f;
1692    ...
1693  }
1694  configuration {
1695    f.a = "Hello, World!";
1696    f.b = 42;
1697    ...
1698  }
1699}
1700```
1701
1702This results in the specified values being available as global variables
1703in the glue code with the same name as the attribute.
1704
1705```c
1706const char * a = "Hello, World!";
1707const int b = 42;
1708```
1709
1710### Hardware Components
1711
1712A hardware component represents an interface to hardware in the form of a component.
1713Declaring a component with the `hardware` keyword creates a hardware component.
1714
1715```camkes
1716component Device {
1717  hardware;
1718
1719  provides IOPort io_port;
1720  emits Interrupt irq;
1721  dataport Buf mem;
1722}
1723```
1724
1725When an interface of a device component instance is connected to a regular
1726component, that component gets access to that device via some
1727hardware interface (interface here refers to a means of interacting with
1728hardware - not a CAmkES interface).
1729The type of hardware interface depends on the type of CAmkES interface,
1730and the connector used. Available connectors for hardware, and their
1731corresponding hardware interfaces are listed below.
1732
1733**Interface:** procedure            \
1734**Keyword:** `provides`               \
1735**Connector:** `seL4HardwareIOPort`   \
1736**Description:**
1737When using `IOPort` as the interface type, this provides access to IO ports. The connected
1738component gets access to the methods in the `IOPort` interface, which allow sending and receiving
1739data over IO ports. This is specific to the IA32 architecture.
1740
1741**Interface:** event                    \
1742**Keyword:** `emits`                      \
1743**Connector:** `seL4HardwareInterrupt`    \
1744**Description:**
1745An event is emitted when an interrupt occurs.
1746
1747**Interface:** port                 \
1748**Keyword:** `dataport`              \
1749**Connector:** `seL4HardwareMMIO`     \
1750**Description:**
1751Memory mapped registers can be accessed via the shared memory.
1752
1753The following shows an example of connecting a hardware component to a driver
1754component. Note the order of arguments to the connection. `seL4HardwareInterrupt` requires
1755the hardware interface on the `from` side of the connection, whereas the other connectors
1756require the hardware interface on the `to` side.
1757
1758```camkes
1759component Driver {
1760  uses IOPort io_port;
1761  consumes Interrupt irq;
1762  dataport Buf mem;
1763}
1764
1765assembly {
1766  composition {
1767    component Device dev;
1768    component Driver drv;
1769    ...
1770    connection seL4HardwareIOPort ioport_c(from drv.io_port, to dev.io_port);
1771    connection seL4HardwareInterrupt irq_c(from dev.irq, to drv.irq);
1772    connection seL4HardwareMMIO mmio_c(from drv.mem, to dev.mem);
1773  }
1774}
1775```
1776
1777#### Configuration
1778
1779Each type of hardware component interface has some configuration required for it
1780to work. This is done by setting attributes of instances of device components.
1781
1782##### MMIO
1783
1784The physical address of the memory, and size (in bytes) to make available
1785to a connected component must be specified. The example below specifies that
1786the port named `mem` of the component instance `d` is a 0x1000 byte region
1787starting at physical address 0xE0000000.
1788
1789```camkes
1790component Device {
1791  hardware;
1792
1793  dataport Buf mem;
1794  ...
1795}
1796
1797assembly {
1798  composition {
1799    component Device d;
1800    ...
1801  }
1802  configuration {
1803    d.mem_paddr = 0xE0000000;
1804    d.mem_size = 0x1000;
1805    ...
1806  }
1807}
1808```
1809
1810##### Interrupts
1811
1812Depending on the platform different information needs to specified to
1813connect a hardware interrupt source with a components interrupt handler.
1814
1815On ARM and if you are using the legacy x86 PIC controller then simply an
1816interrupt number must be specified. The example below specifies that
1817the event will be emitted when interrupt number 2 is received.
1818
1819```camkes
1820component Device {
1821  hardware;
1822
1823  emits Interrupt irq;
1824  ...
1825}
1826
1827assembly {
1828  composition {
1829    component Device d;
1830    ...
1831  }
1832  configuration {
1833    d.irq_irq_number = 2;
1834    ...
1835  }
1836}
1837```
1838
1839If using the newer I/O APIC controller on x86 then you need to describe
1840the I/O APIC source and provide a destination vector. An I/O APIC source
1841is described in terms of
1842
1843* Physical I/O APIC controller indexed starting at 0. Typically a system
1844  only has one of these
1845* Pin, ranging from 0 to 23, on the I/O APIC controller that the interrupt
1846  will come in on
1847* The trigger mode and polarity of the interrupt
1848
1849The destination vector is a number in the range of 0 to 107 and must be unique
1850across all destination vectors defined in an assembly.
1851
1852Selecting between edge and level trigger modes is done by setting the
1853`*_irq_ioapic_level` attribute where a value of `1` means level triggered and
1854`0` means edge triggered. Similarly the active polarity is configured by
1855the `*_irq_ioapic_polarity` attribute where a value of `1` means active
1856low and `0` means active high.
1857
1858To change the previous example to connect an interrupt on I/O APIC 0, pin 2
1859that is edge triggered with active high polarity you would change
1860
1861```camkes
1862d.irq_irq_number = 2;
1863```
1864
1865To become
1866
1867```camkes
1868d.irq_irq_type = "ioapic";
1869d.irq_irq_ioapic = 0;
1870d.irq_irq_ioapic_pin = 2;
1871d.irq_irq_ioapic_polarity = 0;
1872d.irq_irq_ioapic_level = 0;
1873d.irq_irq_vector = 42;
1874```
1875
1876With the `vector` being arbitrarily chosen as `42`
1877
1878An interrupt that is edge triggered and active high can be more concisely
1879declared as an ISA interrupt by
1880
1881```camkes
1882d.irq_irq_type = "isa";
1883d.irq_irq_ioapic = 0;
1884d.irq_irq_ioapic_pin = 2;
1885d.irq_irq_vector = 42;
1886```
1887
1888Similarly if this interrupt were to be level triggered and active low it
1889could be declared as a PCI interrupt by
1890
1891```camkes
1892d.irq_irq_type = "pci";
1893d.irq_irq_ioapic = 0;
1894d.irq_irq_ioapic_pin = 2;
1895d.irq_irq_vector = 42;
1896```
1897
1898##### IO Ports
1899
1900The allowable range of IO Ports must be specified.
1901The example below specifies that the hardware component instance
1902`d` may access IO ports greater than or equal to 0x60, and less
1903than 0x64.
1904
1905```camkes
1906component Device {
1907  hardware;
1908
1909  provides IOPort io_port;
1910  ...
1911}
1912
1913assembly {
1914  composition {
1915    component Device d;
1916    ...
1917  }
1918  configuration {
1919    d.io_port_attributes = "0x60:0x64";
1920    ...
1921  }
1922}
1923```
1924
1925### Port Privileges
1926
1927CAmkES allows the programmer to specify access rights that instances have over
1928the ports connecting them to other instances. This is done by setting the
1929`*_access` attribute of the port. The value of the attribute must be a string
1930containing the letters "R", "W" and "X", giving the port read, write and execute
1931privileges, respectively. If left unspecified, full access will be given.
1932
1933In the example below, instance `f` has read-only access to `port_a`, and
1934instance `b` has read/write access to `port_a`. Instance `b` has read-only
1935access to `port_b`. Instance `a` has read/write/execute access to `port_b` even
1936though it's not explicitly stated, as this is the default.
1937
1938```camkes
1939component Foo {
1940  dataport Buf data_a;
1941  dataport Buf data_b;
1942}
1943
1944component Bar {
1945  dataport Buf data_a;
1946  dataport Buf data_b;
1947}
1948
1949assembly {
1950  composition {
1951    component Foo f;
1952    component Bar b;
1953    ...
1954    connection seL4SharedData port_a(from f.data_a, to b.data_a);
1955    connection seL4SharedData port_b(from f.data_b, to b.data_b);
1956    ...
1957  }
1958  configuration {
1959    f.data_a_access = "R";
1960    b.data_a_access = "RW;
1961    f.data_b_access = "R";
1962    ...
1963  }
1964}
1965```
1966
1967### Thread Model
1968
1969CAmkES components are typically multithreaded and, to prevent race conditions,
1970it is often necessary to understand what threads exist in your system.
1971
1972Firstly there is a single active thread. This is the thread of control that
1973calls the component's entry point for components declared `control`. This
1974thread is present even in non-control components in order to perform
1975initialisation actions.
1976
1977Each interface your component interacts with, either as an incoming or outgoing
1978interface, induces another thread within the component. Initial synchronisation
1979of these threads and their various setup activities is all handled by generated
1980code. Note that this per-interface thread is present even for interfaces that
1981you may think of as passive. For example, dataports. This is merely an
1982implementation artefact and may change in future.
1983
1984One thing that may not be intuitive for users is that you have no guarantee as
1985to which thread will invoke an event callback. If you have registered a
1986callback for an event you are receiving, you should not assume that any
1987thread-local state persists between invocations. This is because the thread
1988which invokes a callback may not be the same thread as was used last time the
1989callback was invoked.
1990
1991### Thread Priorities
1992
1993Each thread in a CAmkES system has a priority that determines how it is
1994scheduled by seL4. These priorities default to a value given by the
1995`--default-priority` command-line argument to the runner. In a given system, it
1996it possible to adjust the priority of a specific thread with an attribute that
1997has specific semantics. To adjust the priority of the control thread (the
1998thread that calls `run`), use the `_priority` attribute:
1999
2000```camkes
2001assembly {
2002  composition {
2003    component Foo f;
2004    ...
2005  }
2006  configuration {
2007    f._priority = 100;
2008  }
2009}
2010```
2011
2012To adjust the priority of an interface thread, use an attribute named with the
2013name of the interface and the suffix ``_priority'':
2014
2015```camkes
2016component Foo {
2017  uses MyInterface i;
2018}
2019
2020assembly {
2021  composition {
2022    component Foo f;
2023    ...
2024  }
2025  configuration {
2026    f.i_priority = 100;
2027  }
2028}
2029```
2030
2031If you want to adjust the priority of every thread within a given component
2032instance, you can use a general component attribute:
2033
2034```camkes
2035configuration {
2036  f.priority = 100;
2037}
2038```
2039
2040For more information about the specifics of the seL4 scheduler, please refer to
2041the seL4 documentation.
2042
2043### Thread CPU affinity
2044
2045Each thread in a CAmkES system also has a processor affinity. This affinity will
2046by default bind all threads to CPU index 0, bootstrap-processor. In a system
2047where seL4 is built without multicore, setting this value above 0 is illegal.
2048
2049```camkes
2050component Mycomponent {
2051    /* ... */
2052    uses Myinterface i;
2053}
2054
2055assembly {
2056    composition {
2057        component Mycomponent c;
2058    }
2059    configuration {
2060        /* Run all threads in "c" on CPU 1 */
2061        c.affinity = 1;
2062    }
2063}
2064```
2065
2066Alternatively:
2067
2068```camkes
2069configuration {
2070    /* Run only the control thread on CPU 1, but run the rest of the threads
2071     * in this component on the "default" CPU (index 0).
2072     */
2073    c._affinity = 1;
2074}
2075```
2076
2077Or perhaps:
2078
2079```camkes
2080configuration {
2081    /* Run only the interface thread for "i" on CPU 1, but run the rest of the
2082     * threads in this component on the "default" CPU (index 0).
2083     */
2084    c.i_affinity = 1;
2085}
2086```
2087
2088### Thread Stacks
2089
2090Each CAmkES thread has a stack provided for it for use at runtime, as is
2091typical. Stack size defaults to 4K, but this default can be adjusted through
2092the relevant build system configuration option. Additionally the stacks of
2093individual threads within a component can be set with attributes:
2094
2095```camkes
2096configuration {
2097
2098  // Assign foo's control thread an 8K stack
2099  foo._stack_size = 8192;
2100
2101  // Assign the interface thread for inf in foo a 16K stack
2102  foo.inf_stack_size = 16384;
2103
2104}
2105```
2106
2107Note that stacks must have a size that is 4K aligned, so if you assign a thread
2108a stack size that is not 4K aligned it will be rounded up. Stacks have a 4K
2109unmapped "guard page" either side of them. This is a debugging aid to force a
2110virtual memory fault when threads underrun or overrun their stacks.
2111
2112### Scheduling Domains
2113
2114In CAmkES, it is possible to specify the domain each thread belongs to, by setting attributes.
2115Each interface of each component instance will have an associated thread, and
2116there will be an additional thread per-component to perform initialisation and
2117optionally act as the control thread. For interface threads, their domain can be
2118specified by setting the attribute `<interface>_domain` of the instance. For
2119control threads, the attribute `_domain` of the instance can be set.
2120
2121```camkes
2122component Foo {
2123  control;
2124  uses iface i;
2125}
2126
2127component Bar {
2128  provides iface o;
2129}
2130
2131assembly {
2132  composition {
2133    component Foo f;
2134    component Bar b;
2135    connection seL4RPCCall c(from f.i, to b.o);
2136    ...
2137  }
2138  configuration {
2139    f._domain = 0;  // domain of control thread of f
2140    b.o_domain = 1; // domain of o interface of b
2141    ...
2142  }
2143}
2144```
2145
2146### Userspace RPC Transfer Buffers
2147
2148By default, the majority of RPC connectors exchange data through a
2149kernel-managed IPC buffer. RPC communication involving longer messages can be
2150optimised by exchanging data through userspace buffers instead of the IPC
2151buffer. To achieve this, set up an `seL4SharedData` connection and assign a
2152custom attribute:
2153
2154```camkes
2155component Foo {
2156  uses iface i;
2157  dataport Buf d;
2158}
2159
2160component Bar {
2161  provides iface j;
2162  dataport Buf e;
2163}
2164
2165assembly {
2166  composition {
2167    component Foo foo;
2168    component Bar bar;
2169
2170    connection seL4RPCCall conn(from foo.i, to bar.j);
2171    connection seL4SharedData ubuf(from foo.d, to bar.e);
2172  }
2173  configuration {
2174    conn.buffer = "ubuf";
2175  }
2176}
2177```
2178
2179There are a few limitations to be aware of when using this technique. The only
2180RPC connector that supports this style of userspace communication at time of
2181writing is `seL4RPCCall`. The RPC connection must be 1-to-1 and the
2182`seL4SharedData` connection must connect the same two component instances. The
2183size of the buffer (determined by the dataports' type) is flexible, but if you
2184use a buffer that is too small to accommodate RPC data you will trigger runtime
2185errors during parameter marshalling.
2186
2187### Multi-Assembly Applications
2188
2189CAmkES allows programmers to define an arbitrary number of assemblies for their application.
2190Different assemblies may appear in different files, provided that they are appropriately
2191included in the main ADL file. At compile time, the bodies of each
2192assembly are merged together, with all declared names remaining the same.
2193Thus, naming conflicts can occur on items declared in different assemblies.
2194
2195```camkes
2196assembly {
2197  composition {
2198    component Foo f;
2199  }
2200}
2201
2202assembly {
2203  composition {
2204    component Bar b;
2205    connection seL4RPCCall c(from f.a, to b.a);
2206  }
2207  configuration {
2208    f.some_attribute = 0;
2209  }
2210}
2211```
2212
2213The example above is equivalent to:
2214
2215```camkes
2216assembly {
2217  composition {
2218    component Foo f;
2219    component Bar b;
2220    connection seL4RPCCall c(from f.a, to b.a);
2221  }
2222  configuration {
2223    f.some_attribute = 0;
2224  }
2225}
2226```
2227
2228### Hierarchical Components
2229
2230#### Syntax
2231
2232A component definition may include a composition and configuration section.
2233The composition and configuration sections must be the last items in the component definition.
2234The composition and configuration sections may appear in any order. A composition section
2235can be included without a configuration, however a configuration section is only allowed
2236if there is a composition.
2237
2238```camkes
2239component Foo_Impl {
2240  provides iface_a a_impl;
2241  attribute string str;
2242}
2243
2244component Foo {
2245  provides iface_a a;
2246
2247  composition {
2248    component Foo_Impl fi;
2249    export fi.a_impl -> a;
2250  }
2251  configuration {
2252    fi.str = "Hello, World!";
2253  }
2254}
2255
2256component Bar {
2257  control;
2258  uses iface_a a;
2259}
2260
2261assembly {
2262  composition {
2263    component Foo f;
2264    component Bar b;
2265    connection seL4RPCCall c(from b.a, to f.a);
2266  }
2267}
2268```
2269
2270In the example above, the component `Foo` exposes a virtual interface `a`,
2271which is exported from the interface `a_impl` of the component instance `fi` of type `Foo_Impl`.
2272
2273#### Hierarchy Resolution
2274
2275Prior to compilation, the AST representing the system is transformed to remove all
2276hierarchical components. For each instance of a compound component, any internal instances
2277and internal connections declared
2278inside the component are copied into the top-level assembly with the compound component instance's
2279name prepended to their own.
2280Each appearance of a virtual interface of some compound component instance
2281in a connection in the top-level assembly, is replaced
2282with the exported interface of the internal instance copied into the top-level assembly
2283while resolving that compound component instance.
2284Then, for each compound component, all virtual interfaces are removed.
2285If this results in any components with no interfaces, these components, and all instances
2286of such components, are removed from the specification.
2287
2288The example above would be converted into the following:
2289
2290```camkes
2291component Foo_Impl {
2292  provides iface_a a_impl;
2293  attribute string str;
2294}
2295
2296component Bar {
2297  control;
2298  uses iface_a a;
2299}
2300assembly {
2301  composition {
2302    component Bar b;
2303    component Foo_Impl f.fi;
2304    connection seL4RPCCall c(from b.a, to f.fi.a_impl);
2305  }
2306  configuration {
2307    f.fi.str = "Hello, World!";
2308  }
2309}
2310```
2311
2312#### Examples
2313
2314##### Connecting multiple compound components
2315
2316It's possible for both sides of a connection to be virtual interfaces:
2317
2318```camkes
2319component Foo_Impl {
2320  provides iface_a a_impl;
2321}
2322
2323component Bar_Impl {
2324  uses iface_a a_usage;
2325}
2326
2327component Foo {
2328  provides iface_a a;
2329
2330  composition {
2331    component Foo_Impl fi;
2332    export fi.a_impl -> a;
2333  }
2334}
2335
2336component Bar {
2337  uses iface_a a;
2338
2339  composition {
2340    component Bar_Impl bi;
2341    export bi.a_usage -> a;
2342  }
2343}
2344
2345assembly {
2346  composition {
2347    component Foo f;
2348    component Bar b;
2349    connection seL4RPCCall c(from b.a, to f.a);
2350  }
2351}
2352```
2353
2354This example compiles to:
2355
2356```camkes
2357component Foo_Impl {
2358  provides iface_a a_impl;
2359}
2360
2361component Bar_Impl {
2362  uses iface_a a_usage;
2363}
2364
2365assembly {
2366  composition {
2367    component Foo_Impl f.fi;
2368    component Bar_Impl b.bi;
2369    connection seL4RPCCall c(from b.bi.a_usage, to f.fi.a_impl);
2370  }
2371}
2372```
2373
2374##### Compound component with non-virtual interfaces
2375
2376A component can have both virtual and implemented interfaces:
2377
2378```camkes
2379component Foo_Impl {
2380  provides iface_a a_impl;
2381}
2382
2383component Foo {
2384  provides iface_a a;
2385  provides iface_b b;
2386
2387  composition {
2388    component Foo_Impl fi;
2389    export fi.a_impl -> a;
2390  }
2391}
2392
2393component Bar {
2394  uses iface_a a;
2395  uses iface_b b;
2396}
2397
2398assembly {
2399  composition {
2400    component Foo f;
2401    component Bar b;
2402    connection seL4RPCCall c(from b.a, to f.a);
2403    connection seL4RPCCall c(from b.b, to f.b);
2404  }
2405}
2406```
2407
2408This example compiles to:
2409
2410```camkes
2411component Foo_Impl {
2412  provides iface_a a_impl;
2413}
2414
2415component Foo {
2416  provides iface_b b;
2417}
2418
2419component Bar {
2420  uses iface_a a;
2421  uses iface_b b;
2422}
2423
2424assembly {
2425  composition {
2426    component Foo f;
2427    component Bar b;
2428    component Foo_Impl f.fi;
2429    connection seL4RPCCall c(from b.a, to f.fi.a_impl);
2430    connection seL4RPCCall c(from b.b, to f.b);
2431  }
2432}
2433```
2434
2435##### Deeper Hierarchy
2436
2437So far, each example has had a compound component containing only non-compound component instances.
2438It's possible to have a hierarchy of components of an arbitrary depth.
2439
2440```camkes
2441component A_Piece1 {
2442  provides a_piece ap;
2443}
2444
2445component A_Piece2 {
2446  uses a_piece ap;
2447  provides iface_a a_impl;
2448}
2449
2450component Foo_Impl {
2451  provides iface_a a_impl;
2452
2453  composition {
2454    component A_Piece1 a1;
2455    component A_Piece2 a2;
2456    connection seL4RPCCall c(from a1.ap, to a2.ap);
2457    export a2.a_impl -> a_impl;
2458  }
2459}
2460
2461component Foo {
2462  provides iface_a a;
2463
2464  composition {
2465    component Foo_Impl fi;
2466    export fi.a_impl -> a;
2467  }
2468}
2469
2470component Bar {
2471  uses iface_a a;
2472}
2473
2474assembly {
2475  composition {
2476    component Foo f;
2477    component Bar b;
2478    connection seL4RPCCall c(from b.a, to f.a);
2479  }
2480}
2481```
2482
2483This example compiles to:
2484
2485```camkes
2486component A_Piece1 {
2487  provides a_piece ap;
2488}
2489
2490component A_Piece2 {
2491  uses a_piece ap;
2492  provides iface_a a_impl;
2493}
2494
2495component Bar {
2496  uses iface_a a;
2497}
2498
2499assembly {
2500  composition {
2501    component Bar b;
2502
2503    component A_Piece1 f.fi.a1;
2504    component A_Piece2 f.fi.a2;
2505
2506    connection seL4RPCCall f.fi.c(from f.fi.a1.ap, to f.fi.a2.ap);
2507    connection seL4RPCCall c(from b.a, to f.fi.a2.a_impl);
2508  }
2509}
2510```
2511
2512### Hierarchical Attributes
2513
2514Attributes of internal instances and internal connections declared in the composition section
2515of a compound component may be set to refer to attributes of that compound component. During
2516hierarchy resolution, values of referring attributes are set to copies of the values of
2517their corresponding referent attributes.
2518
2519#### Syntax
2520
2521The `<-` operator is used to set an attribute to refer to another. Lines of the following form
2522may appear in the configuration section of a compound component:
2523
2524```camkes
2525entity_name.attribute_name <- local_attribute_name;
2526```
2527
2528Here, `entity_name` is the name of a component instance or connection declared in the component's
2529composition section, `attribute_name` is the name of an attribute of the entity, and
2530`local_attribute_name` is the name of an attribute of the composition component.
2531
2532#### Example
2533
2534```camkes
2535component B {
2536  ...
2537  attribute string b_str;
2538}
2539
2540component A {
2541  ...
2542  attribute string a_str;
2543
2544  composition {
2545    ...
2546    component B b;
2547  }
2548  configuration {
2549    ...
2550    b.b_str <- a_str;
2551  }
2552}
2553
2554assembly {
2555  composition {
2556    ...
2557    component A a;
2558  }
2559  configuration {
2560    ...
2561    a.a_str = "Hello, World!";
2562  }
2563}
2564```
2565
2566This example is resolved to the following:
2567
2568```camkes
2569component B {
2570  ...
2571  attribute string b_str;
2572}
2573
2574component A {
2575  ...
2576  attribute string a_str;
2577}
2578
2579assembly {
2580  composition {
2581    ...
2582    component A a;
2583    component B a_b;
2584  }
2585  configuration {
2586    ...
2587    a.a_str = "Hello, World!";
2588    a_b.b_str = "Hello, World!";
2589  }
2590}
2591```
2592
2593### Custom Data Types
2594
2595CAmkES allows the definition of custom data types for procedure method arguments and ports.
2596Data types can be defined in C header files by typedefing a struct, enum or built-in type.
2597Sections of the application that refer to custom types must include the header file.
2598
2599#### Procedures
2600
2601Assume a data type `Vector` is defined in the file vector.h in the top level include directory of the application:
2602
2603```c
2604#ifndef _VECTOR_H_
2605#define _VECTOR_H_
2606
2607typedef struct {
2608  double x;
2609  double y;
2610} Vector;
2611
2612#endif
2613```
2614
2615A procedural interface could then be defined to use the type:
2616
2617```camkes
2618procedure algebra_iface {
2619  include <vector.h>;
2620  Vector add(Vector a, Vector b);
2621}
2622```
2623
2624C source files that need access to this data type can include the file with:
2625
2626```c
2627#include <vector.h>
2628```
2629
2630To make the build system aware of the header file, for each component that uses it, the following must be added
2631to the application's `CMakeLists.txt` (replacing the name `Component` with the name of the component):
2632
2633```
2634DeclareCAmkESComponent(Component INCLUDES include/vector.h)
2635```
2636
2637#### Ports
2638
2639Assume a data type `IntArray` is defined in int_array.h in the top level include directory of the application:
2640
2641```c
2642#ifndef _INT_ARRAY_H_
2643#define _INT_ARRAY_H_
2644
2645typedef struct {
2646  int data[1024];
2647} IntArray;
2648
2649#endif
2650```
2651
2652A component could declare a port of this type:
2653
2654```camkes
2655component A {
2656  control;
2657
2658  include "int_array.h";
2659  dataport IntArray int_arr;
2660}
2661```
2662
2663This would give the implementation access to a global pointer, which points to
2664an appropriately large region of memory for the data type:
2665
2666```c
2667extern volatile IntArray * int_arr;
2668```
2669
2670### Single Address Space Components (Groups)
2671
2672By default, each component instance in an application is given its own address
2673space. This is ideal for isolation, but this separation does not come for free
2674and inter-address space communication is necessarily more expensive than local
2675communication. To colocate two component instances in a single address space,
2676they can be grouped together:
2677
2678```camkes
2679assembly {
2680  composition {
2681    group my_group {
2682      component Foo foo;
2683      component Bar bar;
2684    }
2685  }
2686}
2687```
2688
2689Any references to such instances now need to be qualified by their group name.
2690For example, to connect the above two instances:
2691
2692```camkes
2693...
2694connection seL4RPCCall conn(from my_group.foo.inf1,
2695  to my_group.bar.inf2);
2696...
2697```
2698
2699When component instances are colocated, another connector becomes available.
2700The `seL4DirectCall` connector collapses RPC communication into a direct
2701function call. Its usage is identical to other connectors:
2702
2703```camkes
2704...
2705connection seL4DirectCall conn(from my_group.foo.inf1,
2706  to my_group.bar.inf2);
2707...
2708```
2709
2710Using this connector between two components that are not colocated is incorrect
2711and will trigger an error.
2712
2713#### Caveats
2714
2715When colocating component instances in a single address space, the intent is
2716for the environment of the instances to be as close to indistinguishable as
2717possible (with the exception of performance characteristics) from full
2718separation. This abstraction is not perfect and there are some mechanisms that
2719have slightly different semantics when used in a single address space scenario
2720and in an isolated scenario.
2721
2722Parameters of direction `out` of certain types are typically heap-located in an
2723isolated component instance. This is still true in a colocated environment, but
2724when using the `seL4DirectCall` connector, these are located in the _callee's_
2725heap, not the caller's as may be otherwise expected. Freeing one of these
2726pointers to the incorrect heap will result in heap corruption and should be
2727avoided. Conversely, _not_ freeing this pointer will leak memory and should also
2728be avoided. The recommended technique to work around this is to introduce a back
2729channel to the callee when necessary:
2730
2731```camkes
2732procedure my_proc {
2733  /* The following procedure will return a parameter, `x`,
2734   * that is a pointer into the callee's heap. It cannot
2735   * be directly freed by the caller and needs to be
2736   * passed back to the callee.
2737   */
2738  void foo(out string x);
2739
2740  /* We provide a back channel for this. */
2741  include <stdint.h>;
2742  void remote_free(uintptr_t p);
2743}
2744
2745component Caller {
2746  control;
2747  uses my_proc f;
2748}
2749
2750component Callee {
2751  provides my_proc g;
2752}
2753
2754assembly {
2755  composition {
2756    component Caller caller;
2757    component Callee callee;
2758
2759    connection seL4DirectCall conn(from caller.f, to callee.g);
2760  }
2761}
2762```
2763
2764It is then possible to implement both components' code in such a way that
2765memory is always freed to the correct heap:
2766
2767```c
2768/* Caller.c */
2769
2770int run(void) {
2771  char *x;
2772  f_foo(&x);
2773  printf("received %s\n", x);
2774  f_remote_free((uintptr_t)x);
2775  return 0;
2776}
2777```
2778
2779```c
2780/* Callee.c */
2781
2782void g_foo(char **x) {
2783  *x = strdup("hello world");
2784}
2785
2786void g_remote_free(uintptr_t p) {
2787  free((void*)p);
2788}
2789```
2790
2791This is cumbersome, but at least allows one to write safe code. In a
2792continually evolving project, it may not be known in advance whether
2793`seL4DirectCall` will be used. In these situations, it is recommended to use a
2794free wrapper that detects where a pointer is hosted. In the case of a simple
2795static heap region (the default), a wrapper can be constructed as follows:
2796
2797```c
2798/* Caller.c */
2799
2800static void safe_free(void *p) {
2801  /* These symbols are defined by generated code and
2802   * specify the bounds of the heap.
2803   */
2804  extern char *morecore_area;
2805  extern size_t morecore_size;
2806
2807  if ((uintptr_t)p >= (uintptr_t)morecore_area &&
2808      (uintptr_t)p < (uintptr_t)morecore_area + morecore_size) {
2809    /* The pointer is in our heap. */
2810    free(p);
2811  } else {
2812    /* The pointer is in the callee's heap. */
2813    f_remote_free((uintptr_t)p);
2814  }
2815}
2816
2817int run(void) {
2818  char *x;
2819  f_foo(&x);
2820  printf("received %s\n", x);
2821  safe_free(x);
2822  return 0;
2823}
2824```
2825
2826The preceding discussion dealt with `out` parameters, but note that the same
2827issue exists on _both_ sides of an `seL4DirectCall` connection using `inout`
2828parameters. That is, the argument to the callee and the final value to the
2829caller are both pointers that would normally point into a local heap, but now
2830potentially point into a remote heap.
2831
2832As a result of toolchain limitations,
2833[link-time optimisations](https://gcc.gnu.org/wiki/LinkTimeOptimization) cannot
2834be applied to a component group. If you have LTO enabled in your build settings
2835it will be ignored for component groups.
2836
2837### Global Include Directories
2838
2839CAmkES allows users to define a list of directories that will be searched
2840when resolving imports of .camkes files (components and interfaces).
2841`CAmkESAddImportPath(interfaces)` will append a directory to this search path.
2842There is an additional path for templates which can be modified by calling
2843`CAmkESAddTemplatesPath(templates)`. The repository global-components repository
2844is an example of these mechanisms being used to import components, interfaces
2845and templates into a project. The target project simply needs to include
2846`global-components.cmake` to enable these modules to be referred to from within
2847the project's camkes files. Below is an example of importing global-components:
2848```cmake
2849find_file(GLOBAL_COMPONENTS_PATH global-components.cmake PATHS ${CMAKE_SOURCE_DIR}/projects/global-components/ CMAKE_FIND_ROOT_PATH_BOTH)
2850mark_as_advanced(FORCE GLOBAL_COMPONENTS_PATH)
2851if("${GLOBAL_COMPONENTS_PATH}" STREQUAL "GLOBAL_COMPONENTS_PATH-NOTFOUND")
2852    message(FATAL_ERROR "Failed to find global-components.cmake. Consider cmake -DGLOBAL_COMPONENTS_PATH=/path/to/global-components.cmake")
2853endif()
2854include(${GLOBAL_COMPONENTS_PATH})
2855
2856```
2857
2858This allows one to place common components and interfaces in a central location
2859rather than duplicating them inside the application directory of each
2860application that uses them. Components and interfaces defined in global include
2861directories are known as **Global Components** and **Global Interfaces**.
2862When the distinction is necessary, non-global components and interfaces are
2863known as **Local Components** and **Local Interfaces**.
2864
2865#### Recommended Practices
2866
2867Generally, a component should be created as a global component unless there's
2868some good reason not to. Applications should consist of a (usually) small number
2869of control components, and possibly some application specific utility components.
2870When possible, utility components should be generalised and placed in a global
2871component repository.
2872
2873All procedural interfaces used or provided by global components should be
2874global interfaces. Applications containing multiple local components which
2875communicate over procedural interfaces should define these interfaces locally,
2876unless it would make sense for these interfaces to generalise to other components
2877in the future, in which case they should be global interfaces.
2878
2879Regarding header files defining custom data types, if the data type is specific to
2880a particular component or procedural interface, the header file should be placed
2881in the directory of that component or interface. Otherwise, header files should
2882be placed in a well known top-level subdirectory of the component repository so
2883they may be reused between components and interfaces.
2884
2885It is possible that between global components, there is some shared functionality
2886such as commonly used algorithms and data structures. Rather than duplicating this
2887code across multiple global components, it should be placed in source/header files
2888in a well known top-level subdirectory of the component repository.
2889
2890### Cached Hardware Dataports
2891
2892By default, memory backing hardware dataports (`seL4HardwareMMIO`) is mapped uncached.
2893Typically such a dataport will be backed by a device's memory mapped registers rather
2894than main memory. In such cases it's generally desired that after writing to a register
2895the effect of the write is felt immediately, and changes to device registers are observable
2896as soon as they occur, so mapping this memory uncached makes sense. There are however,
2897cases where it is preferable to map this memory cached instead.
2898
2899For example, consider a system that updates a large memory mapped frame buffer for
2900a display, by writing to it one word at a time. If this buffer was mapped uncached,
2901each word written to the buffer would incur the full time taken to write to memory.
2902If instead, the buffer was mapped cached, each word would be written to the cache,
2903incurring a much shorter write time. Cache lines would then be written back to memory
2904at a later point. This optimization works on the assumption that the throughput of
2905the cache being written back to memory is higher than that of the CPU writing
2906directly to memory a word at a time. After all the data has been written to the buffer,
2907the cache must be flushed to ensure the data is actually in the buffer.
2908
2909CAmkES provides a mechanism for flushing the cache, but currently it is a no-op
2910on all architectures other than ARM. On x86, the DMA engine is cache-coherent,
2911so there's no reason to explicitly flush the cache after writing to a cached
2912hardware dataport.
2913
2914#### Marking a hardware dataport as cached
2915
2916To map a hardware dataport cached, set the `<instance>.<interface>_hardware_cached` attribute to `true`:
2917
2918    component DisplayDevice {
2919      hardware;
2920      dataport FrameBuffer framebuffer;
2921    }
2922
2923    component DisplayDriver {
2924      ...
2925      dataport FrameBuffer framebuffer;
2926    }
2927
2928    assembly {
2929      composition {
2930        component DisplayDevice display_device;
2931        component DisplayDriver display_driver;
2932        ...
2933
2934        connection seL4HardwareMMIO fbconn(
2935          from display_driver.framebuffer,
2936          to display_device.framebuffer
2937        );
2938      }
2939      configuration {
2940        ...
2941        display_device.framebuffer_hardware_cached = true; /* <-- set this attribute
2942                                                   *     to mark dataport
2943                                                   *     as cached
2944                                                   */
2945      }
2946    }
2947
2948#### Manipulating the cache
2949
2950After writing to a cached hardware dataport, or potentially prior to reading from it,
2951it is necessary to manipulate the cache to ensure a consistent view of the memory
2952between the CPU and any devices. CAmkES provides a function for each hardware dataport
2953for doing cache operations on the range of addresses inside the dataport.
2954
2955For a dataport interface named `framebuffer`, the function that operates on the cache
2956will be
2957
2958```c
2959int framebuffer_cache_op(size_t start_offset, size_t size, dma_cache_op_t cache_op)
2960```
2961
2962`start_offset` and `size` are the offset in bytes into the dataport to start flushing,
2963and the number of bytes to flush respectively. `cache_op` is one of the three defined
2964cache operations: `DMA_CACHE_OP_CLEAN`, `DMA_CACHE_OP_INVALIDATE`, `DMA_CACHE_OP_CLEAN_INVALIDATE`.
2965The function returns 0 on success and non-zero on error
2966
2967## Templating
2968
2969CAmkES glue code, code automatically introduced into your component system at
2970compile time, is driven by a set of templates. These templates are instantiated
2971with values determined from your input ADL specification. CAmkES templates are
2972written as C code with Python snippets embedded in comments. This is all driven
2973by the [Jinja2](http://jinja.pocoo.org/docs/) templating engine. You can see
2974examples of existing templates in camkes/templates/.
2975
2976The remainder of this section gives advice for people intending to implement
2977their own templates or modify existing templates. If you are attempting to
2978modify the template environment itself, you should instead refer to the
2979[Template Environment](#template-environment) section.
2980
2981### Template Writing
2982
2983Inside a template you write C code as you would normally, but use the following
2984special comments to run Python code:
2985
2986* `/*- execute code -*/` (equivalent of Python's `exec`)
2987* `/*? execute code and replace with result -*/` (equivalent of Python's `eval`)
2988* `/*# a comment to be removed at instantiation #*/`
2989
2990In general, when writing code in a template, refer to the Jinja documentation
2991syntax and functionality. Note that the default Jinja delimiters are `{%` and
2992`%}` which have been modified to `/*` and `*/` to let syntax highlighting in C
2993work more naturally.
2994
2995Within a given template you have a variable `me` that functions like native
2996Python's `self`. It refers to the object of relevance to the current template.
2997So, for example, during instantiation of the component source file, it refers
2998to the component instance being instantiated. In certain general "top-level"
2999templates, there is no particular "subject." In these templates, for example
3000`camkes-gen.cmake`, `me` will be `None`.
3001
3002The template environment is a limited subset of Python. It is relatively easy
3003to extend, and if you intend to do this you can see how in the
3004[Template Environment](#template-environment) section. Some statements in
3005Python could not be cleanly exposed and so have instead become functions. In
3006particular, be aware of quirks in assertions, lambdas and exceptions. `assert`
3007is available as a function. So instead of writing `assert foo == 1` you would
3008write `assert(foo == 1)`.
3009
3010Lambdas are perhaps more confusing. Instead of writing
3011`lambda x: x.startswith('hello')` you would write
3012`lambda('x: x.startswith(\'hello\')'`. Note that you lose some type safety and
3013expressivity here, but there did not seem to be a nicer way to expose this.
3014Exceptions are now also raised by function. So instead of writing
3015`raise Exception('foo')` you would write `raise(Exception('foo'))`.
3016
3017For the specific functionality available in the template context, it may be
3018helpful to refer to the file camkes/runner/Context.py. Note that in the
3019template context you also have access to the command line options via `options`
3020as well.
3021
3022### Idioms
3023
3024There are certain common operations you may wish to perform inside a template
3025context, for which idioms have developed. This section documents some of these
3026snippets of code that may look unusual when you first encounter them.
3027
3028#### Passing Information Between Templates
3029
3030You often wish to do this with two related templates. For example, in the
3031templates that form each side of a connection you often wish to talk about the
3032same object on both sides. None of the templates currently call the low-level
3033helper functions that enable this directly, but if you do want to invoke them,
3034they are `stash` and `pop`. `stash` lets you save a Python object under a given
3035key name and `pop` retrieves a previously saved Python object by key. Note that
3036these are only usable for passing objects between templates that share related
3037`me` references.
3038
3039#### Generating Symbol Names
3040
3041Within a C template you sometimes need a temporary variable in a context in
3042which user-provided variables may be in scope. That is, you need a named symbol
3043but you need to ensure it doesn't collide with any existing user symbols. To do
3044this you can call the function `c_symbol`. This generates a pseudo-unique name
3045that you can use from then on. For example,
3046
3047```c
3048/*- set my_var = c_symbol() -*/
3049int /*? my_var ?*/ = 42;
3050...
3051```
3052
3053`c_symbol` takes an optional string argument that will make that string part of
3054the resulting symbol name. This is helpful for debugging purposes if you want
3055to give someone looking at the instantiated template a visual clue as to the
3056purpose of a temporary variable.
3057
3058#### Subverting Scoping
3059
3060Jinja has some unusual and often counter-intuitive variable scoping rules.
3061Occasionally templates wish to conditionally assign to a variable within the
3062context of a loop or other Jinja block. In these circumstances it can be tricky
3063to get the write to propagate outside the loop. You may see a temporary array
3064and a `do` construct used in these situations:
3065
3066```c
3067/*- set temp = [None] -*/
3068/*- for .... -*/
3069  ...
3070  /*- if ... -*/
3071    /*- do temp.__setitem__(0, True) -*/
3072  /*- else -*/
3073    /*- do temp.__setitem__(0, False) -*/
3074  /*- endif -*/
3075  ...
3076/*- endfor -*/
3077/*- set variable_we_want_to_set = temp[0] -*/
3078```
3079
3080### Reply Capabilities
3081
3082The seL4 system call, `seL4_Call`, generates transient capabilities called
3083reply capabilities (see the seL4 documentation for more specific details). Care
3084must be taken when writing template code in order to avoid interfering with the
3085functionality of another piece of template code that may have created reply
3086capabilities. If you are not using reply capabilities yourself, there is a
3087simple rule to remember:
3088
3089* always call `camkes_protect_reply_cap()` before performing an operation that
3090  would cause a wait on a synchronous endpoint.
3091
3092This call is idempotent (you can call it multiple times in sequence with no ill
3093effects), though be aware it may modify the contents of your IPC buffer. You
3094do not need to perform this operation when sending on a synchronous endpoint or
3095waiting on a notification, however it _is_ necessary when performing
3096batched system calls like `seL4_ReplyRecv` or `seL4_Call` on a synchronous
3097endpoint.
3098
3099If you are _receiving_ reply capabilities in your own template and calling
3100external functionality before using them, you need to be aware that they can be
3101overwritten when execution is outside your template. To safe guard yourself
3102against this, there is a complementary rule:
3103
3104* always call `camkes_declare_reply_cap(...)` when you have just received a
3105  reply capability.
3106
3107Note that you need to pass this function an empty capability slot into which to
3108save the reply capability if it is about to be overwritten. In order to support
3109saving of this reply capability on demand, CAmkES needs a capability to the
3110current thread's CNode. This needs to be setup by your template code. Some
3111variant of the following code needs to be executed for each thread that could
3112receive a reply capability:
3113
3114```c
3115/*# Allocate a cap to our own CNode. #*/
3116/*- set cnode = alloc_cap('cnode', my_cnode) -*/
3117/* Configure a TLS pointer to our own CNode cap. */
3118camkes_get_tls()->cnode_cap = /*? cnode ?*/;
3119```
3120
3121When you need to use a reply capability you have protected, you should check
3122the `reply_cap_in_tcb` member of the CAmkES TLS structure and, if the capability
3123is no longer in your TCB, call `camkes_unprotect_reply_cap()` and deal with any
3124possible error that may have occurred. The functional API for dealing with
3125reply capabilities is provided below. Though this is technically part of the
3126[runtime API](#runtime-api), it is included here because user code is never
3127expected to call these functions.
3128
3129**`int camkes_declare_reply_cap(seL4_CPtr shadow_slot)`** (`#include <camkes/tls.h>`)
3130
3131> Identify to the CAmkES library that you are in possession of a reply
3132  capability in your TCB. CAmkES only handles a single reply capability
3133  currently and, as such, you should not call this function when you have
3134  previously declared a pending reply capability you have not yet discarded.
3135  This essentially says to CAmkES, "I have a reply cap in my TCB; please save
3136  it to `shadow_slot` if it is in risk of being deleted."
3137
3138**`void camkes_protect_reply_cap(void)`** (`#include <camkes/tls.h>`)
3139
3140> Guard any potential pending reply capability against deletion by saving it
3141  now. Note that this function accepts no arguments and returns nothing. It is
3142  designed to be called unconditionally from generated code that believes it
3143  may be about to overwrite a reply capability. There is no point providing a
3144  result to the caller because the caller is not the conceptual "owner" of
3145  the capability and does not know how to deal with a failure to protect it.
3146  You should always call this code in your template if you believe a reply
3147  capability could be present and the operation you are about to perform has a
3148  chance of deleting it.
3149
3150**`seL4_Error camkes_unprotect_reply_cap(void)`** (`#include <camkes/tls.h>`)
3151
3152> Discard any information relating to a current pending reply capability. This
3153  is designed to be called by the original declarer of a reply capability when
3154  it is about to use (or discard) that capability. Note that this returns a
3155  potential error that was encountered when some intermediate code tried to
3156  protect the capability and it failed. The return value is essentially a
3157  result from `seL4_CNode_SaveCaller`. This should _only_ be called when you
3158  know the reply cap you need is no longer in your TCB. That is, you should
3159  check the `reply_cap_in_tcb` member of the CAmkES TLS structure to determine
3160  if calling this function is necessary.
3161
3162To get a more concrete idea of how these functions are used, you can refer to
3163the seL4RPCCall connector that uses this mechanism.
3164
3165One final thing to note is that this functionality assumes cooperative
3166templates. There is nothing to prevent a malicious template omitting a call to
3167`camkes_protect_reply_cap()` and wilfully destroying pending reply
3168capabilities.
3169
3170### Template Debugging
3171
3172If you are writing complicated template logic and need to debug during
3173instantiation, you can insert breakpoints into your template. These can be
3174inserted as either `/*- breakpoint() -*/` or `/*? breakpoint() ?*/`. When
3175encountered during instantiation they will drop you into the Python
3176interpreter, from where you can explore `me` and other local variables.
3177
3178When prototyping or debugging more complicated problems it can be helpful to
3179have the ability to run arbitrary Python in the template context. There is some
3180limited support for this, with the functions `exec` and `eval`. These operate
3181like the native Python `exec` and `eval`, but may be a little more fragile.
3182Note that `exec` is a function in this context, not a statement. So where you
3183would normally write `exec 'print \'hello\''` you would write
3184`exec('print \'hello\'')`.
3185
3186Although never advisable in a proper implementation, it is possible to pass
3187arbitrary information between unrelated templates. Similar to the `stash` and
3188`pop` functions described above, there are lower level versions, `_stash` and
3189`_pop` that let you write to and read from a context that propagates across all
3190templates. Note that you can only use this to pass information "forwards" to
3191templates that are instantiated after the one you are calling `_stash` from.
3192
3193## Developers
3194
3195This section is targeted at those intending to modify the CAmkES implementation
3196itself. The information below assumes you are familiar with the features and
3197functionality of CAmkES.
3198
3199If you are modifying the actual sources of any of the CAmkES modules I've
3200attempted
3201to leave helpful comments. I've occasionally used tags in the comments that
3202may help you when grepping and whatnot. They mean:
3203
3204**FIXME**
3205
3206> This is a stop gap piece of functionality that should be replaced
3207  with something more feature complete when time permits. This could also refer
3208  to an existing bug that cannot currently be easily remedied.
3209
3210**HACK**
3211
3212> This code is a bit dubious, but is intentionally written this way to
3213  work around limitations in some other tool outside our control.
3214
3215**MOVE**
3216
3217> This is the wrong place for this piece of functionality. It should
3218  be refactored somewhere else.
3219
3220**PERF**
3221
3222> This code is structured in a counter-intuitive or non-obvious way for
3223  performance reasons. Refactor if you wish, but be aware it may have a
3224  significant impact on runtime.
3225
3226**SLOW**
3227
3228> This code is known to be inefficient, but was deliberately written
3229  this way for simplicity. If you are hitting performance problems and looking
3230  for optimisation opportunities try grepping for this.
3231
3232**TODO**
3233
3234> Some part of the functionality in this section has not yet been
3235  implemented or the code could be improved in some way.
3236
3237**XXX**
3238
3239> There is something out of the ordinary about this piece of code that
3240  should probably be fixed. This is often in cases where I didn't have time to
3241  write a proper **FIXME** or **TODO** comment.
3242
3243### Parser Internals
3244
3245* camkes/parser/*
3246
3247The previous section, [camkes.parser](#camkes.parser), describes the high-level
3248interface to the CAmkES parser. This parser is assembled from a pipeline of
3249lower-level parsers. These are each described as a "stage" in parsing. To
3250understand them, it is necessary to understand a few variants of Abstract
3251Syntax Tree representations that are referred to in the source code. The
3252following representations are described in order from least to most abstract:
3253
3254* **Augmented input** This is not an AST, as such, but rather a tuple of source
3255  data and a set of read files.
3256* **Raw AST** This is a tree of `plyplus.stree`s.
3257* **Augmented AST** This is a list of `plyplus.stree`s with attached
3258  information about their original source data and the file they came from.
3259* **Lifted AST** This is the most abstract programmatic representation of an
3260  input specification and the form developers will come to be most familiar
3261  with. It is a tree of objects from [camkes.ast](#camkes.ast).
3262
3263The various low-level parsers are each responsible for a specific AST
3264transformation, with the high-level parser stringing them all together for ease
3265of use. The low-level parsers are:
3266
3267* **Stage 0** Reads an input file and optionally runs the C pre-processor over
3268  it. This "parser" is really just a more full featured version of the `open`
3269  call.
3270* **Stage 1** Parses input using `plyplus`. Note that this is where the CAmkES
3271  grammer (camkes/parser/camkes.g) comes into play.
3272* **Stage 2** Resolves `import` statements. This parser repeatedly calls back
3273  into the stage 1 parser to parse further sources. Note that from here on,
3274  `import` statements do not appear in the AST.
3275* **Stage 3** Lifts the `plyplus` AST into the objects of
3276  [camkes.ast](#camkes.ast). This is generally the most intensive parse phase
3277  and inherently the most fragile as it encodes much of the semantics of the
3278  CAmkES input language.
3279* **Stage 4** Resolves semantic references. From here on, no
3280  `camkes.ast.Reference`s remain in the AST.
3281* **Stage 5** Collapses `group`s. The `group` keyword is used to colocate
3282  component instances into a single address space. This stage removes groups
3283  from the AST, assigning the same address space to their contained instances.
3284* **Stage 6** Combines multiple assemblies. It is possible for more than one
3285  `assembly` block to be specified in a CAmkES input specification, in which
3286  case the intended assembly is the concatentaion of all of them. This stage
3287  performs that concatenation.
3288* **Stage 7** Flattens component hierarchies. Component instances that are
3289  nested inside other components are hoisted to the top-level assembly by this
3290  stage.
3291* **Stage 8** Resolves attribute references. Settings can be given a value that
3292  references another attribute (using the `<-` operator). This stage resolves
3293  these references to concrete values.
3294* **Stage 9** Freezes the AST. This stage transforms various AST internal data
3295  structures into optimised forms and makes AST modification from this point on
3296  impossible.
3297
3298With this information, looking back at the high-level parser, one can see that
3299it simply chains these stages together. It is possible to programmatically
3300construct a differing or partial parser by composing the low-level parsers in a
3301different manner.
3302
3303#### Pre-Compiled Templates
3304
3305 * camkes/runner/Renderer.py
3306
3307The Jinja templating engine works by compiling template code to native Python
3308code, which it then runs to produce the generated output. This compilation to
3309Python code is normally performed in each execution. To speed up this process,
3310when caching is enabled, the templates are compiled to the cache directory. In
3311future executions, template rendering optimistically fetches pre-compiled
3312templates from this cache. On a cache miss, it falls back to the original
3313template sources.
3314
3315### Template Context
3316
3317The code that renders the templates themselves is all contained under the
3318runner directory in the CAmkES module. While the rendering itself is driven
3319from Renderer.py, the more relevant file is actually Context.py. The
3320`new_context` function returns a dictionary that defines the template
3321environment, that is, what local variables are present in the template at
3322instantiation time.
3323
3324There is some fairly complex functionality here aimed at providing nice
3325abstractions to template authors. In particular, `alloc_obj`, `alloc_cap`,
3326`stash`, `pop` and `guard` are intended to provide an abstraction for the
3327template author to pass variables between templates. Refer to the comments in
3328this file to understand more about the template context.
3329
3330Extending the context can be done by adding more items to this dictionary and
3331there aren't many gotchas here. If you're doing something more complicated than
3332exposing an existing built-in and having difficulty you may find the
3333implementations of `breakpoint` or `exec` informative as examples.
3334
3335### Core Libraries
3336
3337CAmkES has a notion of "core libraries" as the set of seL4 libraries that may
3338be relied on to be available from within the template context. These are
3339defined within the camkes-gen.cmake template. This set of libraries has been extended on demand to cover all
3340base seL4 infrastructure. This can be freely expanded to cover more libraries
3341with no expected surprises.
3342
3343Be aware that these libraries will be unconditionally depended upon and linked
3344into all CAmkES components. That is, the user's lists of libraries defined in
3345their application CMakeLists.txt will all be silently extended to include the core
3346libraries.
3347
3348### Testing
3349
3350CAmkES has a set of unit tests and a set of integration tests. The unit tests
3351are structured per-module, with each module's tests in a subdirectory of its
3352source:
3353
3354 * camkes/ast/tests
3355 * camkes/internal/tests
3356 * camkes/parser/tests
3357 * camkes/runner/tests
3358 * camkes/templates/tests
3359
3360The unit tests use Python's
3361[unittest](https://docs.python.org/2/library/unittest.html) framework. The
3362simplest way to execute them is from the top-level wrapper script:
3363
3364```bash
3365./alltests.py
3366```
3367
3368Alternatively, any finer granularity of test cases may be selected:
3369
3370```bash
3371# Run all AST unit tests
3372./camkes/ast/tests/runall.py
3373
3374# Run only AST hashing assumption tests
3375./camkes/ast/tests/runall.py TestHashingAssumptions
3376
3377# Run only the specific test for hashing None
3378./camkes/ast/tests/runall.py TestHashingAssumptions.test_none
3379```
3380
3381The integration tests are contained in the CAmkES project repository under the
3382directory tests/. Again, the simplest way to execute these is with a wrapper
3383script:
3384
3385```bash
3386./tests/run-all.py
3387```
3388
3389Alternatively, you can run individual integration tests:
3390
3391```bash
3392# Test simple RPC
3393./tests/arm-simple.tcl
3394```
3395