Language constructs and transformation for hard real-time systems.
In practice, time critical portions of hard real-time systems are still implemented in low-level programming languages and manually tuned to meet all the timing requirements. Without a real-time language that supports an appropriate way of specifying timing constraints for a generic hard real-time systems, and high precision timing analysis that is transparent to users, the users will ever suffer from the complex coding and analysis, particularly for systems requiring fast turnaround responses.In this paper, we propose novel language constructs that can be added to any imperative programming language so that the extended language provides users a way to specify relative timing constraints between arbitrary operations at instruction-level. The compilation techniques unique to transformation of the proposed language are also presented as a part of CHaRTS, the Compiler for Hard Real-Time Systems, which generates a valid instruction sequence for a target execution model.
Introduction
In our view of real-time systems, a real-time system consists
of a controlling subsystem and controlled entities.
A controlling subsystem is a set of computer systems,
while the controlled entities can be any of a broad range
of systems with mechanical behavior, any device from
a simple blender to a complex robot [19]. Typically, a
controlling subsystem executes control programs to receive
input from the environment and/or to send commands
to the controlled entities appropriately.
For a real-time system to function correctly, the control
program must be logically correct and the controlling
subsystem must execute the program without timing
faults. Either a failure to perform an action at the
appropriate time or a flaw in the control program's logic
can yield catastrophic consequences in hard real-time
systems. Thus, meeting the timing constraints is extremely
important in such systems.
Based on when the control program is scheduled,
real-time systems can be divided into two categories:
dynamic and static. Execution order of control tasks in
a dynamic system is determined on-the-fly at run-time
by a scheduler that examines the current status of the
system; often, this scheduler is a part of the operating
system. Even though the dynamic systems are flexible,
they suffer from scheduling overhead and unpredictable
risks.
In contrast, a static system is scheduled at compile
time based on analysis of the program, timing con-
straints, and resource use predictions [16]. A static
system schedules the execution order at compile time
based on the predicted behavior of the controlled entities
and the timing properties of the controlling subsys-
tems. Thus, the static system guarantees that properly
scheduled code will function without a timing failure.
However, despite the fact that guaranteed timely execution
makes the static systems very attractive in a hard
real-time environment, the high-precision static systems
have received little attention due to:
1. Unpredictable machine behavior: general-purpose
processors often implement instructions with execution
time dependent on operand values, pipeline
conflicts, or memory hierarchy use (e.g., cache
misses, dynamic RAM refresh, virtual memory
page faults). Any of these variables degrades the
accuracy of the required timing analysis.
2. Scheduling complexity: both the instruction-level
timing analysis and the code reorganization are
NP-complete problems [6]. Thus, static scheduling
has focused on coarse-grain tasks to reduce the
problem size.
3. Lack of programming support: no programming
language supports a mechanism to express fully
general real-time constraints.
The first problem is not easily solved, but can be
avoided by careful design of the computer hardware. For
example, the TMS320C40 high-performance DSP has
completely static timing properties, provided that interrupts
are disabled and local memory is implemented
by SRAM [10]. Even interactions between multiple processors
can be made to have static timing properties.
For example, PAPERS (Purdue's Adapter for Parallel
Execution and Rapid Synchronization) can provide fine-grain
communication and synchronization with precise
static timing properties [5].
Although further work is needed, we believe that the
techniques presented in [3] form the basic foundation
for an appropriate static scheduling algorithm. Thus,
the second problem is partially solved and a practical
solution is likely to be found soon.
This leaves the problem of providing an appropriate
programming model and language. Part of this problem
is that specifying fine-grain timing constraints in
the context of a high-level programming language seems
paradoxical. Assembly language hand coding to resolve
fine-grain timing constraints is not the answer; such
programs are difficult to write and maintain, and automated
scheduling is almost impossible [11].
It is equally futile to directly use existing high-level
real-time programming languages, such as ADA [2],
Edison [9], or programming languages extended from
the general purpose languages like RT-Euclid [12],
FLEX [15], MPL [17] and TCEL [7], because they do not
provide a mechanism for specifying timing constraints
on any language construct finer in granularity than an
entire task. These languages also suffer from use of a
programming model that represents timing constraints
as relationships between task pairs that are lexicographically
adjacent in the source program; this adjacency
constraint is both artificial and insufficiently expres-
sive. Timing relationships between arbitrary (poten-
tially parallel) operations cannot be expressed because
some such relationships cannot be mapped into lexicographically
adjacent positions in the program.
Section 2 of this paper proposes novel language constructs
that can be added to any imperative programming
language so that the extended language provides
users with a way to specify relative timing constraints
between arbitrary actions at the level of individual in-
structions. To aid the reader in understanding how
these timing constraints are extracted and processed,
Section 3 provides a brief summary of the relevant compiler
technology. Section 4 summarizes the contributions
of this paper and suggests future directions for
research.
Real-time language
To motivate the design of the new language constructs,
consider the informally annotated control program fragment
shown in Figure 1. Although this example is remarkably
simple and embodies timing constraints that
could easily have been found in a real application, none
of the existing programming languages is capable of expressing
this in a form that would facilitate static timing
analysis and scheduling.
Value from sensor 1 */
must execute no later than 1 -s after i 3
must execute at least 1 -s after i 5
Value from sensor 2 */
must execute no later than 1 -s after i 1
inputs */

