PIPS
freia_sigmac.c
Go to the documentation of this file.
1 /*
2 
3  $Id: freia_sigmac.c 23443 2017-10-27 14:14:05Z guillou $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "pips_config.h"
27 #endif
28 
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 
33 #include "genC.h"
34 #include "misc.h"
35 #include "linear.h"
36 
37 #include "ri.h"
38 #include "ri-util.h"
39 #include "prettyprint.h"
40 #include "properties.h"
41 
42 #include "freia.h"
43 #include "hwac.h"
44 
45 #include "freia_sigmac.h"
46 
47 /*#######################################################################*/
48 /*#######################################################################*/
49 /*#######################################################################*/
50 
51 #define SIGMAC_INSTANTIATE(a, b) " agent " a " = new " b ";\n"
52 #define SIGMAC_CONNECT(a, b) " connect (" a ", " b ");\n"
53 #define REPLICATION_AGENT "rep" //"Dup<int16_t>"
54 
55 // global variable to store the total number of dags processed
56 static int n_dags = 0;
57 
58 /* Populates the hash table htid:
59  * one dagvtx is linked to an unique id depending on its freia_api_t
60  */
61 static void sigmac_name_instances(dag dg, hash_table htid) {
62  _int nb_op;
63  const freia_api_t *f;
64 
65  // freia_api_t * -> number of encoutered vertices
67 
68  FOREACH(dagvtx, vtx, dag_vertices(dg)) {
69  f = get_freia_api_vtx(vtx);
70  if (!f)
71  continue;
72 
73  // initializating hash_table htinst
74  if (!hash_defined_p(htinst, f))
75  hash_put(htinst, f, (void *)(_int)0);
76 
77  // new instance id = total nb of instances of the same operation
78  nb_op = (_int)hash_get(htinst, f);
79  hash_put(htid, vtx, (void *)nb_op);
80  // updating nb of instances for current operation
81  nb_op++;
82  hash_update(htinst, f, (void *)nb_op);
83  }
84 
85  hash_table_free(htinst);
86 }
87 
88 /* Generate a unique string per dagvtx consisting in
89  * - one short name, shared by all the dagvtx with the same freia_api_t
90  * - one integer, different for every dagvtx with the same freia_api_t
91  */
92 static string sc_vtx_tostring(const dagvtx v, const hash_table htid) {
93  string r = get_freia_api_vtx(v)->sigmac.inst_prefix;
94  _int n = (_int)hash_get(htid, v);
95  return strdup(cat(r, i2a(n)));
96 }
97 
98 /* Determine if an argument contains references to other variables
99  * (dirty hack based on isalpha)
100  */
101 static bool is_param_dynamic(expression arg) {
102  string s = expression_to_string(arg);
103  bool is_dyn = false;
104  unsigned int i;
105  for (i = 0; i < strlen(s); i++)
106  if (isalpha(s[i]))
107  is_dyn = true;
108  return is_dyn;
109 }
110 
111 /* Determine if a dagvtx has at least one dynamic parameter
112  */
114  const freia_api_t *f = get_freia_api_vtx(v);
115  if (!f)
116  return false;
117  if (strstr(f->function_name, "_const") || dagvtx_optype(v) == spoc_type_thr) {
118  list vtx_params = freia_get_vertex_params(v);
119  FOREACH(expression, arg, vtx_params) {
120  if (is_param_dynamic(arg))
121  return true;
122  }
123  }
124  return false;
125 }
126 
127 /* Returns a list of values
128  of one dagvtx misc input parameters
129  */
130 static list sc_get_params_values(dagvtx vtx, hash_table hparams, int *nparams) {
131  vtxcontent vtc = dagvtx_content(vtx);
133  call c = freia_statement_to_call(stm);
134 
135  // list of misc param values
136  return freia_extract_params(dagvtx_opid(vtx), call_arguments(c), NULL, NULL,
137  hparams, nparams);
138 }
139 
140 /* Print the value of a morphological kernel
141  * extracted from a dagvtx
142  */
143 static bool sc_print_kernel(string_buffer sb_par, dagvtx v) {
144  intptr_t k[9];
145  bool b = freia_extract_kernel_vtx(v, true, &k[0], &k[1], &k[2], &k[3], &k[4],
146  &k[5], &k[6], &k[7], &k[8]);
147  sb_cat(sb_par, "{ ");
148  for (int i = 0; i < 8; i++)
149  sb_prf(sb_par, "%d, ", k[i]);
150  sb_prf(sb_par, "%d }", k[8]);
151  return b;
152 }
153 
154 /* Print a kernel customized inner loop from
155  a morphological kernel
156 */
157 static bool sc_kernel_compute_loop(string_buffer sb_morpho, const dagvtx vtx,
158  string kname) {
159  intptr_t k[9];
160 
161  if (dagvtx_optype(vtx) != spoc_type_poc)
162  return false;
163 
164  bool b = freia_extract_kernel_vtx(vtx, true, &k[0], &k[1], &k[2], &k[3],
165  &k[4], &k[5], &k[6], &k[7], &k[8]);
166 
167  string row[3] = {"olid", "clid", "ilid"};
168  int i, j;
169 
170  sb_prf(sb_morpho, "\n"
171  "#define %s_%d(OPR)\t\t\t\t\\\n",
172  kname, n_dags);
173  for (i = 0; i < 3; i++)
174  for (j = 0; j < 3; j++)
175  if (k[3 * i + j]) {
176  string neighbor = strdup(cat("buffer[", row[i], "][i+", i2a(j), "]"));
177  sb_prf(sb_morpho, "ret = PIXEL_ ## OPR(ret, %s);\t\\\n", neighbor,
178  neighbor);
179  }
180  sb_prf(sb_morpho, "\nCUSTOM_MORPHO_AGENT(%s_%d, " PIXEL_T ")\n"
181  "\n",
182  kname, n_dags);
183 
184  return b;
185 }
186 
188  hash_table hparams, const dag dg) {
189  list lparams = NIL;
190 
191  FOREACH(dagvtx, vtx, dag_vertices(dg)) {
192 
193  if (dagvtx_optype(vtx) != spoc_type_poc)
194  continue;
195 
196  list vtx_param_vars = freia_get_vertex_params(vtx);
197 
198  // tests if argument already declared
199  string parname =
200  (string)hash_get(hparams, EXPRESSION(gen_nth(0, vtx_param_vars)));
201  if (gen_in_list_p(parname, lparams))
202  continue;
203  lparams = CONS(string, parname, lparams);
204 
205  sc_kernel_compute_loop(sb_morpho, vtx, parname);
206  }
207 }
208 
209 /* Generates the constant parameters declaration
210  */
211 static void sigmac_params_decl(string_buffer sb_par, dag dg, hash_table hparams,
212  int *pnparams) {
213  // dirty workaround preventing deblocking convolutions
214  // to declare several times the same parameter
215  list lparams = NIL;
216  FOREACH(dagvtx, vtx, dag_vertices(dg)) {
217 
219  continue;
220 
221  // list of misc param values
222  list vtx_param_vals = sc_get_params_values(vtx, hparams, pnparams);
223  // list of freia misc param names
224  list vtx_param_vars = freia_get_vertex_params(vtx);
225 
226 #ifdef DEBUG_INFO
227  const freia_api_t *f = get_freia_api_vtx(vtx);
228  sb_prf(sb_par, "// nb args for type %s : %d/%d, in %d, out %d\n",
229  f->sigmac.agent_name, gen_length(vtx_param_vals),
230  gen_length(vtx_param_vars), f->arg_misc_in, f->arg_misc_out);
231  FOREACH(expression, arg, vtx_param_vars) {
232  sb_prf(sb_par, "// %s\n", expression_to_string(arg));
233  }
234  FOREACH(expression, arg, vtx_param_vals) {
235  sb_prf(sb_par, "// %s\n", expression_to_string(arg));
236  }
237 #endif
238 
239  bool dynamic_agent = has_vtx_dynamic_params(vtx);
240 
241  // misc params declaration
242  unsigned int i = 0;
243  FOREACH(expression, arg, vtx_param_vals) {
244 
245  // tests if argument already declared
246  string parname =
247  (string)hash_get(hparams, EXPRESSION(gen_nth(i, vtx_param_vars)));
248  if (gen_in_list_p(parname, lparams))
249  continue;
250  lparams = CONS(string, parname, lparams);
251 
252  if (!dynamic_agent) {
253  // print parameter type (in SigmaC, everything is int16_t)
254  sb_cat(sb_par, " " PIXEL_T);
255 
256  // print parameter pips name
257  sb_prf(sb_par, " %s",
258  hash_get(hparams, EXPRESSION(gen_nth(i, vtx_param_vars))));
259 
260  // print parameter value
261  if (dagvtx_optype(vtx) == spoc_type_poc) {
262  // kernel vtx have only one misc parameter
263  sb_cat(sb_par, "[9]", " = ");
264  sc_print_kernel(sb_par, vtx); // get & print kernel
265  } else
266  sb_prf(sb_par, " = %s", expression_to_string(arg));
267 
268  sb_cat(sb_par, ";\n");
269 
270  if (freia_convolution_p(vtx))
271  break;
272  i++;
273  }
274  } // FOREACH(expression, arg, vtx_param_vals)
275  }
276 }
277 
278 /* Generate the instanciation of an agent
279  * in the forme "agent instname = new agentname (parameters)"
280  */
281 static void sc_inst(string_buffer sb, const dagvtx v, const hash_table htid,
282  const hash_table hparams, string miscparams,
283  bool is_dynamic) {
284  const freia_api_t *f = get_freia_api_vtx(v);
285  string_buffer sbinst = string_buffer_make(true);
286 
287  // beginning of declaration
288  sb_cat(sbinst, f->sigmac.agent_name);
289 
290  if (is_dynamic)
291  sb_cat(sbinst, "_dyn");
292 
293  sb_prf(sbinst, "(%s", f->sigmac.agent_arg);
294 
295  // completing with misc arguments
296  if ((f->arg_misc_in + f->arg_misc_out) && hparams) {
297  if (is_dynamic)
298  sb_cat(sbinst, ", height");
299  else {
300  list largs = freia_get_vertex_params(v);
301  FOREACH(expression, arg, largs) {
302  sb_cat(sbinst, ", ", hash_get(hparams, arg));
303  if (freia_convolution_p(v))
304  break;
305  }
306  }
307  // add manually more arguments
308  if (miscparams)
309  sb_cat(sbinst, ", ", miscparams);
310  }
311  sb_cat(sbinst, ")");
312 
313  if (get_bool_property("HWAC_SIGMAC_SPECIFIC_MORPHO") &&
315 
316  string_buffer_reset(sbinst);
317  if (same_string_p(f->compact_name, "E8"))
318  sb_cat(sbinst, "erode_");
319  else if (same_string_p(f->compact_name, "D8"))
320  sb_cat(sbinst, "dilate_");
321  else if (same_string_p(f->compact_name, "conv"))
322  sb_cat(sbinst, "convole_");
323  list largs = freia_get_vertex_params(v);
324  FOREACH(expression, arg, largs) {
325  sb_prf(sbinst, "%s_%d(width, height", hash_get(hparams, arg), n_dags);
326  if (freia_convolution_p(v)) // convolution needs the kernel
327  sb_prf(sbinst, ", %s", hash_get(hparams, arg));
328  sb_prf(sbinst, ")");
329  break; // there is only 1 argument
330  }
331  }
332 
333  sb_prf(sb, SIGMAC_INSTANTIATE("%s", "%s"), sc_vtx_tostring(v, htid),
334  string_buffer_to_string(sbinst));
335 
336  string_buffer_free(&sbinst);
337 }
338 
339 /* Helper function
340  * determine the input port of the succ dagvtx
341  * to be connected to the output port of current_vtx dagvtx
342  * succ must be in dagvtx_succs(current_vtx)
343  */
344 static int sc_get_port_id(dagvtx current_vtx, dagvtx succ, dag dg) {
345  return gen_position(current_vtx, dag_vertex_preds(dg, succ)) - 1;
346 }
347 
348 /* Generate a 3 lines commented code delimiter
349  * with a centered title
350  */
351 static void sc_delimiter(string_buffer sb, const string title) {
352  sb_cat(sb, "\n\n");
353  int columns = 69;
354  int i, l = strlen(title);
355 
356  // 1st line
357  sb_cat(sb, "/*");
358  for (i = 0; i < columns; i++)
359  sb_cat(sb, "#");
360  sb_cat(sb, "*/\n");
361 
362  // 2nd line, with title
363  sb_cat(sb, "/*");
364  int a = (columns - l - 2) / 2;
365  for (i = 0; i < a; i++)
366  sb_cat(sb, "#");
367  if (!(l % 2))
368  sb_cat(sb, " ", title, " #");
369  else
370  sb_cat(sb, " ", title, " ");
371  for (i = 0; i < a; i++)
372  sb_cat(sb, "#");
373  sb_cat(sb, "*/\n");
374 
375  // 3rd line, same as 1st one
376  sb_cat(sb, "/*");
377  for (i = 0; i < columns; i++)
378  sb_cat(sb, "#");
379  sb_cat(sb, "*/\n");
380 
381  sb_cat(sb, "\n");
382 }
383 
384 /* Generate an application subgraph header
385  * containing the declarations and connections
386  * of the i/o agents
387  */
388 static void sc_subgraph_app(string_buffer sb, string subgraph_name,
389  int n_imgs_input, int n_imgs_output,
390  int n_params_input, int n_params_output) {
391  sb_prf(sb, "subgraph\n%s\n", subgraph_name);
392  sb_cat(sb, "(char pipein[255],\n char pipeout[255],\n",
393  " int width,\n int height,\n size_t sizeMax,\n"
394  " char pipeparin[255],\n char pipeparout[255])\n"
395  "{\n\n");
396 
397  sb_cat(sb, " map {\n");
398 
399  // launchers and streamers
400  if (n_imgs_input > 0) {
401  sb_prf(sb,
402  SIGMAC_INSTANTIATE("lhin", "Launcher_In(pipein, %d, width, height)"),
403  n_imgs_input);
404  sb_prf(sb, SIGMAC_INSTANTIATE("strin", "Streamer_In(width, height, %d)"),
405  n_imgs_input);
406  sb_cat(sb, SIGMAC_CONNECT("lhin.param", "strin.input"));
407  sb_cat(sb, " SigmaC_agent_setUnitType(strin,\"k1-I/O\");\n");
408  }
409 
410  if (n_imgs_output > 0) {
411  sb_prf(sb, SIGMAC_INSTANTIATE("lhout",
412  "Launcher_Out(pipeout, %d, width, height)"),
413  n_imgs_output);
414  sb_prf(sb, SIGMAC_INSTANTIATE("strout", "Streamer_Out(width, height, %d)"),
415  n_imgs_output);
416  sb_cat(sb, SIGMAC_CONNECT("strout.output", "lhout.result"));
417  sb_cat(sb, " SigmaC_agent_setUnitType(strout,\"k1-I/O\");\n");
418  }
419 
420  // scalar passing agents
421  if (n_params_input > 0) { // transfers dynamic parameters to MPPA
422  sb_cat(sb, "\n");
423  sb_prf(sb, SIGMAC_INSTANTIATE("pp", "Params_Provider(pipeparin, %d)"),
424  n_params_input);
425  sb_prf(sb, SIGMAC_INSTANTIATE("sp", "Split<" PARAM_T ">(%d, 1)"),
426  n_params_input);
427  sb_prf(sb, " SigmaC_agent_setUnitType(sp,\"k1-I/O\");\n");
428  sb_cat(sb, SIGMAC_CONNECT("pp.output", "sp.input"));
429  }
430 
431  if (n_params_output > 0) { // transfers reduction results to host
432  sb_cat(sb, "\n");
433  sb_prf(sb, SIGMAC_INSTANTIATE("mr", "Measures_Retriever(pipeparout, %d)"),
434  n_params_output);
435  sb_prf(sb, SIGMAC_INSTANTIATE("jo", "Join<" PARAM_T ">(%d, 1)"),
436  n_params_output);
437  sb_prf(sb, " SigmaC_agent_setUnitType(jo,\"k1-I/O\");\n");
438  sb_cat(sb, SIGMAC_CONNECT("jo.output", "mr.input"));
439  }
440 }
441 
442 /*#######################################################################*/
443 /*#######################################################################*/
444 /*#######################################################################*/
445 
446 static int dagvtx_sigmac_priority(const dagvtx *pv1, const dagvtx *pv2) {
447  const dagvtx v1 = *pv1, v2 = *pv2;
448  return dagvtx_number(v1) - dagvtx_number(v2);
449 }
450 
451 /* If vtx is compound, returns the id of
452  correspondant connected component.
453  Else returns -1.
454  */
455 static int is_vtx_compound(dagvtx vtx, list lcomponents) {
456  unsigned int n_connex = 0; // id of the connected component
457  FOREACH(list, lconnex, lcomponents) {
458  if (gen_in_list_p(vtx, lconnex)) {
459  break; // to pick the right connected component
460  }
461  // v does not belong to this connected component
462  n_connex++;
463  }
464  return (n_connex == gen_length(lcomponents)) ? -1 : (int)n_connex;
465 }
466 
467 static list sigmac_get_component_outputs(list lconnex, dag dg) {
468  list result = NIL;
469  bool output;
470  FOREACH(dagvtx, vtx, lconnex) {
471  output = false;
472  if (!gen_length(dagvtx_succs(vtx)) || gen_in_list_p(vtx, dag_outputs(dg)))
473  output = true;
474  FOREACH(dagvtx, succ, dagvtx_succs(vtx))
475  if (!gen_in_list_p(succ, lconnex))
476  output = true;
477  if (output)
478  result = CONS(dagvtx, vtx, result);
479  }
480  return result;
481 }
482 
483 static list sigmac_get_component_inputs(list lconnex, dag dg) {
484  list result = NIL;
485  bool input;
486  FOREACH(dagvtx, v, lconnex) {
487  input = false;
488  if (!gen_length(dag_vertex_preds(dg, v)))
489  input = true;
490  FOREACH(dagvtx, pred, dag_vertex_preds(dg, v))
491  if (!gen_in_list_p(pred, lconnex))
492  input = true;
493  if (input)
494  result = CONS(dagvtx, v, result);
495  }
496  return result;
497 }
498 
499 static list sigmac_get_in_channels(list lconnex, dag dg) {
500  list inputs = sigmac_get_component_inputs(lconnex, dg);
501  list ext_inputs = NIL;
502  FOREACH(dagvtx, vtx, inputs) {
503  FOREACH(dagvtx, pred, dag_vertex_preds(dg, vtx)) {
504  if (!gen_in_list_p(pred, lconnex) && !gen_in_list_p(pred, ext_inputs))
505  ext_inputs = CONS(dagvtx, pred, ext_inputs);
506  }
507  }
508  return ext_inputs;
509 }
510 
511 static list sigmac_get_mergeable_ops(dag dg) {
512  _int nb_cc = 0; // counts the connex composants
513  hash_table ht_merge = hash_table_make(hash_pointer, 16);
514 
515  FOREACH(dagvtx, vtx, dag_vertices(dg)) {
516  const freia_api_t *api = get_freia_api_vtx(vtx);
517  if (api->sigmac.mergeable && !has_vtx_dynamic_params(vtx)) {
518  // search for mergeable vtx among successors
519  bool connex = false;
520  FOREACH(dagvtx, succ, dagvtx_succs(vtx)) {
521  if (get_freia_api_vtx(succ)->sigmac.mergeable &&
522  !has_vtx_dynamic_params(succ))
523  connex = true;
524  }
525  if (!connex)
526  nb_cc++;
527  hash_put(ht_merge, vtx, (void *)nb_cc);
528  }
529  }
530 
531  unsigned int min_thr = 2;
532  unsigned int max_thr = get_int_property("HWAC_SIGMAC_MERGE_ARITH");
533 
534  // filter hash_table:
535  // remove connex composants containing less than n vtx
536  set set_connex[nb_cc];
537  for (int i = 0; i < nb_cc; i++)
538  set_connex[i] = set_make(set_pointer);
539 
540  HASH_FOREACH(dagvtx, v, _int, i, ht_merge) {
541  set_add_element(set_connex[i - 1], set_connex[i - 1], v);
542  }
543  hash_table_free(ht_merge);
544 
545  list lresult = NIL;
546 
547  for (int i = 0; i < nb_cc; i++) {
548  unsigned int p = set_size(set_connex[i]); // TODO use weight
549  unsigned int g = (p + max_thr - 1) / max_thr;
550  unsigned int thr = (g > 0) ? p / g + (p % g > 0) : 0;
551  thr = (thr > 1) ? thr : max_thr;
552  if (p >= min_thr) {
553  list lconnex = NIL;
554 
555  FOREACH(dagvtx, v, dag_vertices(dg)) {
556  if (set_belong_p(set_connex[i], v)) {
557  if (gen_length(lconnex) == thr) {
558  lresult = CONS(list, lconnex, lresult);
559  lconnex = NIL;
560  }
561  lconnex = CONS(dagvtx, v, lconnex);
562  }
563  }
564  if (gen_length(lconnex) >= min_thr)
565  lresult = CONS(list, lconnex, lresult);
566  }
567  }
568  return lresult;
569 }
570 
571 static int ncompound = 0;
572 
573 static void sigmac_generate_compound_agent(string_buffer sb, list lconnex,
574  int n_connex, dag dg) {
575  list outputs = sigmac_get_component_outputs(lconnex, dg);
576  list ext_inputs = sigmac_get_in_channels(lconnex, dg);
577  unsigned int n_inputs = gen_length(ext_inputs);
578  unsigned int n_outputs = gen_length(outputs);
579  sb_prf(sb, "AGENT_MERGE_ARITH(agent_compound_%d_%d, " PIXEL_T, ncompound,
580  n_connex);
581  sb_prf(sb, ", %d, %d, \n", n_inputs, n_outputs);
582 
583  // print input assignments
584  unsigned int i;
585  for (i = 0; i < n_inputs; i++)
586  sb_prf(sb, " " PIXEL_T " pi%d = inp[%d][i];\n", i, i);
587 
588  // print calls to operations
589  int vtxn = 0;
590  FOREACH(dagvtx, vtx, lconnex) {
591  const freia_api_t *api = get_freia_api_vtx(vtx);
592  string op = strdup(api->sigmac.inst_prefix);
593  sb_prf(sb, " " PIXEL_T " po%d = ", vtxn++);
594  sb_prf(sb, "PIXEL_%s(", strupper(op, api->sigmac.inst_prefix));
595 
596  i = 0;
597  FOREACH(dagvtx, pred, dag_vertex_preds(dg, vtx)) {
598  if (gen_in_list_p(pred, lconnex)) {
599  sb_prf(sb, "po%d", gen_position(pred, lconnex) - 1);
600  } else {
601  // use pi%d variables
602  sb_prf(sb, "pi%d", gen_position(pred, ext_inputs) - 1);
603  }
604  if (i < gen_length(dag_vertex_preds(dg, vtx)) + api->arg_misc_in - 1)
605  sb_cat(sb, ", ");
606  i++;
607  }
608 
609  // get misc param values
611  int nparams = 0;
612  list vtx_param_vals = sc_get_params_values(vtx, hparams, &nparams);
613 
614  // print param values
615  i = 0;
616  FOREACH(expression, arg, vtx_param_vals) {
617  sb_prf(sb, "%s", expression_to_string(arg));
618  if (i < api->arg_misc_in - 1)
619  sb_cat(sb, ", ");
620  i++;
621  }
622 
623  sb_prf(sb, ");\n");
624  hash_table_free(hparams);
625  }
626 
627  // print output assignments
628  i = 0;
629  FOREACH(dagvtx, vtx, outputs) {
630  sb_prf(sb, " outp[%d][i] = po%d;\n", i++, gen_position(vtx, lconnex) - 1);
631  }
632 
633  sb_cat(sb, ");\n"
634  "\n");
635 
636  gen_free_list(outputs);
637  gen_free_list(ext_inputs);
638 }
639 
640 /*
641  */
642 static list get_succ_insts(dagvtx vtx, list lcomponents, dag dg,
643  hash_table htid) {
644  list res = NIL;
645  string_buffer succ_inst = string_buffer_make(true);
646  int vtxconnex = is_vtx_compound(vtx, lcomponents);
647  list used_components = NIL;
648 
649  FOREACH(dagvtx, succ, dagvtx_succs(vtx)) {
650  _int succconnex = is_vtx_compound(succ, lcomponents);
651  if (vtxconnex != -1 && succconnex == vtxconnex)
652  continue;
653 
654  else if (succconnex == -1) { // add succ
655  sb_prf(succ_inst, "%s.input", sc_vtx_tostring(succ, htid));
656  if (get_freia_api_vtx(succ)->arg_img_in > 1)
657  sb_prf(succ_inst, "[%d]", sc_get_port_id(vtx, succ, dg));
658  }
659 
660  else if (succconnex != -1) {
661  // add corresponding compound agent if not already connected
662  if (!gen_in_list_p((void *)succconnex, used_components)) {
663  used_components = CONS(int, succconnex, used_components);
664  sb_prf(
665  succ_inst, "cpd%"_intFMT
666  ".input[%d]",
667  succconnex,
668  gen_position(vtx, sigmac_get_in_channels(
669  LIST(gen_nth(succconnex, lcomponents)), dg)) -
670  1);
671  }
672  }
673  if (!string_buffer_empty_p(succ_inst))
674  res = CONS(string, string_buffer_to_string(succ_inst), res);
675  string_buffer_reset(succ_inst);
676  }
677 
678  if (gen_in_list_p(vtx, dag_outputs(dg))) { // add strout.input[%d]
679  sb_prf(succ_inst, "strout.input[%d] /* %s */",
680  gen_position(vtx, dag_outputs(dg)) - 1,
682  res = CONS(string, string_buffer_to_string(succ_inst), res);
683  }
684 
685  string_buffer_free(&succ_inst);
686  return res;
687 }
688 
689 static void sigmac_compile_subgraph(string module, dag dg, string fname,
690  int n_split, FILE *helper) {
691  fprintf(helper, "// code module=%s fname=%s split=%d\n", module, fname,
692  n_split);
693 
694  /*
695  * Variables used for SigmaC code generation
696  */
697 
699  string_buffer sb_new = string_buffer_make(true);
700  string_buffer sb_conn = string_buffer_make(true);
701  string_buffer sb_par = string_buffer_make(true);
702  string_buffer sb_cpd = string_buffer_make(true);
703  string_buffer sb_mor = string_buffer_make(true);
704 
705  // stores vtx instance id
707  // get a name for each vertex
708  sigmac_name_instances(dg, htid);
709 
710  // stores dagvtx parameters
712  int nparams = 0;
713  // declare dag constant parameters
714  sigmac_params_decl(sb_par, dg, hparams, &nparams);
715 
716  // detect mergeable arithmetic components
717  list lcomponents = NIL;
718  if (get_int_property("HWAC_SIGMAC_MERGE_ARITH"))
719  lcomponents = sigmac_get_mergeable_ops(dg);
720  _int n_connex = 0;
721  // instiantiate the compound agents
722  FOREACH(list, lconnex, lcomponents) {
723  sigmac_generate_compound_agent(sb_cpd, lconnex, n_connex++, dg);
724  }
725  list lcomponents_inst = NIL;
726 
727  // generate kernel specific morphological agents
728  if (get_bool_property("HWAC_SIGMAC_SPECIFIC_MORPHO"))
729  sc_kernel_specific_agent(sb_mor, hparams, dg);
730 
731  // some counters...
732  int nb_rep_nd = 0; // number of dup agents
733  int join_port_n = 0; // number of reduction scalar results
734  int split_port_n = 0; // number of dynamic parameters
735 
736  pips_assert("image size must be available",
737  get_int_property("FREIA_IMAGE_WIDTH") &&
738  get_int_property("FREIA_IMAGE_HEIGHT"));
739 
740  /* Main loop
741  * looping over the list of vertices of the given dag
742  */
743  FOREACH(dagvtx, v, dag_vertices(dg)) {
744 
745  const freia_api_t *f = get_freia_api_vtx(v);
746 
747  // test if current vtx part of one compound agent
748  n_connex = is_vtx_compound(v, lcomponents);
749 
750  // test if current vtx has dynamic parameters
751  bool dynamic_agent = has_vtx_dynamic_params(v);
752 
753  // instantiate current vtx - filter out input vtx
754  if (!same_string_p(dagvtx_operation(v), "undefined")) {
755  if (n_connex == -1) {
756  // if not compound, instantiate current dagvtx agent normally
758  sc_inst(sb_new, v, htid, NULL, NULL, dynamic_agent);
759  else
760  sc_inst(sb_new, v, htid, hparams, NULL, dynamic_agent);
761  } else { // if compound, only instantiate once
762  if (!gen_in_list_p((void *)n_connex, lcomponents_inst)) {
763  sb_prf(sb_new,
764  SIGMAC_INSTANTIATE("cpd%d", "agent_compound_%d_%d(width)"),
765  n_connex, ncompound, n_connex);
766  lcomponents_inst = CONS(int, n_connex, lcomponents_inst);
767  }
768  }
769  }
770 
771  // manipulate more easily instname.output
772  string_buffer sb_instoutp = string_buffer_make(true);
773  if (gen_in_list_p(v, dag_inputs(dg)))
774  sb_prf(sb_instoutp, "strin.output[%d] /* %s */",
775  gen_position(v, dag_inputs(dg)) - 1,
777  else if (n_connex == -1)
778  sb_prf(sb_instoutp, "%s.output", sc_vtx_tostring(v, htid));
779  else {
780  list comp_outps = sigmac_get_component_outputs(
781  LIST(gen_nth(n_connex, lcomponents)), dg);
782  sb_prf(sb_instoutp, "cpd%d.output[%d]", n_connex,
783  gen_position(v, comp_outps) - 1);
784  }
785  string instoutp = string_buffer_to_string(sb_instoutp);
786  string_buffer_free(&sb_instoutp);
787 
788  // deal with measure agents: connect to join
789  if (dagvtx_is_measurement_p(v)) {
790  unsigned int i;
791  if (f->arg_misc_out == 1)
792  sb_prf(sb_conn, SIGMAC_CONNECT("%s", "jo.input[%d]"), instoutp,
793  join_port_n++);
794  else if (f->arg_misc_out > 1)
795  for (i = 0; i < f->arg_misc_out; i++)
796  sb_prf(sb_conn, SIGMAC_CONNECT("%s[%d]", "jo.input[%d]"), instoutp, i,
797  join_port_n++);
798  }
799 
800  // deal with dynamic parameter dagvtx: connect to split
801  if (dynamic_agent) {
802  unsigned int i;
803  for (i = 0; i < f->arg_misc_in; i++) {
804  string s = "";
805  if (dagvtx_optype(v) == spoc_type_thr)
806  s = strdup(cat("[", i2a(i), "]"));
807  sb_prf(sb_conn, SIGMAC_CONNECT("sp.output[%d]", "%s.param%s"),
808  split_port_n++, sc_vtx_tostring(v, htid), s);
809  }
810  }
811 
812  // connect current vtx to its succs
813  list succ_insts = get_succ_insts(v, lcomponents, dg, htid);
814  if (gen_length(succ_insts) > 1) {
815  FOREACH(string, inst, succ_insts) {
816  sb_prf(sb_conn, SIGMAC_CONNECT("dup%d.output[%d]", "%s"), nb_rep_nd,
817  gen_position(inst, succ_insts) - 1, inst);
818  }
819  sb_prf(sb_conn, SIGMAC_CONNECT("%s", "dup%d.input"), instoutp, nb_rep_nd);
820  sb_prf(sb_new,
821  SIGMAC_INSTANTIATE("dup%d", REPLICATION_AGENT "(%d, width)"),
822  nb_rep_nd, gen_length(succ_insts));
823  nb_rep_nd++;
824  } else { // gen_length(succ_insts) <= 1
825  FOREACH(string, inst, succ_insts) { // auto cast to string
826  sb_prf(sb_conn, SIGMAC_CONNECT("%s", "%s"), instoutp, inst);
827  }
828  }
829 
830  } // FOREACH(dagvtx, v, dg)
831 
832  string subgraph_name = strdup(cat(fname, "_", i2a(n_split)));
833  sc_delimiter(sb, strdup(cat(subgraph_name, " Subgraph")));
834 
835  // compound agent declaration
837 
838  // kernel specific morpho agent declaration
840 
841  // subgraph header and pipe agents declaration
842  sc_subgraph_app(sb, subgraph_name, gen_length(dag_inputs(dg)),
843  gen_length(dag_outputs(dg)), split_port_n, join_port_n);
844 
845  // append the parameter declarations
846  sb_cat(sb, "\n // parameters declaration...\n");
848 
849  // append the instantiation statements in reverse order
850  sb_cat(sb_new, " // instantiations...\n");
851  sb_cat(sb_new, "\n");
853  sb_cat(sb, "\n");
854 
855  // append the connection statements
856  sb_cat(sb_conn, " // connections...\n");
858  sb_cat(sb, " }\n}\n");
859 
860  string_buffer_to_file(sb, helper);
861  fprintf(helper, "\n");
862 
863 #ifdef DEBUG_INFO
864  FOREACH(dagvtx, v, dag_vertices(dg)) {
865  fprintf(helper, "vtx %"_intFMT
866  ", op %s,",
868  dagvtx_nb_dump(helper, " succs", dagvtx_succs(v));
869  }
870  dag_dump(helper, "hello", dg);
871 #endif
872 
873  ncompound++;
874  /*
875  * Memory cleanup
876  */
878  string_buffer_free(&sb_new);
879  string_buffer_free(&sb_conn);
880  string_buffer_free(&sb_par);
881  string_buffer_free(&sb_cpd);
882  string_buffer_free(&sb_mor);
883 
884  hash_table_free(htid);
885  hash_table_free(hparams);
886 
887  FOREACH(list, lconnex, lcomponents)
888  gen_free_list(lconnex);
889  gen_free_list(lcomponents);
890 }
891 
892 #define SIGMAC_HELPER "freia_mppa_launch"
893 
894 /* call this helper for dag d
895  * ??? currently non constant parameters are NOT handled at all.
896  */
897 static void sigmac_call_helper(dag d, int helper) {
898  int n_inputs = gen_length(dag_inputs(d));
899  int n_outputs = gen_length(dag_outputs(d));
900 
901  list lpin = NIL;
902  list lpout = NIL;
903 
904  FOREACH(dagvtx, v, dag_vertices(d)) {
905  // pass dynamic arguments of *_const agents
906  if (strstr(get_freia_api_vtx(v)->function_name, "_const")) {
908  FOREACH(expression, paramin, vtx_params) {
909  if (is_param_dynamic(paramin))
910  lpin = CONS(expression, paramin, lpin);
911  }
912  }
913 
914  // pass arguments of thresholder_dyn agent
917  FOREACH(expression, paramin, vtx_params) {
918  lpin = CONS(expression, paramin, lpin);
919  }
920  }
921 
922  // return result of measure agents
925  }
926  lpin = gen_nreverse(lpin);
927 
928  list largs = gen_make_list(
931  int_to_expression(gen_length(lpout)), NULL);
932  list lin = NIL;
933  FOREACH(dagvtx, v, dag_inputs(d)) {
934  entity in = dagvtx_image(v);
935  if (in)
936  lin = CONS(expression, entity_to_expression(in), lin);
937  }
938  lin = gen_nreverse(lin);
939 
940  list lout = NIL;
941  FOREACH(dagvtx, v, dag_outputs(d)) {
942  entity out = dagvtx_image(v);
943  if (out)
944  lout = CONS(expression, entity_to_expression(out), lout);
945  }
946  lout = gen_nreverse(lout);
947 
948  largs = gen_nconc(largs, lin);
949  largs = gen_nconc(largs, lout);
950  largs = gen_nconc(largs, lpin);
951  largs = gen_nconc(largs, lpout);
952 
953  // rough...
954  bool call_inserted = false;
955  FOREACH(dagvtx, v, dag_vertices(d)) {
956  _int op = dagvtx_opid(v);
957  if (op == 0)
958  continue;
959  statement st = dagvtx_statement(v);
960  if (call_inserted)
961  hwac_replace_statement(st, freia_ok(), true);
962  else {
964  if (entity_undefined_p(sc_helper))
966  hwac_replace_statement(st, make_call(sc_helper, largs), false);
967  call_inserted = true;
968  }
969  }
970 }
971 
972 /*#######################################################################*/
973 /*#######################################################################*/
974 /*#######################################################################*/
975 
976 // global string_buffer, stores the subgraph calls
977 static string_buffer subg_calls;
978 
979 #define N_PREDEFINED_CONTROLLERS 5
980 
981 static void print_subgraph_calls(string fname, int n_split, int n_dags) {
982  /* we generate an application subgraph with 4 pipes
983  * for every independant dag
984  */
985  sb_prf(subg_calls, " new %s_%d\n"
986  " (pipes[%d], pipes[%d],\n"
987  " width, height, sizeMax,\n"
988  " pipes[%d], pipes[%d]);\n"
989  "\n",
990  fname, n_split, 4 * n_dags + 2 * N_PREDEFINED_CONTROLLERS,
991  4 * n_dags + 2 * N_PREDEFINED_CONTROLLERS + 1,
992  4 * n_dags + 2 * N_PREDEFINED_CONTROLLERS + 2,
993  4 * n_dags + 2 * N_PREDEFINED_CONTROLLERS + 3);
994 }
995 
996 #define MAIN_PATH "cd .. && ./main"
997 
998 /* Generate a root subgraph (equivalent of the main function)
999  * which initialize the image data
1000  * and calls the application subgraphs
1001  */
1002 static void sc_subgraph_root(FILE *sigmac_helper, int n_graphs) {
1004  sc_delimiter(sb, "Subgraph Root");
1005 
1006  sb_prf(sb, "subgraph root () {\n"
1007  " map {\n"
1008  " int width = %d, height = %d;\n"
1009  " size_t sizeMax = width * height * sizeof(" PIXEL_T ");\n"
1010  "\n",
1011  get_int_property("FREIA_IMAGE_WIDTH"),
1012  get_int_property("FREIA_IMAGE_HEIGHT"));
1013 
1014  string exec_path = MAIN_PATH;
1015  sb_cat(sb, " char cmd[255] = \"", exec_path, "\";\n");
1016 
1017  /* two i/o pipes for each predefined controller and
1018  * four for each dag (2 for images i/o, 2 for parameters i/o)
1019  */
1020  int n_pipes = 2 * N_PREDEFINED_CONTROLLERS + 4 * n_graphs;
1021 
1022  sb_prf(sb, " int i, n_pipes = %d;\n", n_pipes);
1023  sb_cat(sb, " char pipes[n_pipes][255];\n"
1024  " for (i=0; i<n_pipes; i++)\n"
1025  " tmpnam(pipes[i]);\n"
1026  "\n"
1027 
1028  " agent pp = new Pipes(cmd, n_pipes, pipes);\n"
1029  " agent sk = new Sink<char>(1);\n"
1030  " SigmaC_agent_setUnitType(sk, \"native\");\n"
1031  " connect(pp.output, sk.input);\n\n"
1032 
1033  /* we only need one instance of the following agents
1034  * because several commands can be sent throughout the same pipe
1035  */
1036  " new Malloc(pipes[0], pipes[1]);\n"
1037  " new Free(pipes[2], pipes[3]);\n"
1038  " new MCopy(pipes[4], pipes[5]);\n"
1039  " new SendDataToMPPA(pipes[6], pipes[7], sizeMax);\n"
1040  " new SendDataToHost(pipes[8], pipes[9], sizeMax);\n"
1041  "\n");
1042 
1043  // insert subgraph calls
1044  sb_cat(sb, string_buffer_to_string(subg_calls));
1045  sb_cat(sb, " }\n}\n");
1046 
1047  string_buffer_to_file(sb, sigmac_helper);
1048 
1049  string_buffer_free(&subg_calls);
1051 }
1052 
1053 /*
1054  @brief compile one dag with AIPO optimizations
1055  @param ls statements underlying the full dag
1056  @param occs image occurences
1057  @param exchanges statements to exchange because of dependences
1058  @return the list of allocated intermediate images
1059 */
1060 list freia_sigmac_compile_calls(string module, dag fulld, sequence sq, list ls,
1061  const hash_table occs, hash_table exchanges,
1062  const set output_images,
1063  // for launchers...
1064  __attribute__((__unused__)) FILE *helper_file,
1065  __attribute__((__unused__)) set helpers,
1066  int number, int n_calls) {
1067  pips_debug(3, "considering %d statements\n", (int)gen_length(ls));
1068  pips_assert("some statements", ls);
1069 
1070  // allocate file for sigmac stuff
1071  string sigmac_file_name = helper_file_name(module, "sc");
1072  FILE *sigmac_file = safe_fopen(sigmac_file_name, "a");
1073 
1074  // SigmaC includes
1075  if (n_dags == 0) {
1076  fprintf(sigmac_file, FREIA_SIGMAC_SC_INCLUDES);
1077  subg_calls = string_buffer_make(true);
1078  }
1079 
1080  // intermediate images
1082  list new_images = dag_fix_image_reuse(fulld, init, occs);
1083 
1084  // about aipo statistics: no helper file to put them...
1085  list added_before = NIL, added_after = NIL;
1086  freia_dag_optimize(fulld, exchanges, &added_before, &added_after);
1087 
1088  // dump final optimised dag
1089  dag_dot_dump_prefix(module, "dag_cleaned_", number, fulld, added_before,
1090  added_after);
1091 
1092  string fname_fulldag = strdup(cat(module, "_sigmac", HELPER, i2a(number)));
1093 
1094  list ld = dag_split_on_scalars(fulld, NULL, NULL,
1095  (gen_cmp_func_t)dagvtx_sigmac_priority, NULL,
1096  output_images);
1097 
1098  pips_debug(3, "dag initial split in %d dags\n", (int)gen_length(ld));
1099 
1100  int n_split = 0;
1101 
1102  set stats = set_make(set_pointer), dones = set_make(set_pointer);
1103 
1104  FOREACH(dag, d, ld) {
1105  if (dag_no_image_operation(d))
1106  continue;
1107 
1108  // fix statements connexity
1109  dag_statements(stats, d);
1110  freia_migrate_statements(sq, stats, dones);
1111  set_union(dones, dones, stats);
1112 
1113  // helper_file?
1114  sigmac_compile_subgraph(module, d, fname_fulldag, n_split, sigmac_file);
1115  print_subgraph_calls(fname_fulldag, n_split, n_dags);
1116  sigmac_call_helper(d, n_dags);
1117 
1118  n_split++;
1119  n_dags++;
1120  }
1121 
1122  // generate the subgraph root which will launch the application
1123  if (number == n_calls - 1)
1124  sc_subgraph_root(sigmac_file, n_dags);
1125 
1126  set_free(stats);
1127  set_free(dones);
1128 
1129  // now may put actual allocations, which messes up statement numbers
1130  list reals =
1131  freia_allocate_new_images_if_needed(ls, new_images, occs, init, NULL);
1132 
1133  // ??? should it be NIL because it is not useful in AIPO->AIPO?
1134  freia_insert_added_stats(ls, added_before, true);
1135  added_before = NIL;
1136  freia_insert_added_stats(ls, added_after, false);
1137  added_after = NIL;
1138 
1139  // cleanup
1140  gen_free_list(new_images);
1142  fclose(sigmac_file);
1143  free(sigmac_file_name);
1144 
1145  return reals;
1146 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
int get_int_property(const string)
call make_call(entity a1, list a2)
Definition: ri.c:269
static FILE * out
Definition: alias_check.c:128
void const char const char const int
static graph dg
dg is the dependency graph ; FIXME : should not be static global ?
Definition: chains.c:124
_int dagvtx_optype(const dagvtx v)
Definition: dag-utils.c:116
list dag_vertex_preds(const dag d, const dagvtx target)
return target predecessor vertices as a list.
Definition: dag-utils.c:680
_int dagvtx_number(const dagvtx v)
returns the vertex number, i.e.
Definition: dag-utils.c:98
void dagvtx_nb_dump(FILE *out, const string what, const list l)
Definition: dag-utils.c:176
bool dag_no_image_operation(dag d)
tell whether we have something to do with images ??? hmmm...
Definition: dag-utils.c:2500
list dag_split_on_scalars(const dag initial, bool(*alone_only)(const dagvtx), dagvtx(*choose_vertex)(const list, bool), gen_cmp_func_t priority, void(*priority_update)(const dag), const set output_images)
split a dag on scalar dependencies only, with a greedy heuristics.
Definition: dag-utils.c:2823
list dag_fix_image_reuse(dag d, hash_table init, const hash_table occs)
fix intermediate image reuse in dag
Definition: dag-utils.c:2779
bool dagvtx_is_measurement_p(const dagvtx v)
returns whether the vertex is an image measurement operation.
Definition: dag-utils.c:623
entity dagvtx_image(const dagvtx v)
return the produced image or NULL
Definition: dag-utils.c:82
void dag_dump(FILE *out, const string what, const dag d)
for dag debug
Definition: dag-utils.c:212
void freia_dag_optimize(dag d, hash_table exchanges, list *lbefore, list *lafter)
remove dead image operations.
Definition: dag-utils.c:1416
string dagvtx_operation(const dagvtx v)
Definition: dag-utils.c:134
statement dagvtx_statement(const dagvtx v)
return statement if any, or NULL (for input nodes).
Definition: dag-utils.c:56
_int dagvtx_opid(const dagvtx v)
Definition: dag-utils.c:121
void dag_statements(set stats, const dag d)
build the set of actual statements in d
Definition: dag-utils.c:64
void dag_dot_dump_prefix(const string module, const string prefix, int number, const dag d, const list lb, const list la)
Definition: dag-utils.c:504
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
entity freia_create_helper_function(const string function_name, list lparams)
Definition: freia-utils.c:1030
string helper_file_name(string func_name, string suffix)
return malloc'ed "foo.database/Src/%{module}_helper_functions.c" should it depend on the target?...
Definition: freia-utils.c:2029
list freia_get_vertex_params(const dagvtx v)
Definition: freia-utils.c:578
list freia_extract_params(const int napi, list args, string_buffer head, string_buffer head2, hash_table params, int *nparams)
returns an allocated expression list of the parameters only (i.e.
Definition: freia-utils.c:613
list freia_allocate_new_images_if_needed(list ls, list images, const hash_table occs, const hash_table init, const hash_table signatures)
insert image allocation if needed, for intermediate image inserted before if an image is used only tw...
Definition: freia-utils.c:1650
void freia_migrate_statements(sequence sq, const set stats, const set before)
Definition: freia-utils.c:1905
void hwac_replace_statement(statement s, call newc, bool kill)
replace statement contents with call to c, or continue if kill
Definition: freia-utils.c:720
bool freia_convolution_p(dagvtx v)
is it the convolution special case?
Definition: freia-utils.c:1441
bool freia_extract_kernel_vtx(dagvtx v, bool strict, intptr_t *k00, intptr_t *k10, intptr_t *k20, intptr_t *k01, intptr_t *k11, intptr_t *k21, intptr_t *k02, intptr_t *k12, intptr_t *k22)
vertex-based version
Definition: freia-utils.c:2012
call freia_ok(void)
build all is well freia constant
Definition: freia-utils.c:695
call freia_statement_to_call(const statement s)
return the actual function call from a statement, dealing with assign and returns....
Definition: freia-utils.c:973
void freia_insert_added_stats(list ls, list stats, bool before)
insert statements to actual code sequence in "ls" BEWARE that ls is assumed to be in reverse order....
Definition: freia-utils.c:1185
const freia_api_t * get_freia_api_vtx(dagvtx v)
Definition: freia-utils.c:483
#define cat(args...)
Definition: freia.h:41
#define sb_prf(args...)
Definition: freia.h:43
#define HELPER
Definition: freia.h:38
#define sb_cat(args...)
Definition: freia.h:42
static void sc_delimiter(string_buffer sb, const string title)
Generate a 3 lines commented code delimiter with a centered title.
Definition: freia_sigmac.c:351
static void sigmac_params_decl(string_buffer sb_par, dag dg, hash_table hparams, int *pnparams)
Generates the constant parameters declaration.
Definition: freia_sigmac.c:211
#define N_PREDEFINED_CONTROLLERS
static void sc_kernel_specific_agent(string_buffer sb_morpho, hash_table hparams, const dag dg)
Definition: freia_sigmac.c:187
#define MAIN_PATH
static bool sc_print_kernel(string_buffer sb_par, dagvtx v)
Print the value of a morphological kernel extracted from a dagvtx.
Definition: freia_sigmac.c:143
static int n_dags
Definition: freia_sigmac.c:56
#define SIGMAC_HELPER
static bool has_vtx_dynamic_params(dagvtx v)
Determine if a dagvtx has at least one dynamic parameter.
Definition: freia_sigmac.c:113
#define SIGMAC_INSTANTIATE(a, b)
Definition: freia_sigmac.c:51
static void sigmac_name_instances(dag dg, hash_table htid)
Populates the hash table htid: one dagvtx is linked to an unique id depending on its freia_api_t.
Definition: freia_sigmac.c:61
static bool is_param_dynamic(expression arg)
Determine if an argument contains references to other variables (dirty hack based on isalpha)
Definition: freia_sigmac.c:101
static list sc_get_params_values(dagvtx vtx, hash_table hparams, int *nparams)
Returns a list of values of one dagvtx misc input parameters.
Definition: freia_sigmac.c:130
static int sc_get_port_id(dagvtx current_vtx, dagvtx succ, dag dg)
Helper function determine the input port of the succ dagvtx to be connected to the output port of cur...
Definition: freia_sigmac.c:344
#define SIGMAC_CONNECT(a, b)
Definition: freia_sigmac.c:52
static string sc_vtx_tostring(const dagvtx v, const hash_table htid)
Generate a unique string per dagvtx consisting in.
Definition: freia_sigmac.c:92
#define REPLICATION_AGENT
Definition: freia_sigmac.c:53
static void sc_inst(string_buffer sb, const dagvtx v, const hash_table htid, const hash_table hparams, string miscparams, bool is_dynamic)
Generate the instanciation of an agent in the forme "agent instname = new agentname (parameters)".
Definition: freia_sigmac.c:281
static bool sc_kernel_compute_loop(string_buffer sb_morpho, const dagvtx vtx, string kname)
Print a kernel customized inner loop from a morphological kernel.
Definition: freia_sigmac.c:157
#define FREIA_SIGMAC_SC_INCLUDES
Definition: freia_sigmac.h:32
#define PARAM_T
Definition: freia_sigmac.h:61
#define PIXEL_T
Definition: freia_sigmac.h:60
@ spoc_type_thr
Definition: freia_spoc.h:178
@ spoc_type_poc
Definition: freia_spoc.h:176
#define dagvtx_content(x)
#define dag_outputs(x)
#define pstatement_statement(x)
#define dag_inputs(x)
#define dagvtx_succs(x)
#define dag_vertices(x)
#define vtxcontent_source(x)
#define LIST(x)
Definition: genC.h:93
static int input(void)
void free(void *)
list gen_make_list(int domain,...)
Definition: list.c:851
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
int gen_position(const void *item, const list l)
Element ranks are strictly positive as for first, second, and so on.
Definition: list.c:995
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
list freia_sigmac_compile_calls(string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int, int)
freia_sigmac.c
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
string strupper(string, const char *)
Definition: string.c:213
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#define same_string_p(s1, s2)
int set_size(const set)
returns the number of items in s.
Definition: set.c:359
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
set set_union(set, const set, const set)
Definition: set.c:211
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
string string_buffer_to_string(const string_buffer)
return malloc'ed string from string buffer sb
void string_buffer_to_file(const string_buffer, FILE *)
put string buffer into file.
void string_buffer_free(string_buffer *)
free string buffer structure, also free string contents according to the dup field
Definition: string_buffer.c:82
void string_buffer_reset(string_buffer)
remove stack contents
Definition: string_buffer.c:70
string_buffer string_buffer_make(bool dup)
allocate a new string buffer
Definition: string_buffer.c:58
bool string_buffer_empty_p(const string_buffer)
return whether string_buffer sb is empty.
string string_buffer_to_string_reverse(const string_buffer)
return malloc'ed string from string buffer sb going from bottom to top
#define _intFMT
Definition: newgen_types.h:57
char * string
STRING.
Definition: newgen_types.h:39
intptr_t _int
_INT
Definition: newgen_types.h:53
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
string expression_to_string(expression e)
Definition: expression.c:77
list lparams
Array bounds.
Definition: reindexing.c:111
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define call_arguments(x)
Definition: ri.h:711
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define intptr_t
Definition: stdint.in.h:294
internally defined structure.
Definition: string_buffer.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
FREIA API function name -> SPoC hardware description (and others?)
Definition: freia.h:71
unsigned int arg_misc_in
Definition: freia.h:83
sigmac_hw_t sigmac
Definition: freia.h:92
Definition: statement.c:4047
string inst_prefix
Definition: freia_sigmac.h:52
bool mergeable
Definition: freia_sigmac.h:55