Changes between Version 2 and Version 3 of ObjectDeveloperGuide

Show
Ignore:
Timestamp:
12/19/08 17:39:23 (16 years ago)
Author:
ismael (IP: 147.83.118.226)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ObjectDeveloperGuide

    v2 v3  
    1414And produces the following behavior: 
    1515 
    16  * Given a set of parameter values, the object will produce an output set of streams when an input set of streams is placed at input interfaces within the defined resource utilization constraints. 
    17  
    18 == [[BR]]Object structure == 
    19 .h + .c + directory structure 
     16 * The object reads once the initialization parameters and configures its behavior. 
     17 * Given a set of parameter values, the object produces an output set of streams as a function of an input set of streams within the defined resource utilization constraints. 
     18 
     19== [[BR]]Defining an Object == 
     20Given the previous definition of an object, we define a directory structure for its implementation in order to homogenize objects from several sources and to access easily to useful information. Generating a new object should follow this layout: 
     21 
     22||'''File/Directory'''||'''Comment'''|| 
     23||''myobj''/interf/||A file with name ''interface_name.h'' for each input and output interface defining the used data structure and in case of input ones, an explanation of the object behavior given that input. [[BR]][[BR]]See example: input.h control.h|| 
     24||''myobj''/src/||The source code of your object. Among others, the principal one (where the main() is) with the name ''myobj.c''|| 
     25||''myobj''/bin/||Binaries after compilation and linking are placed here.|| 
     26||myobj/props/||'''Under Work: '''A file with name ''resources.conf ''specifying demanded resource utilization given certain parameters and a file with name ''parameters.conf'' defining the set of initialization parameters and its behavior.|| 
     27||myobj/Makefile||For compilation|| 
    2028 
    2129==  == 
    22 == [[BR]]Implementing the Object == 
    23 estructura del .c 
     30==  == 
     31==  == 
     32== Implementing the Object == 
     33Once your object has been properly defined, you can begin implementing its behavior. Here we assume the reader is familiar with basic ALOE concepts, nevertheless, this section describes how to implement an ALOE Object and provides some examples. 
     34 
     35===  === 
     36=== Process Structure === 
     37All the tasks a radio application shall realize must follow the following simple function structure: 
     38 
     39{{{ 
     40“Check message, if any present -> 
     41Dispatch the task -> 
     42Return” 
     43}}} 
     44Figure 1 represents this concept. Notice how the object must announce its presence to ALOE prior to receive any order. 
     45 
     46The first order the object will receive will be to initialize (INIT) itself. Then, the object will read a set of initialization parameters, activate the communications interfaces and declare a set of statistics variables (for monitoring purposes). This procedure is executed just once in the lifecycle of the object. 
     47 
     48If an execution order is received (RUN), the object will receive any pending message, dispatch the required task (for example process a block of data received from an interface and send the result through another interface) and return to the initial point. 
     49 
     50The last case is the reception of the order to close (STOP) the object. In such case, the object must tell to ALOE to close all the allocated resources and finish its execution. 
     51 
     52Note how the object owns the CPU during the time it process the message. After that, the object returns to the STATUS point handing the CPU over to ALOE again. In anomalous or time rules violation, ALOE may release the ownership from the object before returning to the STATUS point. 
     53 
     54'''Figure 3.1 – P-HAL Object Flow Diagram''' 
     55 
     56=== Coding an Object === 
     57The programming language used to describe an object may change between different processing devices, depending on the tools provided by the device manufacturer. However, it would be very interesting to use always the same language so the code can be reused. This is unrealistic, because currently programmable devices as GPP or DSP can use C/C++ while others like logic programmable devices as FPGA use totally different languages (VHDL). 
     58 
     59Nevertheless, these are the chosen standard programming language for the P-HAL Framework: 
     60 
     61 * C Language for programmable devices 
     62 
     63 * VHDL Language for FPGA devices 
     64 
     65Not only the use of a standard language is a requirement to enable the whole set of functionalities provided by ALOE. Also the use of the ALOE Software Library API is a requirement as well as other considerations. 
     66 
     67An Object writer must be concerned about the misinformation of the final platform to be executed on. This means that very important concepts (in software radio) like sampling frequency, time slot duration, memory distribution or architecture, etc. are totally unknown when objects are designed. Thus, it would need to support such sort of frequency ranges and architectures under parameter reconfigurations. 
     68 
     69A special function provided by the ALOE Software Library API will serve for this purpose. The number of samples to be generated every time the object is executed (every time slot) will be obtained using the following function: 
     70 
     71{{{ 
     72int GetTempo(float freq); 
     73}}} 
     74This function receive has a parameter the frequency the object desires to operate. As the environment (ALOE) is the only who knows the execution interval associated to the process, a simply operation will be done to calculate the number of samples to be generated at that precise moment. The amount of samples that the object needs at its input will depend on the algorithm, more precisely, in the rate relation between the input and output frequency. Anyway, the object will wait until all the data it needs is available. Note that this could lead to time violations if frequency relations between collateral objects are not defined with caution. 
     75 
     76The following concepts should be taken into account when designing an object: 
     77 
     78 * Sampling frequency and time slot is unknown: the length of input and         output packet (packet length over time slot duration equals sampling         frequency) should be allowed to change and should be limited. 
     79 
     80 * Our goal is to write to the output interface certain number of         samples (!GetTempo()) each execution cycle (time-slot) ensuring a         constant mean sampling frequency along time. 
     81 
     82 * Processing time over data unit (cycles/sample) should be taken into         account when defining the required processing resources depending on         the operating frequency. 
     83 
     84 * The format of the input and output data has to be well defined         (integers, short, signed/unsigned, etc.). 
     85 
     86 * If control data must be received, another interface '''different         '''from the data in/out interfaces should be used, in such case, an         struct may be defined to receive such parameters. 
     87 
     88 * The values acquired from parameters initialization should always be         checked, to ensure they follow our local limitations (i.e. buffer         sizes). 
     89 
     90 * '''Always''' define constants as compiler constant definitions         (#define …).         This facilitates code reusing and maintenance. 
     91 
     92The following example provides a template of the main object file named, conventionally, as ''myobj.c''. Notice how we first include definition files for each interface we are going to use and the header files for ALOE API utilization. Then, we fall to an infinite loop where we continuously check for an status and execute it, then, we relinquish the cpu. 
     93 
     94'''Figure 2 – Main example source (myobj.c)''' 
     95 
     96{{{ 
     97/** ALOE headers 
     98 */ 
     99#include <phal.h> 
     100#include <phal_sw_api.h> 
     101 
     102#include "input.h"      /**< Definition of interface 'input' */ 
     103#include "control.h"    /**< Definition of interface 'control' */ 
     104#include "output.h"     /**< Definition of interface 'output' */ 
     105 
     106/** Main 
     107 */ 
     108void main() { 
     109 
     110        int status; 
     111 
     112        switch(status) { 
     113        case PHAL_STATUS_INIT: 
     114                /** Call INITIALIZATION function */ 
     115                if (!Init()) { 
     116                        ClosePHAL(); 
     117                        exit(0); 
     118                } 
     119                break; 
     120        case PHAL_STATUS_RUN: 
     121                /** Call RUN function */ 
     122                if (!Run()) { 
     123                        ClosePHAL(); 
     124                        exit(0); 
     125                } 
     126                break; 
     127        default: 
     128                /** rest, is STOP */ 
     129                ClosePHAL(); 
     130                exit(0); 
     131                break; 
     132        } 
     133        Relinquish(); 
     134} 
     135}}} 
     136Now following figures shows the content of input.h output.h and control.h here control is an interface to modify object behavior. '''NOTE '''the difference between this control variables and the initialization parameters: any the input we provide to this control interface will produce a change in the object behavior (reconfiguration) '''within '''the time/memory specifications. That means, for example, that certain reconfigurations, lets say, compute filter coeficients may not be realized inside the time window producing a real time failure, thus can not be performed during the execution (RUN) phase (should be realized during the initialization phase, as an initialization parameter). 
     137 
     138'''Figure 3 – Interface example definitions (input.h)''' 
     139 
     140{{{ 
     141/** Interface Name: input 
     142 *   
     143 *  Data type: 32-bit signed integer 
     144 *  Max input size: 1024 elements 
     145 *  Min input size: 128 elements 
     146 *   
     147 *  Description: Input stream of data 
     148 */ 
     149 
     150#define INPUT_MAX_DATA  1024     
     151#define INPUT_MIN_DATA  128 
     152 
     153struct input_itf { 
     154        int data[INPUT_MAX_DATA]; 
     155}; 
     156 
     157 
     158}}} 
     159'''Figure 4 – Interface example definitions (output.h)''' 
     160 
     161{{{ 
     162/** Interface Name: output 
     163 *   
     164 *  Data type: 16-bit signed integer 
     165 *  Max output size: 2048 elements 
     166 *  Min output size: 256 elements 
     167 *   
     168 *  Description: Output stream of data 
     169 */ 
     170 
     171#define OUTPUT_MAX_DATA 2048     
     172#define OUTPUT_MIN_DATA 256 
     173 
     174struct output_itf { 
     175        short data[OUTPUT_MAX_DATA]; 
     176}; 
     177 
     178 
     179}}} 
     180'''Figure 5 – Interface example definitions (control.h)''' 
     181 
     182{{{ 
     183/** Interface Name: control 
     184 *   
     185 *  Data type: Structure (see below) 
     186 *  Max input size: 1 element 
     187 *  Min input size: 1 element 
     188 *   
     189 *  Description: Configures the behavior of the object etc. etc. 
     190 */ 
     191 
     192#define CONTROL_MAX_DATA        1        
     193#define INPUT_MIN_DATA          1 
     194 
     195struct control_itf { 
     196        unsigned char modulation_type; 
     197        short modulation_levels; 
     198        int roll_factor; 
     199}; 
     200 
     201 
     202}}} 
     203Finally, the following figure shows where actually the user code should be written. We provide here an skeleton to easy the deployment of new    
     204 
     205#define DATA_OUT_SZ        128 
     206 
     207#define FIR_COEF_SZ 12 
     208 
     209/* frequency in/out rate */ 
     210 
     211#define DATA_INOUT_RATE        1 
     212 
     213int data_in[DATA_IN_SZ],data_out[DATA_OUT_SZ]; 
     214 
     215int fir_coef[FIR_COEF]; 
     216 
     217int fdi,fdo; 
     218 
     219int rcv_len; 
     220 
     221int long_block; 
     222 
     223int nof_coef; 
     224 
     225float freq; 
     226 
     227int stat_outsignal; 
     228 
     229/** Init function 
     230 
     231* @return 1 if ok, 0 if error 
     232 
     233*/ 
     234 
     235int Init() 
     236 
     237{ 
     238 
     239fdi = !NewFlow(“input”, FLOW_READ_ONLY); 
     240 
     241if (fdi < 0) { 
     242 
     243!WriteLog(“Error creating flow\n”); 
     244 
     245return 0; 
     246 
     247} 
     248 
     249fdo = !CreateFlow(“output”, FLOW_WRITE_ONLY); 
     250 
     251if (fdo < 0) { 
     252 
     253!WriteLog(“Error creating flow\n”); 
     254 
     255return 0; 
     256 
     257} 
     258 
     259n = !InitParamFile(); 
     260 
     261if (n < 0) { 
     262 
     263!WriteLog (“Error initiating params file\n”); 
     264 
     265return 0; 
     266 
     267} 
     268 
     269n = !GetParameter(“freq”, &freq, 1); 
     270 
     271if (n < 0) { 
     272 
     273!WriteLog (“Error getting parameter\n”); 
     274 
     275return 0; 
     276 
     277} 
     278 
     279n = !GetParameter(“nof_coef”, &nof_coef, 1); 
     280 
     281if (n < 0) { 
     282 
     283!WriteLog (“Error getting parameter\n”); 
     284 
     285return 0; 
     286 
     287} 
     288 
     289if (nof_coef > FIR_COEF_SZ) { 
     290 
     291!WriteLog (“Error getting parameter, too long\n”); 
     292 
     293return 0; 
     294 
     295} 
     296 
     297memset(fir_coef, 0, FIR_COEF_SZ * 4); 
     298 
     299n = !GetParameter(“fir_coef”, fir_coef, nof_coef); 
     300 
     301if (n < 0) { 
     302 
     303!WriteLog (“Error getting parameter\n”); 
     304 
     305return 0; 
     306 
     307} 
     308 
     309n = !InitStatsFile(); 
     310 
     311if (n < 0) { 
     312 
     313!WriteLog (“Error initiating stats\n”); 
     314 
     315return 0; 
     316 
     317} 
     318 
     319stat_outsignal = !InitStat(“out_signal”); 
     320 
     321if (stat_outsignal < 0) { 
     322 
     323!WriteLog (“Error initiating stat\n”); 
     324 
     325return 0; 
     326 
     327} 
     328 
     329rcv_len = 0; 
     330 
     331return 1; 
     332 
     333} 
     334 
     335/** Run function. 
     336 
     337* @return 1 if ok, 0 if error 
     338 
     339*/ 
     340 
     341int Run() 
     342 
     343{ 
     344 
     345/* Get number of samples to generate in current timeslot only if last block is already send*/ 
     346 
     347if (rcv_len == 0) { 
     348 
     349long_block = !GetTempo(freq); 
     350 
     351if (long_block > DATA_OUT_SZ) { 
     352 
     353!WriteLog(“Error requested tempo exceeds output buffer.\n”); 
     354 
     355return 0; 
     356 
     357} 
     358 
     359if (long_block * DATA_INOUT_RATE > DATA_IN_SZ) { 
     360 
     361!WriteLog(“Error requested tempo exceeds input buffer.\n”); 
     362 
     363return 0; 
     364 
     365} 
     366 
     367} 
     368 
     369/* receive a block of data */ 
     370 
     371do { 
     372 
     373n = !ReadFlow(fdi, data_in, long_block / DATA_INOUT_RATE - rcv_len); 
     374 
     375if (n < 0) { 
     376 
     377!WriteLog(“Error reading from flow\n”); 
     378 
     379return 0; 
     380 
     381} else if (!n) { 
     382 
     383break; 
     384 
     385} 
     386 
     387rcv_len += n; 
     388 
     389} while(n && rcv_len < long_block / DATA_INOUT_RATE); 
     390 
     391/* when enough data is received, process and send it */ 
     392 
     393if (rcv_len * DATA_INOUT_RATE == long_block) { 
     394 
     395my_process_function(data_in, data_out, fir_coef, long_block); 
     396 
     397/* write output data to output flow */ 
     398 
     399n = !WriteFlow(fdo, data_out, long_block); 
     400 
     401if (n < 0) { 
     402 
     403!LogWrite(“Error writing to flow\n”); 
     404 
     405return 0; 
     406 
     407} else if (!n) { 
     408 
     409!LogWrite(“Caution, missing packet due to full buffer\n”); 
     410 
     411} 
     412 
     413/* reset rcv counter */ 
     414 
     415rcv_len=0; 
     416 
     417/* set stats variable */ 
     418 
     419!SetStatsValue(stat_outsignal,data_out,long_block); 
     420 
     421} 
     422 
     423} 
     424 
     425== Coding Style == 
     426!FlexNets Coding style is based on the Linux Kernel Coding Style and, although we strongly recommend its reading, you may first of all check the following document defining basic codying style conventions: [wiki:WrittingCode Writing code for FlexNets]. 
     427 
     428naming conventions per les interficies, els fitxers, etc. 
    24429 
    25430== [[BR]]Compiling and Linking == 
    26431com compilar i linkar amb phal 
    27432 
    28 == Documentation == 
    29433[wiki:Users&Developers "[Back to User&Developer Guides]"]