260 likes | 452 Views
A Case Study on Partial Evaluation in Embedded Software Design. Michael Jung Ralf Laue Sorin Alexander Huss Integrated Circuits and Systems Lab Darmstadt University of Technology. Introduction.
E N D
A Case Study on Partial Evaluation in Embedded Software Design Michael Jung Ralf Laue Sorin Alexander Huss Integrated Circuits and Systems Lab Darmstadt University of Technology
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
Overview • Problem illustration • Introduction to basics • OSEK • Partial Evaluation • Implementation • Results
Problem Illustration Reusability Efficient Implementation High Degree of Configurability (Parameters, Indirections, ...) Conflicting Goals Hand Optimized and Specialized Code Low Level Machine- Intimate Code High Level of Abstraction (e.g.OOP) Hard economical constraints led to the fact that embedded software is usually highly specialized for the application at hand and therefore not reusable
Development Time End of Assembly Line Time Run Time t e.g. bus bandwidth e.g. amount of fuel to inject 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 Configuration
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 Translator Specification in a DSL Generator Implementation Components [2] Generative Programming
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
OSEK Generation Flow optional OSEK Builder [1] Application Configuration File (OIL) "C" code User's source code System Generator OSEK OS Kernel Files produced by SG "C" code "C" code Compiler Object libraries Linker Device Driver Executable File
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
static input GenericProgram Generator Partial Evaluator Divisonstatic vs.dynamicparameters dynamicinput SpecializedProgram output [3] Partial Evaluation • 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
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}“); } 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; } Partial Evaluation: Example x : dynamic n : static int power(int x, unsigned n) { int r=1; while (n) { if (n&1) r=r*x; x=x*x; n=n>>1; } return r; } n = 3
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
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
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
Implementation User written/designed Code to be specialized i386 3rd party tools Part of OSEK-Implementation C-Mix/II Partition static/dynamic Text-file Program Generator OIL/XML Specialized Code General Code Application Code M68K Compiler/Linker Executable
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[3] = { INVALID_TASK, INVALID_TASK, INVALID_TASK }; TaskRefType OSEK_ready_queues_back[3] = { INVALID_TASK, INVALID_TASK, INVALID_TASK }; Example: Intialization • Number of tasks > 3 • Exactly 3 different unique priorities were assigned to the tasks • Gaps between priorities possible
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; ... 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
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 • Selected: • No error reporting • No error hooks • Sanity checks
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
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
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
Thanks for your attention Questions? 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
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