Figure

1: An example of real-time code segment.
2.1 Timing constraint model
The real-time language we propose in this paper implements
a graphical model, denoted as
the directed graph G consists of a set of nodes \Gamma and a
set of edges \Theta. The nodes and edges are associated with
instructions and real-time constraints respectively. The
graphical model, called a directed timed graph or DTG,
is distinguished from conventional directed graphs in
several aspects. Most importantly, each edge in a DTG
does not necessarily indicate a precedence or dependence
relation, but represents the direction of the temporal
relation between two control action.
An instruction in \Gamma can be classified as an externally
viewed instruction(EVI) or an internally viewed instruc-
tion(IVI) based on the effect of the instruction 1 .
The effect of IVI is limited to the internal compu-
tation, while an EVI changes the status of the control
environment. For example, the variables defined
as volatile in the C language [20] or commands to control
robots using RCCL [13] are EVIs, and their execution
must meet the timing constraints specified. Because
EVIs may depend on values computed by IVIs,
any such dependence also implies a relative timing constraint
(execution order) which must be preserved.
A directed edge in \Theta is associated with multiple at-
tributes: source object fl s , sink object fl e , relational
This concept is not common, but a similar view was taken
by some compiler designers for code optimization [4] and some
real-time compiler developers for improved schedulability [7].
operator j, and offset ffi . A constraint ' k is defined
as ?. The type of relationship represented
by each edge is specified by j: before(!),
after(?), concurrent(=), or exclusive(6=). Indeed, any
temporal relations between fl s and fl e for each edge type
can be expressed with time value ffi as:
must happen
at the latest ffi after
ffl after constraint : must happen at
the earliest ffi after
ffl concurrent constraint : must happen
exactly at ffi after
must NOT
happen at ffi after
An edge representing the direction of the temporal
relation between the source instruction (fl s ) and sink
instruction (fl e ) follows a simple rule. The fl s and fl e
appear, respectively, in the RHS and the LHS of the
constraint.
The fl s and fl e can be any arbitrary pair of instruc-
tions. Moreover, this method is sufficient to specify the
constraints among n instructions using less than n(n-
1)/2 constraints in this model. That is, any constraint
among multiple instructions can be specified by our constraint
model - even constraints which cannot be satisfied
by a sequential schedule (i.e., constraints which
imply parallel execution).
It is significant that simple ordering (precedence)
constraints can be represented without introducing any
additional types. Each precedence constraint of the
form "x uses y's result'' can be encoded as the after
constraint "x happens at the earliest 0 after y". Hence,
both timing constraints and precedence constraints can
be expressed using the same syntax.
2.2 Real-time languages features
The single most important aspect of any programming
system is how easily that system can be used to create
and maintain working programs. Although the relative
ease of programming of various languages is largely a
matter of religious debate, it is clear that familiar language
constructs and programming tools are more effective
than if a completely new program development
style must be adopted. The real-time language should
look and feel like a popular conventional language, e.g.,
C. Likewise, because there is no familiar syntax that
can be borrowed for expressing timing constraints, it is
critical that the timing aspects of the code be directly
observable and easy to modify. Any timing constraint
involving two operations should be able to be expressed
directly, without having to adjust other portions of the
code.
Part of the ability to treat each constraint independently
depends on the ability to combine multiple
constraints that affect the same operation. Although
most work on real-time systems suggests that such constraints
are always combined by requiring all constraints
to be met, it is sometimes necessary [8] to combine constraints
by requiring that any one or more of these constraints
be met. This concept of an ORing constraint is
quite new in the real-time community. Suppose an event
A 1 can be executed either before A 2 or after A 3 as shown
in

Figure

2. This can be mathematically expressed as
shows that the possible
range of A 1 could be different for the same constraint
based on the temporal values of A 2 and A 3 . Despite
the usefulness and necessity of such a construct, ORing
constraints have been conspicuously absent from other
real-time programming languages, perhaps because the
scheduling is made more complex by supporting both
types of constraint combining.
time axis time axis

Figure

2: An example of ORing constraint.
We further suggest that it is critical that the timing
constraints be expressed at the finest possible grain
level. Because finer grain yields more freedom in the
compiler's scheduling, this yields the highest probability
that all timing constraints can be met. Of course,
more freedom in scheduling also implies a larger search
space for schedules, but the user does not need to be
aware of the additional complexity in the compiler.
The concept of a cyclic task in a program is a structure
that is unique to real-time systems, but is commonly
used. There is no obvious way to obtain the
same effect using other constructs, and subtle methods
destroy maintainability. Thus, we suggest that cyclic
structures should be directly represented in the lan-
guage, making them easy to recognize for both programmer
and compiler. In fact, the language should allow
multiple arbitrary cyclic tasks to be specified without
concern for how the different length cycles will be converted
into a single coherent schedule.
2.3 Parent language
Thus far, none of the existing real-time languages provides
all the features mentioned above. Most of the real-time
languages are not easy to program, not based on
fine-grain tasks, and/or not designed to express relative
constraints among arbitrary control operations. Thus,
we propose an extension of an imperative language to
facilitate the features. Even though any imperative language
can be extended for those features, we develop
novel language constructs onto a subset of the C language
because C is used for most of the embedded real-time
systems in conjunction with assembly macros for
time critical portions.
The parent language we propose includes all expressions
using arithmetic and relational operators, if state-
ment, and while statement. At this time, neither aliasing
nor floating point computation is supported.
2.4 Proposed language constructs
In order to specify the constraints on top of the parent
language, we introduce several new constructs: timing
block, temporal expression and cyclic block. A timing
block defines a code segment to be manipulated as a unit
for the purpose of constraint specification, while time
expression specifies the relative constraints in terms of
the timing blocks. A cyclic block is defined for the code
sequence that runs indefinitely or until the program ter-
minates. A program may contain more than one cyclic
block.
Before illustrating the constructs, consider an example
of a control program shown in Figure 3. The
program is written to read data from memory locations
where they are updated by the devices, and to
write commands to memory locations where they are
dispatched to the devices at desired times.
2.4.1 Timing block
A timing block is a user-defined variable or a sequence
of statements that could be viewed as a task in the traditional
real-time systems. That is, it contains either a
volatile variable (EVI) or statement(s) that consist of
at least one EVI. If a timing block contains no EVI,
the temporal expressions associated with the temporal
variable are ignored, implying that the constraint is automatically
The timing variable identifying a timing block appears
between "@" and ":" that is followed by an EVI
or a body of the block as shown in the syntax:
@tvar: variable
or
Here, tvar is a user defined name for the block and
variable is a regular variable that is an EVI 2 . The notation
(statement)+ denotes one or more statements
2 The volatile variables are translated into one or more instructions
in low-level languages.
1: main()
2: f
3: volatile char action1, action2, action3;
4: volatile int sense1, sense2, sense3;
5: char command1, command2;
int a,b,c,d;
7:
8:
9: cycle @tp1:(5) f
10: /* Read in data stored by sensors. */
13: /* Specify timing between the reads */
14: @: tv1.
Action based on the data read */
19: else
21: /* Specifying the timing for action */
25: /* timing constraints in a loop */
27: while( a
28:
34: @: .tv8 ? .tv6 +10;
37: cycle @tp2:(10) f
38: int c;
43: /* tp2 should be started before tp1 */
44:
45: exit(0);

Figure

3: A program with the new constructs.
composing a timing block. For example, line 12 in Figure
3 defines temporal variables tv2 and tv3 that are
associated with a variable sensor2 and a statement b
4;. In this case, tv2 is a nested block of
tv3.
A timing block has all the properties of a regular
block, such that it is lexically scoped and variable declarations
are allowed in the beginning of the block. Also,
the timing blocks can be nested unless they are inter-
leaved. The interleaving of the timing blocks is disallowed
because it increases the complexity and destroys
the structured language feature.
2.4.2 Cyclic block
Cyclic block is a special case of timing block in the
sense that the block is executed repeatedly until the
program is terminated. Thus, the compiler should treat
this block differently from other blocks for analysis as
well as scheduling. A cyclic block is identified by a temporal
variable tvar and the period ffi as defined here.
cycle @tvar:(ffi) f statement(s) g
The cycle is a keyword indicating that the following
block enclosed by f and g is a cyclic block, tvar is the
temporal variable name for the block, and ffi specifies the
timing requirement that the cyclic block must complete
within. That is, the statements in the timing block
and looping overhead must be completed within ffi .
The timing constraints associated with a cyclic block
may be expressed in the temporal expressions described
later. For example, the program in Figure 3 consists of
two cyclic blocks tp1 (line 9 to 35) and tp2 (line 37 to
42), and a temporal relation between the cyclic blocks
is specified in line 44. The temporal expression in line
44 implies that the first action of tp2 should not be
executed later than 2 time units after the last action of
tp1.
2.4.3 Temporal expression
A temporal expression is classified as either a temporal
assignment or a temporal relation. A temporal assignment
is a way of defining another temporal variable that
has temporal distance from an existing temporal vari-
able, while a temporal relation is used to express the
relationship between the temporal variables.
or
In this syntax, tvar is the name of a temporal vari-
able, and etvar is an extended temporal variable indicating
the start time or completion time using prefixed-
dot or postfixed-dot respectively. In Figure 3, tv1. in
line 14 indicates the completion time of tv1 while .tv3
in line 15 indicates the start time of tv3. Also, j is one
of the temporal relation operator defined in the previous
section, and ffi is the offset that is any time unit as
small as a clock cycle. Also, the temporal relation
indicates zero or
more temporal relations to specify ORing constraint.
As we have seen in the syntax of the temporal as-
signment, computation upon the temporal variables is
allowed. For example, temporal assignment
implies that the start time of tv3 must happen earlier
than 14 time units after the start time of tv3 which is
equivalent to .tv3 7.

Figure

3 illustrates one unique temporal expression
for the timing constraints involving the iterations.
When a block that appears in iterated loop is consid-
ered, it is necessary to specify timing constraints between
the instances in different iterations. We introduce
an array of temporal variables to resolve this problem.
As we see in line 31 of Figure 3, the distance between the
instances are expressed as the index of the array. For
example, line 31 says that the loop should be executed
within units because the temporal expression
requires that the first action of the (i + 1)th iteration
should be started earlier than 25 time units after last
action of the ith iteration. At this point, we formally
define etar as:
where tvar is a temporal variable and f[i]g is an
optional expression of [i] denoting ith instance of the
iteration.
2.4.4 Illegal expressions
The lines 17 to 20 of the Figure 3 defines the temporal
variables tv4 and tv5 and lines 22 to 23 shows corresponding
temporal expressions, temporal assignment
and temporal relation. It says that the action in the
then clause should be performed later than 14 time units
after tv2 is completed. Thus, the timing constraint is
taken into account only when a ! b holds. However,
any temporal expression that has a pair of instructions
one from the then clause and the other from
the else clause is illegal because it is impossible to run
both branches in an execution.
Another illegal expression is the statement whose
pair of instructions necessarily include a statement with
unpredictable timing property between them. Those
statements are any instructions whose timings are not
predictable such as a break statement in a loop, unpredictable
number of iterations, and unpredictable instructions
involving interrupts. For example, the execution
of tv6 (line 26 to 32) is repeated as long as
holds. Hence, if the range of a and b are non-
deterministic, the temporal expression in line 34 is an
illegal expression.
Temporal expression specifying a timely conflict actions
is also classified as an illegal expression. Consider
two expressions in line 14 and 15, and modify line 14
to
solution, implying that the
code cannot have a valid schedule. Thus, those two temporal
expressions are illegal. These illegal expressions
are found only by thorough semantic analysis.
3 Compilation techniques
In this section, we briefly explain the compilation techniques
unique to process the language transformation.
Particularly, the compiler organization, data structure
of intermediate representation, and cyclic block scheduling
are focused because they are either very much different
from conventional compilation techniques [1] [4]
or novel concept to the compilation.
3.1 Compiler organization
As we see in Figure 4, CHaRTS consists of four software
modules: syntax analysis, semantic analysis, code
scheduling, and code generation module. Each module
is designed and implemented to be independent so that
the software can be individually replaced for enhance-
ment. For example, the scheduling algorithm we developed
[3] can be replaced with better one without affecting
any other modules except minimal modification on
interface between them. In our implementation, those
modules are written in the C language with the support
of PCCTS (Purdue Compiler Construction Tool Set).
Analysis
Code Scheduling
Analysis
Code Generation
Intermediate
Representation
Front-end Phase
Back-end Phase
Program
System
Data
Target Code

Figure

4: Compiler architecture for the proposed language

The syntax analysis module performs building an intermediate
representation from a source program. The
intermediate representation of CHaRTS is unique as described
in section 3.2 because of the timing constraint
specification and cyclic blocks.
The function of the semantic analysis module is to
verify a program context against the language semantics
including the followings:
ffl Does the timing block contain at least one EVI?
ffl Is the temporal expression semantically legal?
ffl Is it compliant to the parent language?
The objective of the code scheduling module is to
reorganize the instruction sequence to meet all the timing
constraints as well as the logical correctness. This
module and the code generation module are entirely system
dependent and the timing properties of the hardware
components and the instruction sets can be either
hard-wired into the compiler or read from a system file
as shown in the Figure 4. The input to the scheduling
module are the tuples whose timing characteristic
is close to the object code so that the execution time of
the tuples are preserved at code generation time.
3.2 Intermediate representation
In addition to the traditional role of a lexical analyzer
and parser, the syntax analysis module extracts constraints
and information of timing blocks from the program
and builds an intermediate representation. As
depicted in Figure 5, the data structure of the intermediate
representation consists of two tables and three
trees. The tables consist of a symbol table (SymTab)
and a table for temporal variables (TVarTab), while the
tree structures include an abstract syntax tree (AST),
a cycle syntax tree (CST), and a temporal syntax
tree (TST) that are all child-sibling trees [18].
Although only AST and SymTab are sufficient data
structure in conventional compilers, the compiler for
real-time systems we propose needs more information.
They are organized in TVarTab to store the information
of the timing blocks such as the block type, the
entry/exit points, the CST to manipulate all the blocks
to be executed periodically, and the TST to represent
the temporal expressions.
In particular, manipulation of CST in conjunction
with temporal expressions specifying the timing constraints
among the cyclic blocks is quite complex and is
a new concept to the compiler community because multiple
cyclic blocks need to be executed indefinitely, considering
the period and timing constraints among the
cyclic blocks.
3.3 Cyclic block scheduling
Scheduling the cyclic blocks is very different from the
conventional compilation techniques because conven-
Cyclic Syntax Tree(CST)
Temporal

Abstract

Symbol Table(SymTab)
Temporal Syntax Tree(TST)

Figure

5: Data structure in IR form of CHaRTS.
tional compilation does not have a notion of interleaving
loops. The cyclic blocks need to be integrated into
a single cyclic block that can be executed without an
explicit dynamic scheduler or a dispatcher. In this sec-
tion, we develop a novel scheme to integrate the given
cyclic blocks associated with different periods into a single
cyclic block. The integrated cyclic block is executed
indefinitely or semi-indefinitely until the program terminates

y
(d)
(a)
self
expansion
(b)
cycle-carried
(c)
intra-cycle
expansion
expansion
inter-cycle
expansion242424242424242135554
Figure

Cyclic block expansion of timing constraints.
be the cyclic blocks associated
with the periods that is, the execution of
the first temporal variable in block / i should be started
every p i . The re-arrangement of the cyclic blocks into
a single cyclic block \Psi is processed as follow using
the fundamental property of the scheduling of periodic
tasks [14].
1. Compute
the least common multiplier of the periods
2. 8i, replicate the instructions in / i for p=p i times.
3. 8i, expand the timing constraints. Notice that the
expansion is a simple addition of temporal expressions
in our model because dependence is a sub-type
of simple constraint. Define fl k
as the instruction
x in the k th instance of / i , say /
, and
as the original cyclic block associated with period
represents the instruction
x in / i . The constraint expansion is performed
based on the following analysis.
self expansion: The replicated instructions add
timing constraints to maintain the execution order
of those replicated instructions. At this ex-
pansion, the periodic constraint is enforced on the
first control action. Namely, 8i and 8j, a temporal
added where
x is the first control action in / i or
otherwise 3 . The graphical representation of self-
expansion is depicted in (a) of Figure 6 when instruction
is the first control action in / i .
cycle-carried expansion: Suppose fl k+1
is dependent
on
, say
0. In this case, the dependence is enforced for
each replica of / i , adding temporal expressions of
is applied to every cyclic-carried dependences and
shown in (b) of Figure 6. In the figure, fl k+1
uses
the result of fl k
thus, the temporal expression
of this relation is represented as
for
intra-cycle expansion: Temporal expressions
specifying the constraints between the instructions
in the same block are replicated as necessary.
That is, for
is added
in every replica of / i . In (c) of Figure 6, the temporal
replicated in
inter-cycle expansion: Temporal expressions
specifying the constraints between the instructions
beyond one block (not within a block) are
replicated as necessary. Let - k
be the starting
time of fl k
in / k
, Then, the range of - k
can
be expressed as
Thus, the inter-cycle temporal expression
yields the temporal expressions fl k
Consider (d) of Figure 6. When we assume that
3 We assume that p i
implies that the first control action in / i
should be repeated every p i
time units. The other instructions in
are correctly executed as long as the expanded dependences
are not violated.
expressions
are
added.
4. \Psi is scheduled by an instruction level fine-grain
scheduling algorithm. One of the approaches to
find a valid schedule by using a genetic search
based algorithm is given in [3].
Building a statically-scheduled real-time system is not
as difficult as it first appears - if we have an appropriate
real-time language and compiler technology. After
making significant strides towards the development
of the compiler technology, we believe that the key to
building the language is providing a very general model
which both the programmer and the compiler can easily
understand and manipulate. This paper has proposed
such a language. The basic features of this language
include:
ffl The basic syntax of a conventional language (in
this paper, C) and compatibility with that lan-
guage's programming idioms
ffl The ability to place relative timing constraints on
arbitrary pairs of fine-grain operations or on cyclic
blocks
ffl The ability to specify arbitrary types of relative
timing constraints (e.g., any of before, after, con-
current, and exclusive combined by either ANDing
or ORing).
Some of these features greatly complicate the com-
piler's job by enlarging the schedule search space or
by adding complexity to the evaluation of constraints.
However, we have made good progress toward solving
these problems, and nothing in the language lies far beyond
the ability of the new compiler technology we have
developed and implemented.
Current and future work centers on the implementation
of a complete compiler for this language: CHaRTS
(Compiler for Hard Real-Time Systems). The primary
focuses of the complete compiler are the control
structure analysis, the code scheduling based on high-precision
timing analysis, and the code generation for
both serial and parallel execution models.

Acknowledgement

This work is supported by the
Office of Naval Research (ONR) under grant number
N00014-91-J-4013.



--R

Compiler Principles
What is ADA?
Static scheduling of hard real-time code with instruction-level timing accuracy
The Refined-Language Approach to Compiling for Parallel Supercomputers
An Implementation of Purdue's Adapter for Parallel Execution and Rapid Synchronization.
Computers and Intractability

Scheduling tasks with and/or precedence constraints.
A multiprocessor language.
Texas Instruments Inc.
Unimate Industrial Robot Programming Manual

Implementation of RCCL
A note on pre-emptive scheduling of periodic real-time tasks
Expressing and Maintaining Timing Constraints in FLEX.
Software architecture for hard real-time applications: cyclic vs
Language Support for the Maruti Real-time Sys- tem
Reference Manual
Hard Real-Time Systems Tutorial

--TR
Compilers: principles, techniques, and tools
Real-time Euclid: a language for reliable real-time systems
The refined-language approach to compiling for parallel supercomputers
Second Generation TMS20 User''s Guide
Tutorial: hard real-time systems
reference manual
Software architecture for hard real-time applications
Computers and Intractability
Static scheduling of hard real-time code with instruction-level timing accuracy

--CTR
Mohamed F. Younis , Thomas J. Marlowe , Alexander D. Stoyen , Grace Tsai, Statically Safe Speculative Execution for Real-Time Systems, IEEE Transactions on Software Engineering, v.25 n.5, p.701-721, September 1999
hard real-time;timing constraint;CHaRTS;real-time language