2005-05-17 1
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
A Case Study on Partial Evaluation in Embedded Software
Design
Michael JungRalf Laue
Sorin Alexander Huss
Integrated Circuits and Systems LabDarmstadt University of Technology
2005-05-17 2
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Introduction
• Embedded systems software design: software generators help to achieve both resuability and efficiency
• Generators usually implemented by hand:– time-consuming and error-prone
• Implementing software generators with partial evaluation constitute way out
2005-05-17 3
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Overview
• Problem illustration• Introduction to basics
– OSEK– Partial Evaluation
• Implementation• Results
2005-05-17 4
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Problem Illustration
High Degree ofConfigurability
(Parameters, Indirections, ...)
Hard economical constraints led to the fact that embedded software is usually highly specialized for the application at hand and therefore not reusable
ConflictingGoals
Reusability EfficientImplementation
Hand Optimized andSpecialized Code
High Level ofAbstraction (e.g.OOP)
Low Level Machine-
Intimate Code
2005-05-17 5
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Binding Time of Parameters
• Parameterization happens at different times during product life cycle:
• Parameters bound to concrete values before run time are called static. Run time parameters are called dynamic
• This distinction is usually not exploited in reusable software modules
t
End of Assembly Line Time Run TimeDevelopment Time
e.g. bus bandwidth e.g. amount of fuel to inject
Configuration
2005-05-17 6
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Generative Programming
• Generative Programming takes advantage of static parameters– Domain Specific Language
• specifies static parameters at a high level of abstraction
– Generator• generates optimized code from generic components
Generator ImplementationComponents
TranslatorSpecification in a DSL
[2]
2005-05-17 7
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
OSEK OS - Generator
• OSEK is a specification for embedded OS (developed by university and automotive industry)
• Domain Specific Language for OSEK is OIL (OSEK Implementation Language)– OIL specifies features like number of tasks and
resources or level of error management
• Generator applies OIL specification and generates specialized code containing only needed functionality
2005-05-17 8
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
OSEK Generation Flow
Application Configuration
File (OIL)
optionalOSEK Builder
SystemGenerator
Files produced by
SG Compiler
Linker
Executable File
Executable File
OSEK OSKernel
Device Driver
User's source code
"C" code
"C" code"C" code
Object libraries
[1]
2005-05-17 9
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Shortcomings of Generators
• Generators are typically implemented by hand (e.g. OSEK)
• Verifying correctness of hand-written generators is hard
• Partial Evaluation promises some means of automation
2005-05-17 10
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
• A Partial Evaluator computes a Generator from– a generic parameterizable software module– a division of the parameters in static and dynamic ones
• Given concrete values for the static parameters this Generator computes a specialized software module exhibiting the same behaviour as the original program with the same inputs
Partial Evaluation
SpecializedProgram
GeneratorPartial Evaluator
GenericProgram
Divisonstatic vs.dynamic
parameters
static input
dynamicinput output
[3]
2005-05-17 11
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Partial Evaluation: Exampleint power(int x, unsigned n) { int r=1; while (n) { if (n&1) r=r*x; x=x*x; n=n>>1; } return r;}
x : dynamicn : static
void power_gen(unsigned n) { printf(„void power(int x, unsigned n) {\n“); printf(„ int r=1;\n“); printf(„ assert(n==%d);\n“, n); while (n) { if (n&1) printf(„ r=r*x;\n“); printf(„ x=x*x;\n“); n=n>>1; } printf(„ return r;\n}“);}
n = 3
void power(int x, unsigned n) { int r=1; assert(n==3); r=r*x; x=x*x; r=r*x; x=x*x; return r;}
2005-05-17 12
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Partial Evaluation: Advantages
• Generators are typically implemented by hand:– division of parameters in static and dynamic
ones is build into generator cannot easily be changed later on
– With Partial Evaluation generators for all 2P can automatically be synthesized
• Verifying correctness of hand-written generators is hard:– Assuming the Partial Evaluator is correct: only
the generic program has to be checked
2005-05-17 13
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Implementation – Basic Ideas
• OSEK-Implementation with C-Mix/II (which processes the complete C-syntax)
• C-Mix/II creates an OSEK-generator out of generic OS code
• Given the information specified in the OIL-file, this generator computes specialized OS code
• Instead of writing an own parser for OIL, we mapped OIL to XML and used an XML-parser
2005-05-17 14
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Implementation
• Two function-types have to be specialized:– Initialization-functions: creation(malloc) and
initialization of OS-data-structures– API-functions: include only the necessary code
paths for the chosen functionality
• For this, the functions get an additional parameter containing the XML-tree containing the OIL-information, which is static and will not be present in the specialized code
2005-05-17 15
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Implementation
Code to bespecialized
Generator
Partitionstatic/dynamic
OIL/XML
Compiler/Linker
SpecializedCode
General Code Application Code
Executable
C-Mix/II
M6
8K
i386
User written/designed
Part of OSEK-Implementation
3rd party tools
Text-file
Program
2005-05-17 16
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Example: Initialization
TaskRefType *OSEK_ready_queues_head;TaskRefType *OSEK_ready_queues_back;
void OSEK_init_ready_queue(xmlNodePtr config){ unsigned int *priority_mapping, maxPriority;
priority_mapping = create_priority_mapping(config); maxPriority = priority_mapping[max_priority(config)]+1; OSEK_ready_queues_head = malloc(sizeof(TaskRefType)*maxPriority); OSEK_ready_queues_back = malloc(sizeof(TaskRefType)*maxPriority); for (i=0; i<maxNeededPriority; i++) { OSEK_ready_queues_head[i] = INVALID_TASK; OSEK_ready_queues_back[i] = INVALID_TASK; } // for} // OSEK_init_ready_queue
TaskRefType *OSEK_ready_queues_head;TaskRefType *OSEK_ready_queues_back;
void OSEK_init_ready_queue(xmlNodePtr config){ unsigned int *priority_mapping, maxPriority;
priority_mapping = create_priority_mapping(config); maxPriority = priority_mapping[max_priority(config)]+1; OSEK_ready_queues_head = malloc(sizeof(TaskRefType)*maxPriority); OSEK_ready_queues_back = malloc(sizeof(TaskRefType)*maxPriority); for (i=0; i<maxNeededPriority; i++) { OSEK_ready_queues_head[i] = INVALID_TASK; OSEK_ready_queues_back[i] = INVALID_TASK; } // for} // OSEK_init_ready_queue
2005-05-17 17
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Example: Intialization
TaskRefType OSEK_ready_queues_head[3] =
{ INVALID_TASK, INVALID_TASK, INVALID_TASK };
TaskRefType OSEK_ready_queues_back[3] =
{ INVALID_TASK, INVALID_TASK, INVALID_TASK };
TaskRefType OSEK_ready_queues_head[3] =
{ INVALID_TASK, INVALID_TASK, INVALID_TASK };
TaskRefType OSEK_ready_queues_back[3] =
{ INVALID_TASK, INVALID_TASK, INVALID_TASK };
• Number of tasks > 3
• Exactly 3 different unique priorities were assigned to the tasks
• Gaps between priorities possible
2005-05-17 18
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Example: API-Function
StatusType InitMessage(
SymbolicName msg,
ApplicationDataRef data,
xmlNodePtr config)
{
read_COM_xml(config);
if (COM_cmix_use_parameter_access)
{
COM_error_last_message = msg;
COM_error_last_dataref = data;
} // if
if (COM_cmix_use_GetServiceId)
COM_error_last_service_called =
COMServiceId_InitMessage;
...
StatusType InitMessage(
SymbolicName msg,
ApplicationDataRef data,
xmlNodePtr config)
{
read_COM_xml(config);
if (COM_cmix_use_parameter_access)
{
COM_error_last_message = msg;
COM_error_last_dataref = data;
} // if
if (COM_cmix_use_GetServiceId)
COM_error_last_service_called =
COMServiceId_InitMessage;
...
if (COM_cmix_COMStatus_is_extended) { if ((msg < 0) || (msg >= COM_cmix_message_amount) || (COM_MessageStore[msg].type != RECEIVE_UNQUEUED)) { if (COM_cmix_user_error_hook && !COM_cmix_ErrorHook_is_active) { COM_cmix_ErrorHook_is_active = 1; COMErrorHook(E_COM_ID); COM_cmix_ErrorHook_is_active = 0; } // if return E_COM_ID; } // if } // if COM_MessageStorage[msg].content.\ receive_unqueued_internal.data=*data; return E_OK;} // InitMessage
if (COM_cmix_COMStatus_is_extended) { if ((msg < 0) || (msg >= COM_cmix_message_amount) || (COM_MessageStore[msg].type != RECEIVE_UNQUEUED)) { if (COM_cmix_user_error_hook && !COM_cmix_ErrorHook_is_active) { COM_cmix_ErrorHook_is_active = 1; COMErrorHook(E_COM_ID); COM_cmix_ErrorHook_is_active = 0; } // if return E_COM_ID; } // if } // if COM_MessageStorage[msg].content.\ receive_unqueued_internal.data=*data; return E_OK;} // InitMessage
2005-05-17 19
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Example: API-Function
StatusType InitMessage(SymbolicName msg,
ApplicationDataRef data)
{
if ((msg < 0) ||
(msg >= COM_cmix_message_amount) ||
(COM_MessageStorage[msg].type !=
RECEIVE_UNQUEUED))
{
return E_COM_ID;
} // if
COM_MessageStorage[msg].content.\
receive_unqueued_internal_data=*data;
return E_OK;
} // InitMessage
StatusType InitMessage(SymbolicName msg,
ApplicationDataRef data)
{
if ((msg < 0) ||
(msg >= COM_cmix_message_amount) ||
(COM_MessageStorage[msg].type !=
RECEIVE_UNQUEUED))
{
return E_COM_ID;
} // if
COM_MessageStorage[msg].content.\
receive_unqueued_internal_data=*data;
return E_OK;
} // InitMessage
Selected:
•No error reporting
•No error hooks
•Sanity checks
2005-05-17 20
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Result: Code Sizes
artifact before specialization
after specialization
standard mode
extended mode
source code 94,849 Byte 66,946 Byte 90,574 Byte
object code (i386)
44,424 Byte 15,244 Byte 22,084 Byte
object code (M68K)
N/A 19,804 Byte 22,676 Byte
artifact OSEK implementation
traditional C-Mix/II-based
flashable image 17,340 Byte 17,336 Byte
2005-05-17 21
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Results: Observed Weaknesses
Although the implementation was feasible, there were some problems, because of limited functionality of the used Partial Evaluator (C-Mix/II):• Reflection:
– Need to access objects (i.e., task functions) via their name– void* GetFuncPtr( const char* name)
• Cross partial evaluation:– Generator is executed on host machine, generating code
for embedded system hardware– Need for identical semantics on both machines
2005-05-17 22
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Results: Observed Weaknesses
• Code bloat:– Unrolling loops, different versions of one function– In our case: only elimination of unused code
• Function signatures:– Partial evaluator changes function signature
not desirable for reusable software modules
• No splitting of structs:– C-Mix/II: if any part of a struct is dynamic, whole
struct is dynamic
• Spaghetti code:– C-Mix/II: control flow implemented with goto
2005-05-17 23
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Conclusion
• Conclusion:– We consider partial evaluation a promising
approach to build efficient reusable software for embedded systems
– A couple of problems still have to be addressed with better tools
• Future Work:– Implementation of a Partial Evaluator considering
the domain of resource constrained embedded systems:
• Cross-Partial Evaluation• Code Bloat
2005-05-17 24
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Thanks for your attention
References[1] The OSEK Group: OSEK/VDX Operating System Version 2.2.2, July 2004[2] K. Czarnecki, U.W. Eisenecker: Generative Programming - Methods, Tools, and Applications,
Addison Wesley, 2000[3] N. D. Jones, C. K. Gomard, and P. Sestoft: Partial Evaluation and Automatic Program Generation,
Prentice Hall, 1993[4] R. Laue: Fallstudie: Implementierung von Software Generatoren mittels partieller Evaluierung,
TU Darmstadt, Diplomarbeit, November 2003[5] M. Jung, and S.A. Huss: Fast Points-to Analysis for Languages with Structured Types, SCOPES
2004, Springer LNCS 3199, 2004
Questions?
2005-05-17 25
ICS
INTEGRATEDCIRCUITS ANDSYSTEMS LABT
EC
HN
ISC
HE U
NIV
ER
SIT
ÄT D
AR
MSTA
DT
Result: Initialization
unsigned char heap_location_1[12];unsigned char heap_location_2[12];
TaskRefType *OSEK_ready_queues_head;TaskRefType *OSEK_ready_queues_back;
void OSEK_init_ready_queue(){ OSEK_ready_queues_head = heap_location_1; OSEK_ready_queues_back = heap_location_2; OSEK_ready_queues_head[0] = INVALID_TASK; OSEK_ready_queues_back[0] = INVALID_TASK; OSEK_ready_queues_head[1] = INVALID_TASK; OSEK_ready_queues_back[1] = INVALID_TASK; OSEK_ready_queues_head[2] = INVALID_TASK; OSEK_ready_queues_back[2] = INVALID_TASK;} // OSEK_init_ready_queue
unsigned char heap_location_1[12];unsigned char heap_location_2[12];
TaskRefType *OSEK_ready_queues_head;TaskRefType *OSEK_ready_queues_back;
void OSEK_init_ready_queue(){ OSEK_ready_queues_head = heap_location_1; OSEK_ready_queues_back = heap_location_2; OSEK_ready_queues_head[0] = INVALID_TASK; OSEK_ready_queues_back[0] = INVALID_TASK; OSEK_ready_queues_head[1] = INVALID_TASK; OSEK_ready_queues_back[1] = INVALID_TASK; OSEK_ready_queues_head[2] = INVALID_TASK; OSEK_ready_queues_back[2] = INVALID_TASK;} // OSEK_init_ready_queue