Commit 289fe2d1 authored by Maxime Perrotin's avatar Maxime Perrotin

Optimize timers in the vertical transformation

Add a filter mechanism that allows to specify which PI actually calls
with RIs. This can save hundreds of AADL ports in large systems.
Applied to timer only but to be extended when information linking PIs to
RIs is available.
parent 4dedd636
Pipeline #365 skipped
......@@ -114,6 +114,10 @@ int Compare_Interface (Interface *one, Interface *two)
return (!strcmp (name1, name2));
}
int Compare_FV (FV *one, FV *two)
{
return (!strcmp(one->name, two->name));
}
int Compare_Protected_Object_Name (Protected_Object_Name *one, Protected_Object_Name *two)
{
......@@ -689,6 +693,7 @@ void Create_Interface(Interface ** i)
(*i)->distant_qgen = distant_qgen;
(*i)->calling_threads = NULL;
(*i)->distant_name = NULL;
(*i)->calling_pis = NULL;
}
// this function clears up an Interface data structure
......@@ -735,16 +740,15 @@ void Clear_Interface(Interface * i)
i->distant_qgen = NULL;
}
if (NULL != i->calling_threads) {
//Clear_FV_List_Keep_Elem(i->calling_threads);
i->calling_threads = NULL;
}
if (NULL != i->distant_name) {
free(i->name);
i->name = NULL;
}
/* Don' t try to free the lists here */
i->calling_threads = NULL;
i->calling_pis = NULL;
}
......
......@@ -174,9 +174,16 @@ void Add_timers_to_function (FV *fv, FV *timer_manager)
{
Interface *expire = NULL, *set_timer = NULL, *reset_timer = NULL;
Parameter *param = NULL;
Interface *cyclic_pi = NULL;
assert (NULL != header && NULL != code);
/* Find the cyclic interface of the timer manager */
FOREACH(pi, Interface, timer_manager->interfaces, {
if (!strcmp(pi->name, "tick_100ms")) cyclic_pi = pi;
});
FOREACH (timer, String, fv->timer_list, {
/* Declare functions in timer manager code */
fprintf (header, "void %s_PI_SET_%s(const asn1SccT_UInt32 *val);\n\n",
......@@ -228,6 +235,8 @@ void Add_timers_to_function (FV *fv, FV *timer_manager)
expire->distant_name = make_string (timer);
free (expire->distant_fv);
expire->distant_fv = make_string (fv->name);
/* Filter: set the list of calling PIs in the timer manager */
ADD_TO_SET(Interface, expire->calling_pis, cyclic_pi);
APPEND_TO_LIST (Interface, timer_manager->interfaces, expire);
/* Add Unpro PI "RESET_timer" to timer manager (no param) */
......@@ -423,13 +432,6 @@ void ProcessArtificial_FV_Creation (Interface *i, RCM rcm)
/* Find the corresponding interface in the caller */
distant_RI = FindCorrespondingRI(caller, i);
// FOREACH (interface, Interface, caller->interfaces, {
// if (RI == interface->direction &&
// !strcmp (interface->distant_name, i->name) &&
// !strcmp (interface->distant_fv, i->parent_fv->name)) {
// distant_RI = interface;
// }
// });
if (NULL != distant_RI
&& strcmp(artificial_fv_name, distant_RI->parent_fv->name)) {
......@@ -522,87 +524,97 @@ void Add_RI_To_Thread (Interface *i, FV *fv)
/* Add a thread to the calling list */
int Add_Thread_To_Calling_List (FV_list **calling_threads_list, FV *fv)
void Add_Thread_To_Calling_List (FV_list **calling_threads_list, FV *fv)
{
assert(NULL != calling_threads_list);
assert(NULL != fv);
FOREACH(t, FV, *calling_threads_list, {
if (t == fv) fv = NULL;
if (t == fv) fv = NULL;
});
if (NULL != fv) {
APPEND_TO_LIST(FV, *calling_threads_list, fv);
return 0;
APPEND_TO_LIST(FV, *calling_threads_list, fv);
return;
}
else return 1;
}
/* Pre-Processing: propagate Calling thread to distant FV
* (used to allow sync function to make call to RI). */
void Propagate_Calling_Thread(Interface *i, FV **fv)
{
FV *distant_fv = NULL;
Interface *corresponding_pi = NULL;
distant_fv = (FV *)FindFV (i->distant_fv);
if (NULL != distant_fv) {
FOREACH(dist_i, Interface, distant_fv->interfaces, {
//printf("%s %s %s\n", dist_i->name, i->name, i->distant_name);
// Temporary fix to support the new version of tasteIV
char *res=NULL;
if (NULL != i->distant_name) {
res = strchr(i->distant_name, '.');
if (NULL != res) {
printf("[preprocessing_backend.c] XXX\n");
*res = '\0';
}
}
if(PI==dist_i->direction &&
!strcmp(dist_i->name,
NULL != i->distant_name?i->distant_name:i->name)) {
corresponding_pi=dist_i;
FV *distant_fv = NULL;
Interface *corresponding_pi = NULL;
/* Find the function to which the RI is connected */
distant_fv = FindFV(i->distant_fv);
if(NULL == distant_fv) {
/* This RI is not connected */
return;
}
/* Find the PI corresponding to the RI passed as first argument */
FOREACH(dist_i, Interface, distant_fv->interfaces, {
// Long-term temporary fix to support the new version of tasteIV
char *res = NULL;
if (NULL != i->distant_name) {
res = strchr(i->distant_name, '.');
if (NULL != res) {
printf("[preprocessing_backend.c] FIXME\n");
*res = '\0';
}
});
}
if(PI == dist_i->direction &&
!strcmp(dist_i->name,
NULL != i->distant_name ? i->distant_name : i->name)) {
corresponding_pi = dist_i;
}
});
assert(NULL != corresponding_pi);
assert(NULL != corresponding_pi);
/*
* Check that the calling thread is not already in the list of
* the distant fv/pi. This is essential to avoid infinite recursion
* in case of circular dependencies
*/
FOREACH(ct, FV, corresponding_pi->calling_threads, {
if(ct == *fv) return;
});
/*
* Check that the calling thread is not already in the list of
* the distant fv/pi. This is essential to avoid infinite recursion
* in case of circular dependencies
*/
FOREACH(ct, FV, corresponding_pi->calling_threads, {
if(ct == *fv) return;
});
FOREACH(ct, FV, distant_fv->calling_threads, {
if(ct == *fv) return;
});
FOREACH(ct, FV, distant_fv->calling_threads, {
if(ct == *fv) return;
});
/* Add the thread to the list of calling FV of the interface */
Add_Thread_To_Calling_List (&(corresponding_pi->calling_threads), *fv);
/* Add the thread to the list of calling FV of the interface */
Add_Thread_To_Calling_List (&(corresponding_pi->calling_threads), *fv);
/* Also add the thread to the calling list of the FV itself */
Add_Thread_To_Calling_List (&(distant_fv->calling_threads), *fv);
/* Also add the thread to the calling list of the FV itself */
Add_Thread_To_Calling_List (&(distant_fv->calling_threads), *fv);
/* And change the "distant fv" field of the corresponding PI */
if(NULL != corresponding_pi->distant_fv) {
free(corresponding_pi->distant_fv);
corresponding_pi->distant_fv=NULL;
}
build_string(&(corresponding_pi->distant_fv),
(*fv)->name, strlen((*fv)->name));
if(passive_runtime == distant_fv->runtime_nature) {
/* Do the same recursively until we reach another thread */
FOREACH(sub_i, Interface, distant_fv->interfaces, {
if (RI == sub_i->direction) {
Propagate_Calling_Thread (sub_i, fv);
}
});
}
/* And change the "distant fv" field of the corresponding PI */
if(NULL != corresponding_pi->distant_fv) {
free(corresponding_pi->distant_fv);
corresponding_pi->distant_fv = NULL;
}
build_string(&(corresponding_pi->distant_fv),
(*fv)->name, strlen((*fv)->name));
if(passive_runtime == distant_fv->runtime_nature) {
/* Do the same recursively until we reach another thread */
FOREACH(sub_i, Interface, distant_fv->interfaces, {
if (RI == sub_i->direction) {
/* filter: some RIs are not called by the code of a given PI
* for example the timer expiration signal is only called by the
* cyclic PI of the timer manager. Don't propagate in that case
* to avoid explosion of the number of AADL ports in the CV */
if (NULL == sub_i->calling_pis
|| IN_SET(Interface, sub_i->calling_pis, corresponding_pi)) {
Propagate_Calling_Thread(sub_i, fv);
}
}
});
}
}
......@@ -708,7 +720,7 @@ void Preprocess_FV (FV *fv)
/* preprocessing: determine if a FV is a thread or a passive function
* (once all artificial threads have been created) */
fv->runtime_nature = passive_runtime;
fv->runtime_nature = passive_runtime;
FOREACH (i, Interface, fv->interfaces, {
if (PI==i->direction) switch (i->rcm) {
......@@ -1021,10 +1033,10 @@ void Preprocess_coverage (Process *node)
" exit(0);\n"
"}\n\n");
/* Initialisation code of the coverage manager - nothing special */
/* Initialisation code of the coverage manager */
fprintf (code, "void %s_startup()\n"
"{\n"
" puts(\"use kill -SIGUSR2 to collectcode coverage\");\n"
" puts(\"use kill -SIGUSR2 to collect code coverage\");\n"
" signal(SIGUSR2, gc_handler);\n"
"}\n\n",
fv->name);
......@@ -1088,28 +1100,47 @@ void Preprocessing_Backend (System *s)
FOREACH (fv, FV, s->functions, {
Preprocess_FV(fv);
})
});
/* preprocessing: Propagate calling thread to distant PI (recursively) */
/* Propagate calling thread to distant PI (recursively)
* i.e look for all threads (functions have already been preprocessed)
* then go through all their RIs recursively until reaching another thread,
* and set that the function is a calling thread of the reached one */
FOREACH(fv, FV, s->functions, {
if (thread_runtime == fv->runtime_nature) {
if (thread_runtime == fv->runtime_nature) {
FOREACH(i, Interface, fv->interfaces, {
if (RI == i->direction) Propagate_Calling_Thread (i, &fv);
})
}
})
});
/* Add each RI of passive functions as RI of their calling thread */
/* Add each RI of passive functions as RI of their calling threads */
FOREACH(fv, FV, s->functions, {
if(passive_runtime==fv->runtime_nature) {
FOREACH(i, Interface, fv->interfaces, {
if (RI==i->direction && i->distant_qgen->language == other) {
FOREACH(thread, FV, fv->calling_threads, {
Add_RI_To_Thread(i, thread);
/* Add to calling threads only of PIs that actually call
* the current RI - filtering to be done, but the result
* is the ri->calling_pis list */
FV_list *callers = NULL;
if (NULL == i->calling_pis) {
callers = fv->calling_threads;
}
else {
/* Build a set of actual calling threads of this RI */
FOREACH(calling_pi, Interface, i->calling_pis, {
FOREACH(thread_caller, FV, calling_pi->calling_threads, {
ADD_TO_SET(FV, callers, thread_caller);
});
});
}
//FOREACH(thread, FV, fv->calling_threads, {
FOREACH(thread, FV, callers, {
Add_RI_To_Thread(i, thread);
Propagate_Calling_Thread(i, &thread);
})
});
}
})
});
}
});
......
......@@ -177,25 +177,26 @@ typedef struct T_name_list
Type used to describe an interface (provided or required)
*/
typedef struct t_interface {
char *name;
Port *port_name;
struct t_fv *parent_fv;
IF_type direction;
Parameter_list *in;
Parameter_list *out;
IF_kind synchronism;
RCM rcm;
long long period;
uint64_t wcet_low;
char *wcet_low_unit;
uint64_t wcet_high;
char *wcet_high_unit;
char *distant_fv;
struct t_qgen *distant_qgen;
struct t_FV_list *calling_threads;
char *distant_name;
unsigned long long queue_size;
bool ignore_params;
char *name;
Port *port_name;
struct t_fv *parent_fv;
IF_type direction;
Parameter_list *in;
Parameter_list *out;
IF_kind synchronism;
RCM rcm;
long long period;
uint64_t wcet_low;
char *wcet_low_unit;
uint64_t wcet_high;
char *wcet_high_unit;
char *distant_fv;
struct t_qgen *distant_qgen;
struct t_FV_list *calling_threads;
char *distant_name;
unsigned long long queue_size;
bool ignore_params;
struct t_Interface_list *calling_pis; // only set in RIs of passive functions
} Interface;
DECLARE_LIST (Interface)
......
......@@ -230,6 +230,7 @@ extern void add_error();
int Compare_Package(Package *one, Package *two);
int Compare_Protected_Object_Name(Protected_Object_Name *one, Protected_Object_Name *two);
int Compare_Interface (Interface *one, Interface *two);
int Compare_FV (FV *one, FV *two);
int Compare_String (String *one, String *two);
int Compare_ASN1_Filename(ASN1_Filename *one, ASN1_Filename *two);
int Compare_ASN1_Module (ASN1_Module *one, ASN1_Module *two);
......@@ -243,13 +244,13 @@ void Print_FV (FV *fv);
Example of use:
with "MyType_list *l;" and l containing elements
FOREACH(tmp, MyType,l, {
printf("%s",tmp);
printf(" ");
}
)
*/
#define FOREACH(var,type,list,stmt) {type##_list *varlist##var##type=list; type *var;while(varlist##var##type!=NULL) { var=varlist##var##type->value; stmt varlist##var##type=varlist##var##type->next; }}
......@@ -289,6 +290,16 @@ if(Compare_##type(val,elem)) result = 1; \
if (!result) APPEND_TO_LIST(type, list, val);\
}
/* return true if value of type sort is in set */
#define IN_SET(sort, set, val) \
__extension__({\
bool result = false; \
FOREACH(elem, sort, set, {\
if(Compare_##sort(val,elem)) result = true; \
});\
result;\
})
#define FREE_LIST(type, list) \
{\
type##_list *next=NULL;\
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment