Skip to content
Snippets Groups Projects
Commit 6e3f9c86 authored by Fort Frédéric's avatar Fort Frédéric
Browse files

Summary: Updated ptask wrappers. Precedence set may now be generated pre-sorted. (actual commit)

git-svn-id: https://svn.onera.fr/Prelude/Prelude/trunk@898 49f62630-d767-4ccd-930e-b3f5589f52e1
parent a0172dc1
No related branches found
No related tags found
No related merge requests found
S src/
B src/_build/
\ No newline at end of file
......@@ -37,8 +37,20 @@ struct multirate_precedence {
int prec_pat_size;
struct job_prec* prec_pref;
struct job_prec* prec_pat;
int src_period;
int dst_period;
};
void get_precedence_set(int* prec_number, struct multirate_precedence** presc);
struct task_precedences {
char* task_name;
int prec_src_size;
int prec_dst_size;
struct multirate_precedence* prec_src;
struct multirate_precedence* prec_dst;
};
void get_precedence_set(int* prec_number, struct multirate_precedence** precs);
void get_sorted_precedence_set(int* prec_number, struct task_precedences** precs);
#endif
......@@ -30,70 +30,54 @@
#include "nonencoded_aer_task_params.h"
#include "multirate_precedence.h"
//Set this to a higher value, if things are too fast
#define SLOWDOWN 1
struct task_args
{
struct nonencoded_aer_task_params* params;
struct job_prec **pred_pref;
int* pred_pref_size;
struct job_prec **pred_pat;
int* pred_pat_size;
sem_t **pred_sem;
int *pred_period;
int pred_count;
struct job_prec **succ_pref;
int* succ_pref_size;
struct job_prec **succ_pat;
int* succ_pat_size;
sem_t **succ_sem;
int *succ_period;
int succ_count;
struct task_precedences* precs;
sem_t **src_sems;
sem_t **dst_sems;
};
void append(void** array, void* add, size_t num_elements, size_t elem_size);
sem_t create_sem();
int nth(int n, struct job_prec* pref, int pref_size, struct job_prec* pat, int pat_size, int src);
int must_wait(const int n, const int job_id, const struct job_prec* pref, const int pref_size, const struct job_prec* pat, const int pat_size);
int gcd(int a, int b);
int lcm(int a, int b);
int must_post(const int n, const int job_id, const struct job_prec* pref, const int pref_size, const struct job_prec* pat, const int pat_size);
void task_body()
{
struct task_args *args = ptask_get_argument();
struct nonencoded_aer_task_params *task_struct = args->params;
int job_id = 0;
int i;
while(1)
{
for(i = 0; i < args->pred_count; ++i)
for(int i = 0; i < args->precs->prec_src_size; ++i)
{
if(job_id % args->pred_period[i] ==
nth(job_id,
args->pred_pref[i], args->pred_pref_size[i],
args->pred_pat[i], args->pred_pat_size[i],
0))
if(must_wait(job_id, args->precs->prec_src[i].dst_period,
args->precs->prec_src[i].prec_pref, args->precs->prec_src[i].prec_pref_size,
args->precs->prec_src[i].prec_pat, args->precs->prec_src[i].prec_pat_size))
{
sem_wait(args->pred_sem[i]);
sem_wait(args->src_sems[i]);
}
}
//ptime next_deadline;
// call step function
if (task_struct->nea_t_A)
task_struct->nea_t_A(NULL);
if (task_struct->nea_t_E)
task_struct->nea_t_E(NULL);
if (task_struct->nea_t_R)
task_struct->nea_t_R(NULL);
for(i = 0; i < args->succ_count; ++i)
if (args->params->nea_t_A)
args->params->nea_t_A(NULL);
if (args->params->nea_t_E)
args->params->nea_t_E(NULL);
if (args->params->nea_t_R)
args->params->nea_t_R(NULL);
for(int i = 0; i < args->precs->prec_dst_size; ++i)
{
if (must_post(job_id, args->precs->prec_dst[i].src_period,
args->precs->prec_dst[i].prec_pref, args->precs->prec_dst[i].prec_pref_size,
args->precs->prec_dst[i].prec_pat, args->precs->prec_dst[i].prec_pat_size))
{
if (job_id % args->succ_period[i] ==
nth(job_id,
args->succ_pref[i], args->succ_pref_size[i],
args->succ_pat[i], args->succ_pat_size[i],
1))
sem_post(args->succ_sem[i]);
sem_post(args->dst_sems[i]);
}
}
job_id += 1;
......@@ -105,126 +89,62 @@ void task_body()
int main()
{
struct nonencoded_aer_task_params *task_set;
struct multirate_precedence *prec_set;
struct task_precedences *prec_set;
tpars param;
int task_number, prec_number, i, j;
int task_number, prec_number;
ptask_init(SCHED_DEADLINE, PARTITIONED, PRIO_INHERITANCE);
// get Prelude task set
get_task_set(&task_number, &task_set);
get_precedence_set(&prec_number, &prec_set);
get_sorted_precedence_set(&prec_number, &prec_set);
int task_pid[task_number];
struct task_args args[task_number];
sem_t sems[prec_number];
int sem_count = 0;
memset(&args, 0, task_number*sizeof(struct task_args));
sem_t* task_sems[prec_number][2][task_number];
int sem_size = 0;
for(int i=0; i<task_number; ++i)
for(int j=0; j<2; ++j)
for(int k=0; k<prec_number; ++k)
task_sems[i][j][k] = NULL;
//populate task arguments
for (i=0; i<task_number; i++)
for (int i=0; i<task_number; i++)
{
args[i].params = &task_set[i];
args[i].src_sems = task_sems[i][0];
args[i].dst_sems = task_sems[i][1];
args[i].precs = &prec_set[i];
}
for (i=0; i<prec_number; i++)
{
int pred = -1;
int succ = -1;
for (j=0; j<task_number && (pred==-1 || succ==-1); j++)
for(int i=0; i<prec_number; i++)
{
if (strcmp(prec_set[i].src_name, task_set[j].nea_t_name) == 0)
{
pred = j;
sem_init(&sems[i], 0, 0);
}
else if (strcmp(prec_set[i].dst_name, task_set[j].nea_t_name) == 0)
for (int i=0; i<task_number; i++)
for (int j=0; j<prec_set[i].prec_dst_size; j++)
{
succ = j;
}
}
sems[sem_count] = create_sem();
int hyperperiod = lcm(task_set[pred].nea_t_period, task_set[succ].nea_t_period);
sem_t *sem = &sems[sem_count];
int succ_period = hyperperiod/task_set[succ].nea_t_period;
int pred_period = hyperperiod/task_set[pred].nea_t_period;
append(
(void**)&args[succ].pred_pref,
&prec_set[i].prec_pref,
args[succ].pred_count,
sizeof(struct job_prec*));
append(
(void**)&args[succ].pred_pat,
&prec_set[i].prec_pat,
args[succ].pred_count,
sizeof(struct job_prec*));
append(
(void**)&args[succ].pred_pref_size,
&prec_set[i].prec_pref_size,
args[succ].pred_count,
sizeof(int));
append(
(void**)&args[succ].pred_pat_size,
&prec_set[i].prec_pat_size,
args[succ].pred_count,
sizeof(int));
append(
(void**)&args[succ].pred_sem,
&sem,
args[succ].pred_count,
sizeof(sem_t*));
append(
(void**)&args[succ].pred_period,
&succ_period,
args[succ].pred_count,
sizeof(int));
append(
(void**)&args[pred].succ_pref,
&prec_set[i].prec_pref,
args[pred].succ_count,
sizeof(struct job_prec*));
append(
(void**)&args[pred].succ_pref_size,
&prec_set[i].prec_pref_size,
args[pred].pred_count,
sizeof(int));
append(
(void**)&args[pred].succ_pat,
&prec_set[i].prec_pat,
args[pred].succ_count,
sizeof(struct job_prec*));
append(
(void**)&args[pred].succ_pat_size,
&prec_set[i].prec_pat_size,
args[pred].succ_count,
sizeof(int));
append(
(void**)&args[pred].succ_sem,
&sem,
args[pred].succ_count,
sizeof(sem_t*));
append(
(void**)&args[pred].succ_period,
&pred_period,
args[pred].succ_count,
sizeof(int));
sem_count += 1;
args[pred].succ_count += 1;
args[succ].pred_count += 1;
args[i].dst_sems[j] = &sems[sem_size];
for (int k=0; k<task_number; k++)
if (!strcmp(prec_set[i].prec_dst[j].dst_name, prec_set[k].task_name))
for (int l=0; l<prec_set[k].prec_src_size; l++)
if (!strcmp(prec_set[k].prec_src[l].src_name, prec_set[i].task_name))
args[k].src_sems[l] = &sems[sem_size];
sem_size += 1;
}
// create tasks
for (i=0; i<task_number; i++)
for (int i=0; i<task_number; i++)
{
ptask_param_init(param);
ptask_param_argument(param, &args[i]);
ptask_param_period(param, (ptime)(task_set[i].nea_t_period), MILLI);
ptask_param_deadline(param, (ptime)task_set[i].nea_t_deadline, MILLI);
ptask_param_period(param, SLOWDOWN*(ptime)(task_set[i].nea_t_period), MILLI);
ptask_param_deadline(param, SLOWDOWN*(ptime)task_set[i].nea_t_deadline, MILLI);
ptask_param_runtime(param, SLOWDOWN*(ptime)(task_set[i].nea_t_wcet), MILLI);
ptask_param_processor(param, i%2); // multi-core scheduling
ptask_param_runtime(param, (ptime)(task_set[i].nea_t_wcet), MILLI);
ptask_param_activation(param, DEFERRED);
task_pid[i] = ptask_create_param(task_body, &param);
......@@ -237,7 +157,7 @@ int main()
}
printf("All tasks created\n");
for (i= 0; i<task_number; i++)
for (int i= 0; i<task_number; i++)
{
if (task_set[i].nea_t_I != NULL)
{
......@@ -257,7 +177,7 @@ int main()
}
ptime now = ptask_gettime(MILLI);
for (i=0; i<task_number; i++)
for (int i=0; i<task_number; i++)
{
ptime offt = 10 + now;
int r = ptask_activate_at(i, offt, MILLI);
......@@ -270,7 +190,7 @@ int main()
// Wait for tasks to finish even if they shouldn't
for(i=0; i<task_number; i++)
for(int i=0; i<task_number; i++)
{
pthread_join(ptask_get_threadid(task_pid[i]), 0);
}
......@@ -279,53 +199,32 @@ int main()
return 1;
}
sem_t create_sem()
inline int must_wait
(const int job_id, const int period,
const struct job_prec* pref, const int pref_size,
const struct job_prec* pat, const int pat_size)
{
sem_t sem;
sem_init(&sem, 0, 0);
return sem;
}
int nth
(int n,
struct job_prec* pref, int pref_size,
struct job_prec* pat, int pat_size,
int src)
{
if (n < pref_size)
if (job_id < pref_size)
{
if (src)
return pref[n].src_job;
else
return pref[n].dst_job;
return job_id % period == pref[job_id].dst_job;
}
else
{
if (src)
return pat[(n-pref_size)%pat_size].src_job;
else
return pat[(n-pref_size)%pat_size].dst_job;
return job_id % period == pat[(job_id-pref_size)%pat_size].dst_job;
}
}
int gcd(int a, int b)
inline int must_post
(const int job_id, const int period,
const struct job_prec* pref, const int pref_size,
const struct job_prec* pat, const int pat_size)
{
if (a==b)
return a;
else if (a > b)
return gcd(a-b, b);
else
return gcd(a, b-a);
}
int lcm(int a, int b)
if (job_id < pref_size)
{
return (a*b)/gcd(a,b);
return job_id % period == pref[job_id].src_job;
}
void append(void** array, void* add, size_t num_elements, size_t elem_size)
else
{
char* tmp = realloc(*array, elem_size*(num_elements+1));
memcpy(tmp+(num_elements*elem_size), add, elem_size);
*array = tmp;
return job_id % period == pat[(job_id-pref_size)%pat_size].src_job;
}
}
# Authors: Titouan ROOS, Julien FORGET, Frédéric Fort
.SUFFIX:
# Note: for correct execution privileges, run:
# sudo sh -c "echo -1 > /proc/sys/kernel/sched_rt_runtime_us"
# modify these 2 folders depending on your installation
PTASK_SOURCE_FOLDER=/home/forget/Installs/ptask
PRELUDE_FOLDER=/home/forget/Installs/prelude-1.7
PTASK_SOURCE_FOLDER=/home/ffort/site/ptask
PRELUDE_FOLDER=/home/ffort/site/prelude
PRELUDE_BIN_FOLDER=$(PRELUDE_FOLDER)/bin
PRELUDE_SHARE_FOLDER=$(PRELUDE_FOLDER)/share
PRELUDE_LIB_FOLDER=$(PRELUDE_FOLDER)/lib/prelude
# the following lines depend on the Prelude program you want to compile
# modify these 3 lines for each new Prelude program
PRELUDE_PROGRAM_FOLDER=.
PRELUDE_PROGRAM_NAME=$(PROG)
PRELUDE_NODE_NAME=$(NODE)
# next line is used only if nodes are not directly defined in header file
#USER_C_NODES=$(PRELUDE_PROGRAM_NAME)_nodes
USER_C_NODES=$(PRELUDE_PROGRAM_NAME)_nodes
# you might want to copy the file out of your installation and modify this line
PTASK_WRAPPER=$(PRELUDE_SHARE_FOLDER)/ptask_wrapper_aer
PTASK_WRAPPER=ptask_wrapper_aer
PRELUDE_PROGRAM=$(PRELUDE_PROGRAM_FOLDER)/$(PRELUDE_PROGRAM_NAME).plu
PRELUDE_C_FOLDER=$(PRELUDE_PROGRAM_FOLDER)/$(PRELUDE_PROGRAM_NAME)_c
PRELUDE_C_PROGRAM=$(PRELUDE_C_FOLDER)/$(PRELUDE_NODE_NAME)
EXTERN_BUFFERS=$(PRELUDE_C_FOLDER)/$(PRELUDE_NODE_NAME)_extbuffers
EXTERN_COM=$(PRELUDE_LIB_FOLDER)/extern_com
USER_C_FOLDER=$(PRELUDE_PROGRAM_FOLDER)
EXTERN_BUFFERS=$(PRELUDE_C_FOLDER)/$(PRELUDE_NODE_NAME)_extbuffers
EXTERN_COM=extern_com
OBJS=$(PRELUDE_C_PROGRAM).o $(EXTERN_BUFFERS).o $(PTASK_WRAPPER).o $(EXTERN_COM).o #$(USER_C_NODES).o
OBJS=$(PRELUDE_C_PROGRAM).o $(EXTERN_BUFFERS).o $(PTASK_WRAPPER).o $(EXTERN_COM).o $(USER_C_NODES).o
PRELUDEC=$(PRELUDE_BIN_FOLDER)/preludec
PLUFLAGS=-aer
PLUFLAGS=-aer -precedence_set sorted-by-task
CC=gcc
CFLAGS=-I$(PTASK_SOURCE_FOLDER)/src -I$(USER_C_FOLDER) -I$(PRELUDE_PROGRAM_FOLDER)/$(PRELUDE_PROGRAM_NAME)_c -I$(PRELUDE_LIB_FOLDER) -Wall -g
LDFLAGS=-lptask -L$(PTASK_SOURCE_FOLDER)/build/src -pthread -lrt
CFLAGS=-I$(PTASK_SOURCE_FOLDER)/src -I$(USER_C_FOLDER) -I$(PRELUDE_PROGRAM_FOLDER)/$(PRELUDE_PROGRAM_NAME)_c -I$(PRELUDE_LIB_FOLDER) -Wall
LDFLAGS=-L$(PTASK_SOURCE_FOLDER)/build/src -lptask -pthread -lrt
EXEC=$(PRELUDE_PROGRAM_NAME)
VPATH=$(PRELUDE_LIB_FOLDER)
.PHONY: all clean
all: $(EXEC)
......
REC
\ No newline at end of file
......@@ -234,18 +234,22 @@ let pp_precedence out_f src annot dst =
pp_prec_pref_ptr out_f pref_length src dst;
fprintf out_f ",@ ";
pp_prec_pat_ptr out_f pat_length src dst;
fprintf out_f "@ }"
let hyperperiod = Task_graph.hyperperiod src dst in
let src_period = hyperperiod/(Task_graph.get_period src) in
let dst_period = hyperperiod/(Task_graph.get_period dst) in
fprintf out_f ",@ %d,@ %d@ }"
src_period dst_period
(** Generates all precedence descriptions for [task_graph] and a function to access them. *)
let pp_precedences out_f task_graph =
(* precs declaration *)
let precs = prec_list task_graph in
let pp_precedences_data out_f precs =
let nb_precs = List.length precs in
Print.list_printer_from_printer "" "@ " "@ @ "
(fun out_f prec -> pp_prec_arrays out_f prec)
out_f precs;
fprintf out_f "#define %s %i@\n" nb_precs_name nb_precs
let nb_precs = List.length precs in
fprintf out_f "#define %s %i@\n" nb_precs_name nb_precs;
(** Generates all precedence descriptions for [task_graph] and a function to access them. *)
let pp_precedences_flat out_f task_graph =
let precs = prec_list task_graph in
fprintf out_f "@[<v 2>static struct %s %s[%s] = "
prec_struct_name static_prec_set_name nb_precs_name;
Print.list_printer_from_printer "{@ " ",@ " "@]@ };@ @ "
......@@ -262,6 +266,68 @@ let pp_precedences out_f task_graph =
fprintf out_f "@]@ }@ @ "
let pp_precedence_sorted out_f task src_precs dst_precs =
fprintf out_f "@[<v2>{ @[<h>\"%s\",@ %d,@ %d,@]@ "
(C_utils.task_name task.task_id)
(List.length src_precs)
(List.length dst_precs);
if List.length src_precs > 0 then
Print.list_printer_from_printer
"@[<v 2>(struct multirate_precedence[]){@ " ",@ " "@]}"
(fun out_f (src,annot,dst) -> pp_precedence out_f src annot dst)
out_f src_precs
else
fprintf out_f "NULL";
fprintf out_f ",@ ";
if List.length dst_precs > 0 then
Print.list_printer_from_printer
"@[<v 2>(struct multirate_precedence[]){@ " ",@ " "@]}"
(fun out_f (src,annot,dst) -> pp_precedence out_f src annot dst)
out_f dst_precs
else
fprintf out_f "NULL";
fprintf out_f "@] }"
let pp_precedences_sorted out_f task_graph task_set =
let precs = prec_list task_graph in
fprintf out_f "@[<v 2>static struct %s %s[%s] = "
"task_precedences" static_prec_set_name nb_tasks_name;
let tasks =
Hashtbl.fold
(fun _ task acc ->
let src_precs =
List.filter
(fun (_,_,dst) -> (taskid_of_vertex dst) = task.task_id)
precs in
let dst_precs =
List.filter
(fun (src,_,_) -> (taskid_of_vertex src) = task.task_id)
precs in
((task),(src_precs),(dst_precs))::acc)
task_set
[]
in
Print.list_printer_from_printer "{@ " ",@ " "@]@ };@ @ "
(fun out_f (task,src_precs,dst_precs) -> pp_precedence_sorted out_f task src_precs dst_precs)
out_f tasks;
(* Function to access precedences *)
fprintf out_f "void get_sorted_precedence_set (int* prec_number, struct %s** prec_set)@ "
"task_precedences";
fprintf out_f "@[<v 2>{@ ";
fprintf out_f "*prec_number = %s;@ " nb_precs_name;
fprintf out_f "*prec_set=%s;" static_prec_set_name;
fprintf out_f "@]@ }@ @ "
let pp_precedences out_f task_graph task_set =
pp_precedences_data out_f (prec_list task_graph);
if !Options.flat_precedence_set then
pp_precedences_flat out_f task_graph;
if !Options.sorted_precedence_set then
pp_precedences_sorted out_f task_graph task_set
(** Generates a description of communication
[tpred_name.vpred_id->tsucc_name.vsucc_id]. See
lib/prelude/com_patterns.h for a description of the generated structure. *)
......@@ -311,4 +377,3 @@ let pp_protocols_export out_f task_set =
fprintf out_f "*com_set=%s;" static_com_set_name;
fprintf out_f "@]@ }@ @ "
......@@ -38,6 +38,27 @@ let bool_is_stdbool = ref true
let aer_format = ref false
let aer_wcc = ref false
let io_code = ref true
let flat_precedence_set = ref true
let sorted_precedence_set = ref false
let configure_precedence_set s =
match s with
| "flat" ->
begin
flat_precedence_set := true;
sorted_precedence_set := false;
end
| "sorted-by-task" ->
begin
flat_precedence_set := false;
sorted_precedence_set := true;
end
| "all" ->
begin
flat_precedence_set := true;
sorted_precedence_set := true;
end
| _ -> failwith ("Unknown precedence set configuration "^s)
let options =
[ "-aer", Arg.Set aer_format, "produce C code following the AER format";
......@@ -46,6 +67,7 @@ let options =
"-cheddar", Arg.Set print_tasks, "simple formatting of task set for Cheddar tests (alias for print_tasks)";
"-d", Arg.Set_string dest_dir, "produces code in the specified directory";
"-extern_buffers", Arg.Set extern_buffers, "produces C code for external buffer allocation";
"-precedence_set", Arg.Symbol(["flat"; "sorted-by-task"; "all"], configure_precedence_set), "configure how the precedence set should be exported" ;
"-no_export_protocols", Arg.Clear export_protocols, "do not export communication protocols in generated code";
"-no_io_code", Arg.Clear io_code, "produce no code for sensors/actuators. WARNING: only works combined with aer option";
"-node", Arg.Set_string main_node, "specifies the main node";
......
......@@ -608,3 +608,18 @@ let prec_list g =
prec::(filter_dup_precs tl)
in
filter_dup_precs precs
(** The period of a vertex *)
let get_period v =
let c = match v.vertex_desc with
| Var v -> Clocks.pclock_parent v.var_clock
| NodeVar nd -> Clocks.pclock_parent (Clocks.clock_of_impnode_clock nd.ndvar_clock)
| _ -> failwith "Task_graph get_period"
in
Clocks.period c
(** Hyperperiod of vertices src and dst *)
let hyperperiod src dst =
let c1 = get_period src in
let c2 = get_period dst in
Utils.lcm c1 c2
......@@ -105,7 +105,7 @@ let pp_prog_legacy task_set task_graph basename =
(* Exports to acess the task set in other C files. *)
C_exports.pp_tasks_params out_f task_set;
if !Options.no_encoding then
C_exports.pp_precedences out_f task_graph;
C_exports.pp_precedences out_f task_graph task_set;
if !Options.export_protocols then
C_exports.pp_protocols_export out_f task_set;
......@@ -158,7 +158,7 @@ let pp_prog_aer task_set task_graph basename =
if(not !Options.aer_wcc) then
begin
C_exports.pp_tasks_params out_f task_set_cut;
C_exports.pp_precedences out_f task_graph;
C_exports.pp_precedences out_f task_graph task_set_cut;
C_exports.pp_protocols_export out_f task_set;
C_exports.pp_extern_buffers out_f task_set
end;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment