7th Biennial Ptolemy Miniconference
Berkeley, CAFebruary 13, 2007
Partial evaluation for optimized compilation of
actor-oriented models
Gang Zhou, Man-Kit Leung and Edward A. Lee with contributions from Christopher Brooks and Ye Zhou
Zhou, Leung, Lee 2
Goals
• Design of embedded system based on understandable concurrency formalism– Provide appropriate abstraction level– Provide useful modeling properties– Easy to reason about and guarantee
correctness– Yield static analyzability
• Automatically derive efficient implementation based on partial evaluation – Generate semantically equivalent code– Performance close to manually written
code
Designs expressed through programming model
Implementations
Functions, requirements, specifications
Partial evaluation
Zhou, Leung, Lee 3
How embedded software has been traditionally written
• Assembly language is used to maximize efficiency and predictability
• C is used to improve productivity and portability• Threads are used as concurrency formalism provided
by underlying operating system• Very low level mechanisms (e.g., mutual exclusion
locks) are used for synchronization
Problem: Interacting threads are not compositional, therefore they are difficult to reason about and guarantee correctness.
Solution: We need alternative concurrency formalisms to match the abstractions with the embedded applications.
Zhou, Leung, Lee 4
Actor-oriented design: a formalized model of concurrency
produceractor
consumeractor
IOPort
Receiver
Director object oriented actor oriented
• Actor-oriented design hides the states of each actor and makes them inaccessible from other actor
• The emphasis of data flow over control flow leads to conceptually concurrent execution of actors
• The interaction between actors happens in a highly disciplined way • Threads and mutexes become implementation mechanism instead of part of
programming model
Zhou, Leung, Lee 5
Simulink: time-based block diagram
• Physical plant is modeled by continuous time dynamics• Controller is modeled by discrete time system• Real-Time Workshop (RTW) is used for code generation
Zhou, Leung, Lee 6
Embedded system needs decidable formalism
• Decidable formalism yields static analyzability– Avoid deadlock– Bound on memory consumption– Bound on execution time– ….
• Some examples with decidable formalism– Synchronous dataflow (SDF) (Lee and Messerschmitt)– Cyclo-static dataflow (CSDF) (Bilsen et al.)– FORTRAN before 90– Synchronous languages (Berry et al., Halbwachs et al.,
Guernic et al.)
Zhou, Leung, Lee 7
From SDF to modal models
• Synchronous dataflow (SDF): a decidable MoC amenable to static analysis
rA rB
Balance equation: fArA = fBrB
A B
rA = 2 rB = 3 => fA = 3 fB = 2
Schedule (for one complete iteration):
• AAABB
• AABAB
• We want to augment SDF to describe dynamic behavior in a convenient, compact and understandable way
(Each actor has fixed rate)
(Each refinement can have different rate)
Refinement ARefinement B
Refinement C
Zhou, Leung, Lee 8
Heterochronous Dataflow (HDF)= SDF + FSM + transition constraints(Girault, Lee, Lee, 97)
HDF
HDFSDF
SDF SDF
SDF SDF
HDFFSM HDFFSM
HDFFSM
Constraint:
State transitions are only allowed to be taken when the model completes one iteration (i.e., one complete SDF schedule) in the given state.
Consequence:
HDF retains static analyzability due to the nature of the FSM.
Zhou, Leung, Lee 9
Execution trace and configurations
State transitions
Between state transitions, the model is in a well-defined configuration represented by a single SDF model
Configuration i Configuration i+1 Configuration i+2 Configuration i+3 Configuration i+4…… ……
The code generation framework provides a systematic way to statically analyze and derive all possible configurations for a given model.
Zhou, Leung, Lee 10
Ptolemy II: a software lab for experimenting with multiple concurrency formalisms
Observation: great as a prototyping environment, but the resulting inefficiency induced by indirection overhead is unacceptable for embedded system implementation.
•Generic components
•Well-defined interface
•Highly specialized components
•No communication overhead
Design Implementation
Solution:
Partial evaluation based compilation (code generation).
Zhou, Leung, Lee 11
Partial evaluation and automatic program generation (Jones, Gomard, Sestoft 1993)
)2in,1in(t<)2in(t+)1in,p(t ppmix 1in
static input in1
subject program p
dynamic input in2
partial evaluator “mix”
residual program Pin1
output
)2in,1in(t<)2in(t pp 1in
run time program generation:
compile time program generation:
: data : program
Zhou, Leung, Lee 12
Partial evaluation in practice
• General purpose software– Functional language (Bondorf 1989, Gomard and Jones 1989)– Logic language (Lloyd and Shepherdson 1991)– Imperative language (Anderson 1994)– Object-oriented language (Schultz 1999)
• Embedded software– The click model: optimizations for modular router configurations Optimization tools: click-fastclassifier, click-devirtualize, click-xform, click-undead
(Kohler et al., 2002, MIT)– The Koala Component Model for Consumer Electronics Software
(Ommering et al., 2000, Philips Research Lab)
Zhou, Leung, Lee 13
My approach: partial evaluation for actor-oriented programs
execution context:data types, buffer sizes,schedules, parameters, model structure, etc.
model (actor-oriented program)
input
partial evaluator(code generator)
monolithic and efficient executable
output
model analysis
highly optimizedtarget code blocks
cod
e gen
eration
target code execution
: data : program
Zhou, Leung, Lee 14
Realization of partial evaluation with helper-based mechanism
• Each actor has a corresponding helper class which is responsible for generating the target code for that actor under the given execution context.
• Each director (which is responsible for governing the interaction between actors) has a corresponding helper class for providing MoC-specific information and orchestrating the code generation for the model.
• The helper class hierarchy and package structure parallel those of the corresponding actors, to achieve modularity, maintainability, portability, efficiency and extensibility in code generation.
Actor Actor helper
Director Director helper
Zhou, Leung, Lee 15
Com ponentEntityCom positeEntity
Atom icActor
Com positeActor
0..10 ..n
« In te rface»Actor
+getD irec to r() : D irec to r+ge tE xecutiveD irec to r() : D irec to r+ge tM anager() : M anager+ inputP ortL is t() : L is t+new R ece iver() : R ece iver+ou tpu tP ortL is t() : L is t
«In te rface»Executable
+fire ()+ in itia lize ()+pos tfire () : boo lean+pre fire () : boo lean+pre in itia lize ()+s topF ire ()+ te rm ina te()+w rapup()
Director
Key classes in helper-based mechanism
Key classes that support actor execution Key classes that support code generation
Key points:1. The helper based-mechanism preserves the actor interface (ports and parameters).
Each helper discovers the interface by “interrogating” its associated actor.2. It realizes code generation for multiple MoC by using the associated director helper
for the corresponding director.3. It realizes code generation for multiple target languages by using corresponding set
of actor helpers.
Zhou, Leung, Lee 16
Actor and helper libraries
Actor libraries Helper classesptolemy.actor.lib
AbsoluteValueAccumulatorAddSubtractAverageBernoulliCommutatorConstCounterDifferentialDiscardElementsToArrayGaussianGradientAdaptivelatticeLimiterLookupTableMaximumMinimumMonitorValueMultiplyDividePulseQuantizerRampRemainder…………
ptolemy.codegen.c.actor.lib
AbsoluteValueAccumulatorAddSubtractAverageBernoulliCommutatorConstCounterDifferentialDiscardElementsToArrayGaussianGradientAdaptivelatticeLimiterLookupTableMaximumMinimumMonitorValueMultiplyDividePulseQuantizerRampRemainder…………
ptolemy.actor.lib.comm
HammingCoderHammingDecoder…………
ptolemy.actor.lib.conversion
ptolemy.actor.lib.gui
ptolemy.actor.lib.logic
BooleanToAnythingCartesianToPolar…………
DisplaySequencePlotter…………
EqualsLogicFunction…………
ptolemy.codegen.c.actor.lib.comm
HammingCoderHammingDecoder…………
ptolemy.codegen.c.actor.lib.gui
ptolemy.codegen.c.actor.lib.logic
BooleanToAnythingCartesianToPolar…………
DisplaySequencePlotter…………
ptolemy.codegen.c.actor.lib.conversion
EqualsLogicFunction…………
Zhou, Leung, Lee 17
Director and helper libraries
Directors and domain-specific actors Helper classes
ptolemy.domains.fsm.kernel
FSMActorFSMDirectorMultirateFSMDirector
HDFDirectorHDFFSMDirector
SDFDirector
ptolemy.domains.fsm.modal
ModalControllerModalModelRefinementTransitionRefinement
ptolemy.domains.hdf.kernel
ptolemy.domains.sdf.kernel
RepeatSampleDelay
ptolemy.domains.sdf.lib
ptolemy.codegen.c.domains.fsm.kernel
FSMActorFSMDirectorMultirateFSMDirector
HDFDirectorHDFFSMDirector
SDFDirector
ptolemy.codegen.c.domains.fsm.modal
ModalControllerModalModelRefinementTransitionRefinement
ptolemy.codegen.c.domains.hdf.kernel
ptolemy.codegen.c.domains.sdf.kernel
RepeatSampleDelay
ptolemy.codegen.c.domains.sdf.lib
Zhou, Leung, Lee 18
A simple helper example
Actor: ptolemy.actor.lib.Ramp (in Java)
Helper java class: ptolemy.codegen.c.actor.lib.Ramp (in Java)
C code template file: ptolemy.codegen.c.actor.lib.Ramp.c/***preinitBlock***/ static int $actorSymbol(state);/**/
/***initBlock***/ $actorSymbol(state) = $val(init);/**/
/***fireBlock***/ $ref(output) = $actorSymbol(state); $actorSymbol(state) += $val(step);/**/
Zhou, Leung, Lee 19
A flow chart for the code generation process
Generate Include files. These files include, e.g., math.h, stdio.h, needed by some actors in their generated code.
Generate shared code.The shared code includes macro definitions, new data type definitions, function definitions, etc.
Generate preinitialize code.
These are variables that are directly modified by actors, e.g., during mode transition.Collect modified
variables.
Create offset variables.
Generate initialize code.
Generate body code.
Generate wrapup code.
Generate variable definitions.
New variables other than those resulting from ports and parameters could be defined here.
These offset variables are used to record the circular buffer positions during code generation.
Variables are initialized here. Make sure the code generated here can be executed multiple times, e.g., after a reset transition in a FSM.
The code generated here performs major functions, corresponding to actor firings.
The code generated here does some wrapup work, e.g., closing open files.
These variables are those resulting from ports and parameters. Some can only be determined after the code generation is complete.
The code generated here is necessary to support dynamic type conversion.Generate type-conversion code.
Zhou, Leung, Lee 20
Advantages of helper-based code generation framework
• A flexible and extensible framework– new actors and helpers, new directors and helpers, new
target language
• seamless integration between the specification and simulation phase and the code generation phase
• code generation framework functions as a coordination language – leverage the huge legacy code repository – leverage many years and many researchers’ work on
compiler optimization techniques for the target language– accessible to the huge base of programmers – generated code is (semi-)human readable
Zhou, Leung, Lee 21
Partial evaluation based code generation in action
Zhou, Leung, Lee 22
Partial evaluation based code generation in action
#include <stdio.h>static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;static double _model_ModalModel_state2_Scale_input[3];static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) { switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input; _model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input; _model_ModalModel_state2_output[0] = 4 * _model_ModalModel_state2_Scale_input[0]; _model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; ………….. case 1: ................. _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input; _model_ModalModel_state1_output = _model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3; ............... } if (_model_ModalModel_fired) { switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) { _model_ModalModel_state1_scaleFactor_ = _model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1; } break; case 1: if (true) { _model_ModalModel__Controller_currentState = 0; _model_ModalModel_currentConfiguration = 0; } break; } _model_ModalModel_fired = 0; }. ................
Zhou, Leung, Lee 23
Partial evaluation based code generation in action
#include <stdio.h>
static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;static double _model_ModalModel_state2_Scale_input[3];static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) { switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input; _model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input; _model_ModalModel_state2_output[0] = 4 * _model_ModalModel_state2_Scale_input[0]; _model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; ………….. case 1: ................. _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input; _model_ModalModel_state1_output = _model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3; ............... } if (_model_ModalModel_fired) { switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) { _model_ModalModel_state1_scaleFactor_ = _model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1; } break; case 1: if (true) { .................
init: 0.0
step: 1.0
data type
memory allocation
Zhou, Leung, Lee 24
Partial evaluation based code generation in action
#include <stdio.h>static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;static double _model_ModalModel_state2_Scale_input[3];static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) { switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input;
_model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input;
_model_ModalModel_state2_output[0] = 4 * _model_ModalModel_state2_Scale_input[0]; _model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; .............. case 1: ............... _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input; _model_ModalModel_state1_output = _model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3; ............... } if (_model_ModalModel_fired) { switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) { _model_ModalModel_state1_scaleFactor_ =_model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1;
static parameter
Zhou, Leung, Lee 25
Partial evaluation based code generation in action
#include <stdio.h>
static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;static double _model_ModalModel_state2_Scale_input[3];static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) { switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input; _model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input; _model_ModalModel_state2_output[0] = 4 * _model_ModalModel_state2_Scale_input[0]; _model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; ………….. case 1: ................. _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input;
_model_ModalModel_state1_output =_model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3; ............... } if (_model_ModalModel_fired) { switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) {
_model_ModalModel_state1_scaleFactor_ = _model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1; } break; case 1:
dynamic parameter
Zhou, Leung, Lee 26
Partial evaluation based code generation in action
#include <stdio.h>static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;static double _model_ModalModel_state2_Scale_input[3];static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) { switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input;
_model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input;
_model_ModalModel_state2_output[0] = 4 *_model_ModalModel_state2_Scale_input[0];
_model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; .............. case 1: ............... _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input; _model_ModalModel_state1_output = _model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3; ............... } if (_model_ModalModel_fired) { switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) { _model_ModalModel_state1_scaleFactor_ =_model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1;
model structure
Zhou, Leung, Lee 27
Partial evaluation based code generation in action
#include <stdio.h>static double _model_ModalModel_state1_scaleFactor_;static double _model_ModalModel_state2_input;static double _model_ModalModel_state2_output[3];static double _model_ModalModel_state2_Repeat_input;
static double _model_ModalModel_state1_input;static double _model_ModalModel_state1_output;static int _model_currentConfiguration;static int _model_ModalModel_output_readoffset = 0;static int _model_ModalModel_output_writeoffset = 0;static int iteration = 0;.................main(int argc, char *argv[]) { _model_ModalModel_state1_scaleFactor_ = 1; _model_ModalModel_currentConfiguration = 1; _model_currentConfiguration = 0 + _model_ModalModel_currentConfiguration * 1 + 0; /* Static schedule: */ for (iteration = 0; iteration < 4; iteration ++) {
switch (_model_currentConfiguration) { case 0: _model_ModalModel_input = _model_Ramp_state; _model_Ramp_state += 1.0; _model_ModalModel__Controller_input = _model_ModalModel_state2_input = _model_ModalModel_input; _model_ModalModel_state2_Repeat_input = _model_ModalModel_state2_input; _model_ModalModel_state2_Scale_input[0] = _model_ModalModel_state2_Scale_input[1] = _model_ModalModel_state2_Scale_input[2] = _model_ModalModel_state2_Repeat_input; _model_ModalModel_state2_output[0] = 4 * _model_ModalModel_state2_Scale_input[0]; _model_ModalModel_state2_output[1] = 4 * _model_ModalModel_state2_Scale_input[1]; _model_ModalModel_state2_output[2] = 4 * _model_ModalModel_state2_Scale_input[2]; …………..
case 1:
................. _model_ModalModel_state1_Scale_input = _model_ModalModel_state1_input; _model_ModalModel_state1_output = _model_ModalModel_state1_scaleFactor_ * _model_ModalModel_state1_Scale_input; _model_ModalModel_output[(_model_ModalModel_output_writeoffset + 0)&3] = _model_ModalModel__Controller_output[(_model_ModalModel__Controller_output_writeoffset + 0)&3] = _model_ModalModel_state1_output; _model_ModalModel_output_writeoffset = (_model_ModalModel_output_writeoffset + 1)&3; _model_ModalModel__Controller_output_writeoffset = (_model_ModalModel__Controller_output_writeoffset + 1)&3;} if (_model_ModalModel_fired) {
switch (_model_ModalModel__Controller_currentState) { case 0: if ((_model_ModalModel__Controller_input > 0)) { _model_ModalModel_state1_scaleFactor_ = _model_ModalModel__Controller_input; _model_ModalModel__Controller_currentState = 1; _model_ModalModel_currentConfiguration = 1; } break;
case 1: if (true) { _model_ModalModel__Controller_currentState = 0;
MoC-specific scheduling
firing sequence
firing sequence
state transition
Zhou, Leung, Lee 28
Performance
Number of iteration
Time(s)
Ptolemy II 103 0.53
c 106 0.75
Number of iteration
Time(s)
Ptolemy II 105 0.33
c 108 0.34
Number of iteration
Time(s)
Ptolemy II 103 0.23
c 106 0.44
Ratio of time per iteration
970
Ratio of time per iteration
520
Ratio of time per iteration
710
Zhou, Leung, Lee 29
Future direction
• Explore code generation for other MoCs suited for embedded system design and for other target languages (e.g., VHDL)
• Integrate code generation with PTIDES: a time-synchronized distributed run time environment
Zhou, Leung, Lee 30
Conclusion
• The partial evaluation based compilation (code generation) framework provides a rapid path from a design environment with understandable concurrency formalism to efficient implementation
• HDF formalism balances the need for schedulability analysis for embedded software and the more expressive support of modal behavior
• Combined with timed MoC (DE-variant), we can realize a run time environment with precise timing control