PIPS
freia-utils.c
Go to the documentation of this file.
1 /*
2 
3  $Id: freia-utils.c 23495 2018-10-24 09:19:47Z coelho $
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 
32 #include "genC.h"
33 #include "misc.h"
34 #include "freia.h"
35 #include "freia_spoc.h"
36 
37 #include "linear.h"
38 
39 #include "ri.h"
40 #include "effects.h"
41 #include "ri-util.h"
42 #include "effects-util.h"
43 #include "properties.h"
44 #include "pipsdbm.h"
45 
46 #include "freia_spoc_private.h"
47 #include "hwac.h"
48 
49 // help reduce code size:
50 #define T true
51 #define F false
52 
53 #define NO_POC { { spoc_poc_unused, 0 }, { spoc_poc_unused, 0 } }
54 #define NO_MES { measure_none, measure_none }
55 
56 // no operation
57 #define NOPE_SPOC { spoc_nothing, NO_POC, alu_unused, NO_MES }
58 #define NOPE_TRPX { 0, 0, 0, 0, 0, 0, false, false, NULL }
59 #define NOPE_OPCL { F, F, NULL, NULL }
60 #define NOPE_SIGMAC { "Id", "nop", "width, height", F, 0 }
61 #define NOPE_MPPA {"MPPA_KERNEL_NOP"}
62 
63 // not implemented
64 #define NO_SPOC { spoc_not_implemented, NO_POC, alu_unused, NO_MES }
65 #define NO_TRPX { 0, 0, 0, 0, 0, -1, false, false, NULL }
66 #define NO_OPCL { F, F, NULL, NULL }
67 #define NO_SIGMAC { "not_implemented", NULL, NULL, F, 0 }
68 #define NO_MPPA {"MPPA_KERNEL_NOP"}
69 
70 #define TRPX_OP(c, op) { 0, 0, 0, 0, 0, c, true, false, "TERAPIX_UCODE_" op }
71 #define TRPX_IO(c, op) { 0, 0, 0, 0, 0, c, true, true, "TERAPIX_UCODE_" op }
72 #define TRPX_NG(c, op) { 1, 1, 1, 1, 0, c, false, false, "TERAPIX_UCODE_" op }
73 
74 // preliminary stuff for volume/min/max/...
75 #define TRPX_MS(m, c, op) { 0, 0, 0, 0, m, c, true, false, "TERAPIX_UCODE_" op }
76 
77 #define OPCL(op) { T, F, "PIXEL_" op, NULL }
78 #define OPCLK(op,init) { F, T, "PIXEL_" op, "PIXEL_" init }
79 
80 #define SGC_W(ag, pref) { #ag, #pref, "width", T, 1 }
81 #define SGC_WH(ag, pref) { #ag, #pref, "width, height", F, 0 }
82 
83 #define MPPA(kernel) {#kernel}
84 
85 // types used by AIPO parameters
86 #define TY_INT "int32_t"
87 #define TY_PIN "int32_t *"
88 #define TY_CIP "const int32_t *"
89 #define TY_UIN "uint32_t"
90 #define TY_PUI "uint32_t *"
91 
92 #define NO_PARAM { NULL, NULL, NULL }
93 // this may be moved into some "hwac_freia.[hc]"
94 /* !!! there are some underlying assumptions when using this structure:
95  * only one of ALU/POC/MES is used per AIPO.
96  * only the first of two POC or MES is used per AIPO.
97  * ??? conversions between 8/16 bits images are definitely not handled here.
98  */
99 static const freia_api_t FREIA_AIPO_API[] = {
100  { "undefined", "?", NULL, 0, 0, 0, 0, NO_PARAM, NO_PARAM,
102  },
103  {
104  // ARITHMETIC
105  // binary
106  AIPO "add", "+", AIPO "add", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
107  // spoc_hw_t
108  {
109  // parts used...
111  // poc[2]
112  NO_POC,
113  // alu
114  alu_add,
115  // global measures
116  NO_MES
117  },
118  TRPX_OP(4, "ADD3"),
119  OPCL("ADD"),
120  SGC_W(img_add_img_16, add),
121  MPPA(MPPA_KERNEL_ADD)
122  },
123  { AIPO "sub", "-", NULL, 1, 2, 0, 0, NO_PARAM, NO_PARAM,
125  NO_POC, alu_sub_01, NO_MES }, TRPX_OP(4, "SUB3"), OPCL("SUB"),
126  SGC_W(img_sub_img_16, sub),
127  MPPA(MPPA_KERNEL_SUB)
128  },
129  { AIPO "mul", "*", AIPO "mul", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
131  NO_POC, alu_mul, NO_MES }, TRPX_OP(4, "MUL3"), OPCL("MUL"),
132  SGC_W(img_mul_img_16, mul),
133  MPPA(MPPA_KERNEL_MUL)
134  },
135  { AIPO "div", "/", NULL, 1, 2, 0, 0, NO_PARAM, NO_PARAM,
137  NO_POC, alu_div_01, NO_MES }, TRPX_OP(4, "DIV3"), OPCL("DIV"),
138  SGC_W(img_div_img_16, div),
139  MPPA(MPPA_KERNEL_DIV)
140  },
141  { AIPO "addsat", "+s", AIPO "addsat", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
143  NO_POC, alu_addsat, NO_MES }, TRPX_OP(4, "ADDSAT"), OPCL("ADDSAT"),
144  SGC_W(img_addsat_img_16, addsat),
145  MPPA(MPPA_KERNEL_ADDSAT)
146  },
147  { AIPO "subsat", "-s", NULL, 1, 2, 0, 0, NO_PARAM, NO_PARAM,
149  NO_POC, alu_subsat_01, NO_MES }, TRPX_OP(4, "SUBSAT"), OPCL("SUBSAT"),
150  SGC_W(img_subsat_img_16, subsat),
151  MPPA(MPPA_KERNEL_SUBSAT)
152  },
153  { AIPO "absdiff", "-|", AIPO "absdiff", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
155  NO_POC, alu_abssub, NO_MES }, TRPX_OP(4, "ABS_DIFF3"), OPCL("ABSDIFF"),
156  SGC_W(img_absdiff_img_16, absd),
157  MPPA(MPPA_KERNEL_ABSDIFF)
158  },
159  { AIPO "inf", "<", AIPO "inf", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
161  NO_POC, alu_inf_01, NO_MES }, TRPX_OP(4, "INF3"), OPCL("INF"),
162  SGC_W(img_inf_img_16, inf),
163  MPPA(MPPA_KERNEL_INF)
164  },
165  { AIPO "sup", ">", AIPO "sup", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
167  NO_POC, alu_sup_01, NO_MES }, TRPX_OP(4, "SUP3"), OPCL("SUP"),
168  SGC_W(img_sup_img_16, sup),
169  MPPA(MPPA_KERNEL_SUP)
170  },
171  { AIPO "and", "&", AIPO "and", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
173  NO_POC, alu_and, NO_MES }, TRPX_OP(4, "AND3"), OPCL("AND"),
174  SGC_W(img_and_img_16, and),
175  MPPA(MPPA_KERNEL_AND)
176  },
177  { AIPO "or", "|", AIPO "or", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
179  NO_POC, alu_or, NO_MES }, TRPX_OP(4, "OR3"), OPCL("OR"),
180  SGC_W(img_or_img_16, or),
181  MPPA(MPPA_KERNEL_OR)
182  },
183  { AIPO "xor", "^", AIPO "xor", 1, 2, 0, 0, NO_PARAM, NO_PARAM,
185  NO_POC, alu_xor, NO_MES }, TRPX_OP(4, "XOR3"), OPCL("XOR"),
186  SGC_W(img_xor_img_16, xor),
187  MPPA(MPPA_KERNEL_XOR)
188  },
189  { AIPO "mask", "m", NULL, 1, 2, 0, 0, NO_PARAM, NO_PARAM,
191  NO_POC, alu_mask_0, NO_MES }, TRPX_OP(4, "MASK3"), OPCL("MASK"),
192  SGC_W(img_mask_img_16, mask),
193  MPPA(MPPA_KERNEL_MASK)
194  },
195  { AIPO "replace_const", ":", AIPO "replace_const",
196  1, 2, 0, 1, NO_PARAM, { TY_INT, NULL, NULL},
198  NO_POC, alu_repcst_0, NO_MES }, TRPX_IO(3, "CONV_REPLACE_EQ_CONST"),
199  OPCL("REPLACE_EC"),
200  SGC_W(img_replace_const, replc),
201  MPPA(MPPA_KERNEL_REPLACE_CONST)
202  },
203  // unary
204  { AIPO "not", "!", NULL, 1, 1, 0, 0, NO_PARAM, NO_PARAM,
206  // ??? why not less?
207  TRPX_OP(4, "NOT"), OPCL("NOT"),
208  SGC_W(img_invert_16, not),
209  MPPA(MPPA_KERNEL_NOT)
210  },
211  { AIPO "log2", "l2", NULL, 1, 1, 0, 0, NO_PARAM, NO_PARAM,
213  TRPX_OP(3, "LOG2"), OPCL("LOG2"),
214  SGC_W(img_log2_16, log2),
215  MPPA(MPPA_KERNEL_LOG2)
216  },
217  { AIPO "add_const", "+_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
219  TRPX_OP(3, "ADD_CONST"), OPCL("ADD"),
220  SGC_W(img_add_const_16, addc),
221  MPPA(MPPA_KERNEL_ADD_CONST)
222  },
223  { AIPO "inf_const", "<_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
225  TRPX_OP(3, "INF_CONST"), OPCL("INF"),
226  SGC_W(img_inf_const_16, infc),
227  MPPA(MPPA_KERNEL_INF_CONST)
228  },
229  { AIPO "sup_const", ">_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
231  TRPX_OP(3, "SUP_CONST"), OPCL("SUP"),
232  SGC_W(img_sup_const_16, supc),
233  MPPA(MPPA_KERNEL_SUP_CONST)
234  },
235  { AIPO "sub_const", "-_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
237  TRPX_OP(3, "SUB_CONST"), OPCL("SUB"),
238  SGC_W(img_sub_const_16, subc),
239  MPPA(MPPA_KERNEL_SUB_CONST)
240  },
241  { AIPO "const_sub", "_-", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
243  TRPX_OP(3, "CONST_SUB"), OPCL("SUBC"),
244  SGC_W(img_const_sub_16, csub),
245  MPPA(MPPA_KERNEL_CONST_SUB)
246  },
247  { AIPO "and_const", "&_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
249  TRPX_OP(3, "AND_CONST"), OPCL("AND"),
250  SGC_W(img_and_const_16, andc),
251  MPPA(MPPA_KERNEL_AND_CONST)
252  },
253  { AIPO "or_const", "|_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
255  TRPX_OP(3, "OR_CONST"), OPCL("OR"),
256  SGC_W(img_or_const_16, orc),
257  MPPA(MPPA_KERNEL_OR_CONST)
258  },
259  { AIPO "xor_const", "^_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
261  TRPX_OP(3, "XOR_CONST"), OPCL("XOR"),
262  SGC_W(img_xor_const_16, xorc),
263  MPPA(MPPA_KERNEL_XOR_CONST)
264  },
265  { AIPO "addsat_const", "+s_", NULL, 1, 1, 0, 1, NO_PARAM,
266  { TY_INT, NULL, NULL },
268  TRPX_OP(3, "ADDSAT_CONST"), OPCL("ADDSAT"),
269  SGC_W(img_addsat_const_16, addsatc),
270  MPPA(MPPA_KERNEL_ADDSAT_CONST)
271  },
272  { AIPO "subsat_const", "-s_", NULL, 1, 1, 0, 1, NO_PARAM,
273  { TY_INT, NULL, NULL },
275  TRPX_OP(3, "SUBSAT_CONST"), OPCL("SUBSAT"),
276  SGC_W(img_subsat_const_16, subsatc),
277  MPPA(MPPA_KERNEL_SUBSAT_CONST)
278  },
279  { AIPO "const_subsat", "_-s", NULL, 1, 1, 0, 1, NO_PARAM,
280  { TY_INT, NULL, NULL },
282  TRPX_OP(3, "CONST_SUBSAT"), OPCL("SUBSATC"),
283  SGC_W(img_const_subsat_16, csubsat),
284  MPPA(MPPA_KERNEL_CONST_SUBSAT)
285  },
286  { AIPO "absdiff_const", "-|_", NULL, 1, 1, 0, 1, NO_PARAM,
287  { TY_INT, NULL, NULL },
289  TRPX_OP(3, "ABSDIFF_CONST"), OPCL("ABSDIFF"),
290  SGC_W(img_absdiff_const_16, absdc),
291  MPPA(MPPA_KERNEL_ABSDIFF_CONST)
292  },
293  { AIPO "mul_const", "*_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
295  TRPX_OP(3, "MUL_CONST"), OPCL("MUL"),
296  SGC_W(img_mul_const_16, mulcst),
297  MPPA(MPPA_KERNEL_MUL_CONST)
298  },
299  { AIPO "div_const", "/_", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
301  TRPX_OP(3, "DIV_CONST"), OPCL("DIV"),
302  SGC_W(img_div_const_16, divc),
303  MPPA(MPPA_KERNEL_DIV_CONST)
304  },
305  { AIPO "const_div", "_/", NULL, 1, 1, 0, 1, NO_PARAM, { TY_INT, NULL, NULL },
307  TRPX_OP(3, "CONST_DIV"), OPCL("DIVC"),
308  SGC_W(img_const_div_16, cdiv),
309  MPPA(MPPA_KERNEL_CONST_DIV)
310  },
311  // nullary
312  { AIPO "set_constant", "C", NULL, 1, 0, 0, 1, NO_PARAM, { TY_INT, NULL, NULL},
314  TRPX_OP(2, "SET_CONST"), OPCL("SET"),
315  SGC_W(img_set_constant_16, setc),
316  MPPA(MPPA_KERNEL_SET_CONST)
317  },
318  // not a real one, this is used internally only
319  // semantics of "scalar_copy(a, b);" is "*a = *b;"
320  { AIPO "scalar_copy", "?=", NULL, 0, 0, 1, 1, NO_PARAM,
321  { TY_INT, TY_INT, NULL},
323  },
324  // MISC
325  // this one may be ignored?!
326  { AIPO "copy", "=", NULL, 1, 1, 0, 0, NO_PARAM, NO_PARAM,
327  // hmmm... would NO_SPOC do?
329  TRPX_OP(3, "COPY"), OPCL("COPY"), NOPE_SIGMAC,
330  MPPA(MPPA_KERNEL_COPY)
331  },
332  { // not implemented by SPOC! nor TERAPIX!
333  AIPO "cast", "=()", NULL, 1, 1, 0, 0, NO_PARAM, NO_PARAM,
335  },
336  { AIPO "threshold", "thr", NULL, 1, 1, 0, 3, NO_PARAM,
337  { TY_INT, TY_INT, TY_INT },
339  TRPX_OP(5, "THRESHOLD"), OPCL("THRESHOLD"),
340  SGC_W(thresholder, thr),
341  MPPA(MPPA_KERNEL_THRESHOLD)
342  },
343  // MORPHO
344  { AIPO "erode_6c", "E6", NULL, 1, 1, 0, 1, NO_PARAM, { TY_CIP, NULL, NULL },
346  { { spoc_poc_erode, 6 }, { spoc_poc_unused, 0 } }, alu_unused, NO_MES
347  },
348  TRPX_NG(10, "ERODE_3_3?"), NO_OPCL,
349  SGC_WH(img_erode_6c_16, ero6c),
350  MPPA(MPPA_KERNEL_ERODE_6)
351  },
352  { AIPO "dilate_6c", "D6", NULL, 1, 1, 0, 1, NO_PARAM, { TY_CIP, NULL, NULL },
354  { { spoc_poc_dilate, 6 }, { spoc_poc_unused, 0 } }, alu_unused, NO_MES
355  },
356  TRPX_NG(10, "DILATE_3_3?"), NO_OPCL,
357  SGC_WH(img_dilate_6c_16, dil6c),
358  MPPA(MPPA_KERNEL_DILATE_6)
359  },
360  { AIPO "erode_8c", "E8", NULL, 1, 1, 0, 1, NO_PARAM, { TY_CIP, NULL, NULL },
362  { { spoc_poc_erode, 8 }, { spoc_poc_unused, 0 } }, alu_unused, NO_MES
363  },
364  TRPX_NG(15, "ERODE_3_3"), OPCLK("INF", "MAX"),
365  SGC_WH(img_erode_16, ero),
366  MPPA(MPPA_KERNEL_ERODE_8)
367  },
368  { AIPO "dilate_8c", "D8", NULL, 1, 1, 0, 1, NO_PARAM, { TY_CIP, NULL, NULL },
370  { { spoc_poc_dilate, 8 }, { spoc_poc_unused, 0 } }, alu_unused, NO_MES
371  },
372  TRPX_NG(15, "DILATE_3_3"), OPCLK("SUP", "MIN"),
373  SGC_WH(img_dilate_16, dil),
374  MPPA(MPPA_KERNEL_DILATE_8)
375  },
376  // MEASURES
377  { AIPO "global_min", "min", NULL, 0, 1, 1, 0,
378  { TY_PIN, NULL, NULL }, NO_PARAM,
381  },
382  TRPX_MS(1, 3, "GLOBAL_MIN"), OPCL("MINIMUM"),
383  SGC_WH(img_global_min, min),
384  MPPA(MPPA_KERNEL_MIN)
385  },
386  { AIPO "global_max", "max", NULL, 0, 1, 1, 0, { TY_PIN, NULL, NULL },
389  },
390  TRPX_MS(1, 3, "GLOBAL_MAX"), OPCL("MAXIMUM"),
391  SGC_WH(img_global_max, max),
392  MPPA(MPPA_KERNEL_MAX)
393  },
394  { AIPO "global_min_coord", "min!", NULL, 0, 1, 3, 0,
395  { TY_PIN, TY_PUI, TY_PUI }, NO_PARAM,
398  },
399  TRPX_MS(5, 3, "GLOBAL_MIN_COORD"), OPCL("MIN_COORD"),
400  SGC_WH(img_global_min_coord, minc),
401  MPPA(MPPA_KERNEL_MIN_COORDS)
402  },
403  { AIPO "global_max_coord", "max!", NULL, 0, 1, 3, 0,
404  { TY_PIN, TY_PUI, TY_PUI }, NO_PARAM,
407  },
408  TRPX_MS(5, 3, "GLOBAL_MAX_COORD"), OPCL("MAX_COORD"),
409  SGC_WH(img_global_max_coord, maxc),
410  MPPA(MPPA_KERNEL_MAX_COORDS)
411  },
412  { AIPO "global_vol", "vol", NULL, 0, 1, 1, 0,
413  { TY_PIN, NULL, NULL }, NO_PARAM,
416  },
417  TRPX_MS(2, 3, "GLOBAL_VOL"), OPCL("VOLUME"),
418  SGC_WH(img_global_vol, vol),
419  MPPA(MPPA_KERNEL_VOL)
420  },
421  // LINEAR
422  // cost rather approximated for Terapix
423  { AIPO "convolution", "conv", NULL, 1, 1, 0, 3,
424  NO_PARAM, { TY_PIN, TY_UIN, TY_UIN }, // kernel, width, height
425  // for spoc, only 3x3 convolutions
427  { { spoc_poc_conv, 8 }, { spoc_poc_unused, 0 } }, alu_unused, NO_MES
428  },
429  // for terapix, this is a special case
430  // I'm not sure about the cost model (h*35) for 3x3?
431  { -1, -1, -1, -1, 0, 3, false, false, "TERAPIX_UCODE_CONV" },
432  // missing at tail: / norm
433  OPCLK("ADD", "ZERO"),
434  SGC_WH(img_convole_16, conv),
435  MPPA(MPPA_KERNEL_CONVOLE_8)
436  },
437  // not implemented by SPOC! nor by TERAPIX!
438  { AIPO "fast_correlation", "corr", NULL, 1, 2, 0, 1,
439  NO_PARAM, { TY_UIN, NULL, NULL },
441  NO_SIGMAC, // for now
442  NO_MPPA
443  },
444  // last entry
445  { NULL, NULL, NULL, 0, 0, 0, 0, NO_PARAM, NO_PARAM,
447  }
448 };
449 
450 #define FREIA_AIPO_API_SIZE (sizeof(*FREIA_AIPO_API)/sizeof(freia_api_t))
451 
452 /* @returns the description of a FREIA AIPO API function.
453  * may be moved elswhere. raise an error if not found.
454  */
455 const freia_api_t * hwac_freia_api(const char* function)
456 {
457  static hash_table cache = NULL;
458  if (!cache)
459  {
460  const freia_api_t * api;
461  cache = hash_table_make(hash_string, 0);
462  for (api = FREIA_AIPO_API; api->function_name; api++)
463  hash_put(cache, api->function_name, api);
464  }
465  return (const freia_api_t *)
466  (hash_defined_p(cache, function)? hash_get(cache, function): NULL);
467 }
468 
469 /* returns the index of the description of an AIPO function
470  */
471 int hwac_freia_api_index(const string function)
472 {
473  const freia_api_t * api = hwac_freia_api(function);
474  return api? (api - FREIA_AIPO_API): -1;
475 }
476 
477 const freia_api_t * get_freia_api(int index)
478 {
479  // pips_assert("index exists", index>=0 && index<(int) FREIA_AIPO_API_SIZE);
480  return &FREIA_AIPO_API[index];
481 }
482 
484 {
486 }
487 
488 /* @return new allocated variable name using provided prefix.
489  * *params is incremented as a side effect.
490  */
491 static string get_var(string prefix, int * params)
492 {
493  return strdup(cat(prefix, i2a((*params)++)));
494 }
495 
496 /* @return a string which describes the type of operation
497  * (i.e. the hardware used by the function for spoc).
498  */
499 string what_operation(const _int type)
500 {
501  switch (type)
502  {
503  case spoc_type_sni: return "sni";
504  case spoc_type_oth: return "other";
505  case spoc_type_nop: return "none";
506  case spoc_type_inp: return "input";
507  case spoc_type_poc: return "poc";
508  case spoc_type_alu: return "alu";
509  case spoc_type_mes: return "measure";
510  case spoc_type_thr: return "threshold";
511  case spoc_type_out: return "output";
512  default: return "unexpected value...";
513  }
514 }
515 
516 /* SPoC: set shape depending on hardware component used by vertex
517  */
519 {
520  string shape;
521  switch (type)
522  {
523  case spoc_type_oth:
524  shape = "shape=none"; break;
525  case spoc_type_poc:
526  shape = "shape=box"; break;
527  case spoc_type_alu:
528  shape = "shape=trapezium,orientation=270"; break;
529  case spoc_type_thr:
530  shape = "shape=parallelogram"; break;
531  case spoc_type_mes:
532  shape = "shape=diamond"; break;
533  // these should not happen
534  case spoc_type_out:
535  case spoc_type_inp:
536  case spoc_type_nop:
537  default:
538  shape = "shape=circle";
539  }
540  return shape;
541 }
542 
543 /* ??? beurk: I keep the operation as two ints for code regeneration.
544  */
546 {
547  pips_assert("no type set", *type == spoc_type_nop);
548 
549  // set type which is enough for staging?
550  if (api->spoc.used==spoc_not_implemented)
551  *type = spoc_type_sni;
552  else if (api->spoc.used & spoc_alu)
553  *type = spoc_type_alu;
554  else if (api->spoc.used & (spoc_poc_0|spoc_poc_1))
555  *type = spoc_type_poc;
556  else if (api->spoc.used & (spoc_th_0|spoc_th_1))
557  *type = spoc_type_thr;
558  else if (api->spoc.used & (spoc_measure_0|spoc_measure_1))
559  *type = spoc_type_mes;
560  else
561  *type = spoc_type_nop; // e.g. for copy? (...)
562 
563  // set details
565 }
566 
567 /* @brief get freia further parameters, skipping image ones
568  */
570 {
571  int skip = api->arg_img_in + api->arg_img_out;
572  while (skip--) args = CDR(args);
573  pips_assert("number of scalar args is ok",
574  gen_length(args)==api->arg_misc_in+api->arg_misc_out);
575  return args;
576 }
577 
579 {
580  const vtxcontent vc = dagvtx_content(v);
581  pips_assert("there is a statement",
584  const call c = freia_statement_to_call(s);
585  const freia_api_t * api = dagvtx_freia_api(v);
586  return freia_get_params(api, call_arguments(c));
587 }
588 
590 {
592 }
593 
595 {
596  int bpp = FREIA_DEFAULT_BPP;
597  switch (bpp)
598  {
599  case 8: return 0xff;
600  case 16: return 0xffff;
601  default:
602  pips_user_error("expecting 8 or 16 for pixel size, got %d", bpp);
603  return 0;
604  }
605 }
606 
607 /* returns an allocated expression list of the parameters only
608  * (i.e. do not include the input & output images).
609  * params maps variables (if so) to already present parameters names.
610  * the extraction function allocs new parameter names if necessary.
611  */
612 list /* of expression */ freia_extract_params
613  (const int napi, // api function number
614  list args, // actual arguments to call
615  string_buffer head, // function headers
616  string_buffer head2, // function headers, the retour
617  hash_table params, // argument/variable to parameter mapping
618  int * nparams) // current number of parameters
619 {
620  const freia_api_t * api = get_freia_api(napi);
621  args = freia_get_params(api, args);
622  list res = NIL;
623  bool merge = get_bool_property("FREIA_MERGE_ARGUMENTS");
624 
625  // important shortcut, taken when ops are switched to "copy" for
626  // some reason, then the next assert would not be consistent.
627  if (api->arg_misc_in==0 && api->arg_misc_out==0)
628  return NIL;
629 
630  pips_assert("number of arguments is okay",
631  gen_length(args)==api->arg_misc_in+api->arg_misc_out);
632 
633  for (unsigned int i = 0; i<api->arg_misc_in; i++)
634  {
635  expression e = EXPRESSION(CAR(args));
636  args = CDR(args);
637 
638  if (params)
639  {
640  // ??? if the expression is a constant,
641  // the parameter could be skipped as well?
642  entity var = expression_to_entity(e);
643  if (merge && !entity_undefined_p(var) && entity_variable_p(var))
644  {
645  if (!hash_defined_p(params, var))
646  {
647  // choose new name
648  string name = get_var("pi", nparams);
649  if (head) sb_cat(head, ",\n ", api->arg_in_types[i], " ", name);
650  if (head2) sb_cat(head2, ", ", api->arg_in_types[i], " ", name);
651  hash_put(params, e, name);
652  res = CONS(expression, copy_expression(e), res);
653  // keep record for the *variable* as well...
654  hash_put(params, var, name);
655  }
656  else
657  {
658  // skip argument, just record its where it is found
659  hash_put(params, e, hash_get(params, var));
660  }
661  }
662  else
663  {
664  // append and record new parameter
665  string name = get_var("pi", nparams);
666  if (head) sb_cat(head, ",\n ", api->arg_in_types[i], " ", name);
667  if (head2) sb_cat(head2, ", ", api->arg_in_types[i], " ", name);
668  hash_put(params, e, name);
669  res = CONS(expression, copy_expression(e), res);
670  }
671  }
672  else
673  res = CONS(expression, copy_expression(e), res);
674  }
675 
676  for (unsigned int i = 0; i<api->arg_misc_out; i++)
677  {
678  expression e = EXPRESSION(CAR(args));
679  args = CDR(args);
680  string name = get_var("po", nparams);
681  if (head) sb_cat(head, ",\n ", api->arg_out_types[i], " ", name);
682  if (head2) sb_cat(head2, ", ", api->arg_out_types[i], " ", name);
683  if (params)
684  hash_put(params, e, name);
685  else
686  free(name);
687  res = CONS(expression, copy_expression(e), res);
688  }
689 
690  return gen_nreverse(res);
691 }
692 
693 /* @brief build all is well freia constant
694  */
696 {
697  // how to build the "FREIA_OK" enum value constant?
699 }
700 
701 /* @brief tell whether it is an assignment to ignore?
702  */
704 {
706 }
707 
708 /* @return "freia_aipo_copy(target, source);"
709  */
710 statement freia_copy_image(const entity source, const entity target)
711 {
712  return call_to_statement(
715  CONS(expression, entity_to_expression(source), NIL))));
716 }
717 
718 /* replace statement contents with call to c, or continue if kill
719  */
720 void hwac_replace_statement(statement s, call newc, bool kill)
721 {
723  pips_assert("must kill a call", instruction_call_p(old));
724  call c = instruction_call(old);
725  entity called = call_function(c);
726  if (ENTITY_C_RETURN_P(called))
727  {
728  // replace argument list
731  }
732  else if (freia_assignment_p(called))
733  {
734  // new second argument
735  list largs = call_arguments(c);
736  pips_assert("two arguments to assignment", gen_length(largs)==2);
737  expression first = EXPRESSION(CAR(largs));
738  free_expression(EXPRESSION(CAR(CDR(largs))));
739  gen_free_list(largs), largs = NIL;
740  call_arguments(c) =
742  }
743  else
744  {
745  free_instruction(old);
746  if (kill)
747  {
748  // ??? in C, it is not a do nothing instruction!
750  free_call(newc);
751  }
752  else
753  {
755  }
756  }
757 }
758 
759 /* remove contents of statement s.
760  */
762 {
763  hwac_replace_statement(s, freia_ok(), true);
764 }
765 
766 /* rather approximative?
767  */
769 {
770  bool is_image = false;
771  if (var && var!=entity_undefined &&
772  entity_variable_p(var) && entity_pointer_p(var))
773  {
774  type t = ultimate_type(entity_type(var));
776  if (basic_pointer_p(b))
777  {
778  t = basic_pointer(b);
780  is_image = basic_typedef_p(b) &&
782  "$" FREIA_IMAGE_TYPE);
783  }
784  }
785 
786  pips_debug(8, "%s is%s an image\n", entity_name(var), is_image? "": " not");
787  return is_image;
788 }
789 
790 /* for "ret = freia_aipo_*()": return the 'ret' variable...
791  * return NULL if not an assignment
792  */
794 {
795  entity assigned = NULL;
796  pips_assert("statement is a call", statement_call_p(s));
798  entity called = call_function(c);
799  if (freia_assignment_p(called))
801  return assigned;
802 }
803 
804 /* returns whether the entity is a freia API (AIPO) function.
805  */
807 {
808  // very partial...
809  return strncmp(entity_local_name(f), AIPO, strlen(AIPO))==0;
810 }
811 
812 /* returns whether the statement is a FREIA call.
813  */
815 {
816  // very partial as well
818  if (instruction_call_p(i)) {
819  call c = instruction_call(i);
820  entity called = call_function(c);
821  if (entity_freia_api_p(called))
822  return true;
823  else if (freia_assignment_p(called))
824  {
825  list la = call_arguments(c);
826  pips_assert("2 arguments to assign", gen_length(la));
828  if (syntax_call_p(op2))
830  }
831  else if (ENTITY_C_RETURN_P(called))
832  {
833  list la = call_arguments(c);
834  if (gen_length(la)==1) {
836  if (syntax_call_p(op))
838  }
839  }
840  }
841  return false;
842 }
843 
844 #include "effects-generic.h"
845 
846 /* append simple scalar entities with written/read effects to s
847  * scalars assigned to are ignored (return status).
848  * no attempt at managing aliasing or the like...
849  */
850 static void set_add_scalars(set s, const statement stat, const bool written)
851 {
853  entity skip = NULL;
854 
855  // skip assigned variable of AIPO calls
856  if (freia_statement_aipo_call_p(stat))
857  skip = get_assigned_variable(stat);
858 
859  FOREACH(effect, e, effects_effects(efs))
860  {
861  if (!malloc_effect_p(e) &&
862  ((written && effect_write_p(e)) || (!written && effect_read_p(e))))
863  {
865  if (entity_variable_p(var) && var!=skip &&
867  set_add_element(s, s, var);
868  }
869  }
870 }
871 
872 /************************************************ SCALAR DEPENDENCIES (HACK) */
873 
874 /* is there a simple scalar (no image) rw dependency from s to t?
875  * WW deps are ignored... should be okay of computed in order?
876  * @param s source statement
877  * @param t target statement
878  * @param vars if set, return list of scalars which hold the dependencies
879  */
880 static bool
882 {
883  // pips_assert("distinct statements", s!=t);
884  if (s==t || !s || !t) return false;
885  // I should really use entities_may_conflict_p...
886  set reads = set_make(set_pointer), writes = set_make(set_pointer);
887  set_add_scalars(writes, s, true);
888  set_add_scalars(reads, t, false);
889  set inter = set_make(set_pointer);
890  set_intersection(inter, reads, writes);
891  bool rw_dep = !set_empty_p(inter);
892  if (vars)
894  set_free(reads);
895  set_free(writes);
896  set_free(inter);
897  pips_debug(8, "%" _intFMT " %sdependent from %" _intFMT "\n",
898  statement_number(t), rw_dep? "": "in", statement_number(s));
899  return rw_dep;
900 }
901 
902 // Hmmm...
903 // this is called very often and the performance is abysmal
904 // even on not so big codes, so here is a cached version...
905 
906 // { s -> { t -> (vars) } }
907 static hash_table dep_cache = NULL;
908 
910 {
911  pips_assert("dep_cache is NULL", !dep_cache);
913 }
914 
916 {
917  pips_assert("dep_cache is not NULL", dep_cache);
918 
920  HASH_FOREACH(statement, s2, list, l, h)
921  if (l) gen_free_list(l);
922  hash_table_free(h);
923  }
924 
926 }
927 
928 // cached version
929 bool freia_scalar_rw_dep(const statement s, const statement t, list * vars)
930 {
931  pips_assert("dep_cache is not NULL", dep_cache);
932 
933  // short circuit
934  if (s==t || !s || !t) return false;
935 
936  // first level
937  if (!hash_defined_p(dep_cache, s))
940 
941  // second level
942  if (!hash_defined_p(h, t)) {
943  list l = NIL;
944  real_freia_scalar_rw_dep(s, t, &l);
945  hash_put(h, t, l);
946  }
947 
948  list l = (list) hash_get(h, t);
949  if (vars) *vars = gen_copy_seq(l);
950  return l!=NIL;
951 }
952 
953 static bool lexpression_equal_p(const list l1, const list l2)
954 {
955  bool equal = true;
956  int n1 = gen_length(l1), n2 = gen_length(l2);
957  if (n1==n2) {
958  list p1 = (list) l1, p2 = (list) l2;
959  while (equal && p1 && p2) {
961  equal = false;
962  p1 = CDR(p1), p2 = CDR(p2);
963  }
964  }
965  else
966  equal = false;
967  return equal;
968 }
969 
970 /* return the actual function call from a statement,
971  * dealing with assign and returns... return NULL if not a call.
972  */
974 {
975  // sanity check, somehow redundant
977  call c = instruction_call_p(i)? instruction_call(i): NULL;
978  if (c && freia_assignment_p(call_function(c)))
979  {
980  list args = call_arguments(c);
981  pips_assert("2 args", gen_length(args) == 2);
982  syntax sy = expression_syntax(EXPRESSION(CAR(CDR(args))));
983  c = syntax_call_p(sy)? syntax_call(sy): NULL;
984  }
985  else if (c && ENTITY_C_RETURN_P(call_function(c)))
986  {
987  list args = call_arguments(c);
988  pips_assert("one arg", gen_length(args)==1);
989  syntax sy = expression_syntax(EXPRESSION(CAR(args)));
990  c = syntax_call_p(sy)? syntax_call(sy): NULL;
991  }
992  return c;
993 }
994 
995 static bool is_freia_this_call(const statement s, const string fname)
996 {
998  const char* called = c? entity_user_name(call_function(c)): "";
999  return same_string_p(called, fname);
1000 }
1001 
1003 {
1004  return is_freia_this_call(s, FREIA_ALLOC);
1005 }
1006 
1008 {
1009  return is_freia_this_call(s, FREIA_FREE);
1010 }
1011 
1012 /* tell whether v1 and v2 point to statements with the same parameters.
1013  */
1014 bool same_constant_parameters(const dagvtx v1, const dagvtx v2)
1015 {
1016  call
1019  list
1020  lp1 = freia_extract_params
1021  (dagvtx_opid(v1), call_arguments(c1), NULL, NULL, NULL, NULL),
1022  lp2 = freia_extract_params
1023  (dagvtx_opid(v1), call_arguments(c2), NULL, NULL, NULL, NULL);
1024  bool same = lexpression_equal_p(lp1, lp2);
1025  gen_free_list(lp1), gen_free_list(lp2);
1026  // should also check that there is no w effects on parameters in between
1027  return same;
1028 }
1029 
1030 entity freia_create_helper_function(const string function_name, list lparams)
1031 {
1032  // build helper entity
1033  entity example = local_name_to_top_level_entity("freia_aipo_add");
1034  pips_assert("example is a function", entity_function_p(example));
1035  entity helper = make_empty_function(function_name,
1037  make_language_c());
1038 
1039  // update type of parameters
1040  list larg_params = NIL;
1042  {
1043  debug_on("RI_UTILS_DEBUG_LEVEL");
1045  debug_off();
1046  larg_params = CONS(parameter,
1047  make_parameter(t,
1048  make_mode_value(),
1049  make_dummy_unknown()),
1050  larg_params);
1051  }
1052  larg_params = gen_nreverse(larg_params);
1053  module_functional_parameters(helper) = larg_params;
1054 
1055  return helper;
1056 }
1057 
1058 /* substitute those statement in ls that are in dag d and accelerated
1059  * by a call to function_name(lparams)
1060  * also update sets of remainings and global_remainings
1061  *
1062  * the function must chose one of the statements?
1063  * the current implementation is a buggy mess.
1064  * it should be fully re-thought from scratch.
1065  *
1066  * what should be done, is to chose the FIRST statement after the LAST
1067  * dependency of the compiled statements? at least it must exist beacause
1068  * one of the dependent statement must appear after that, but is it enough
1069  * for all possible graph? so maybe we should do a topological sort of
1070  * all the statements and reshuffle everything instead of trying to preserver
1071  * the initial code as much as possible?
1072  */
1074  // dag reminder, may be null
1075  dag d,
1076  set global_remainings,
1077  set remainings,
1078  list /* of statement */ ls,
1079  const string function_name,
1080  list lparams,
1081  set helpers, // for signatures
1082  int preceeding) // statement which stored the previous insert, -1 for none
1083 {
1084  pips_debug(7, "%d statements, must come after statement %d\n",
1085  (int) gen_length(ls), preceeding);
1086 
1087  // buid the set of statements that are not yet computed
1088  set not_dones = set_make(set_pointer), dones = set_make(set_pointer);
1089  if (d)
1090  {
1091  FOREACH(dagvtx, vs, dag_vertices(d))
1092  {
1094  if (pstatement_statement_p(ps))
1095  set_add_element(not_dones, not_dones, pstatement_statement(ps));
1096  }
1097  }
1098  // dones: those statements which are handled by this helper
1099  set_difference(dones, remainings, not_dones);
1100  // now update remainings & global_remainings
1101  set_difference(remainings, remainings, dones);
1102  set_difference(global_remainings, global_remainings, dones);
1103 
1104  // replace first statement of dones in ls,
1105  // which comes after the preceeding ones.
1106  statement found = NULL, sos = NULL;
1107  FOREACH(statement, sc, ls)
1108  {
1109  pips_debug(5, "in statement %" _intFMT "\n", statement_number(sc));
1110  if (set_belong_p(dones, sc))
1111  {
1112  sos = sos? (statement_number(sc)<statement_number(sos)? sc: sos): sc;
1113  if (statement_number(sc)>preceeding)
1114  {
1115  pips_assert("statement is a call", statement_call_p(sc));
1116  found = found?
1117  (statement_number(sc)<statement_number(found)? sc: found): sc;
1118  }
1119  }
1120  }
1121 
1122  if (!found)
1123  {
1124  pips_user_warning("no statement found after preceeding insertion, "
1125  "using first statement as backup...\n");
1126  // use backup
1127  found = sos;
1128  }
1129 
1130  pips_assert("some statement found", found);
1131 
1132  // create and record helper function
1133  entity helper = freia_create_helper_function(function_name, lparams);
1134  set_add_element(helpers, helpers, helper);
1135 
1136  // substitute by call to helper
1137  call c = make_call(helper, lparams);
1138 
1139  hwac_replace_statement(found, c, false);
1140 
1141  set_free(not_dones);
1142  set_free(dones);
1143 
1144  return statement_number(found);
1145 }
1146 
1147 static statement find_aipo_statement(list ls, bool before)
1148 {
1149  pips_assert("some statements", ls);
1150  pips_debug(8, "choosing among %d statements\n", (int) gen_length(ls));
1151 
1152  statement found = NULL;
1153 
1154  FOREACH(statement, s, ls)
1155  {
1156  pips_debug(8, "stmt %" _intFMT "\n", statement_number(s));
1157  if (before)
1158  {
1159  if (!found || statement_number(found)>statement_number(s))
1160  found = s;
1161  }
1162  else // after
1163  {
1164  if (!found || statement_number(found)<statement_number(s))
1165  found = s;
1166  }
1167  }
1168 
1169  // ??? au pif
1170  if (!found && ls)
1171  {
1172  pips_debug(8, "no aipo call found... backup plan?\n");
1173  if (before)
1174  found = STATEMENT(CAR(gen_last(ls))); // list is reversed...
1175  else
1176  found = STATEMENT(CAR(ls));
1177  }
1178 
1179  return found;
1180 }
1181 
1182 /* insert statements to actual code sequence in "ls"
1183  * *BEWARE* that ls is assumed to be in reverse order...
1184  */
1185 void freia_insert_added_stats(list ls, list stats, bool before)
1186 {
1187  if (stats)
1188  {
1189  statement sref = find_aipo_statement(ls, before);
1190  pips_debug(8, "sref for %s is %" _intFMT "\n",
1191  before? "before": "after", statement_number(sref));
1192  instruction iref = statement_instruction(sref);
1193  statement newstat = instruction_to_statement(iref);
1194  // transfer comments and some cleanup...
1195  statement_comments(newstat) = statement_comments(sref);
1198  // pretty ugly because return must be handled especially...
1199  // ??? not sure that it is ok if !before?
1200  if (instruction_call_p(iref) &&
1202  {
1203  call c = instruction_call(iref);
1205  {
1206  // must split return...
1207  pips_internal_error("return splitting not implemented yet...");
1208  }
1209  else
1210  {
1211  if (before)
1212  stats = gen_nconc(stats, CONS(statement, newstat, NIL));
1213  else
1214  // ???
1215  stats = CONS(statement, newstat, stats);
1216  }
1217  }
1218  else
1219  {
1220  if (before)
1221  stats = CONS(statement, newstat, stats);
1222  else
1223  stats = gen_nconc(stats, CONS(statement, newstat, NIL));
1224  }
1225  statement_instruction(sref) =
1227  }
1228 }
1229 
1230 /* prepend limg images in front of the argument list
1231  * limg is consummed by the operation.
1232  */
1234  (list limg, // of entity
1235  list * lparams) // of expression
1236 {
1237  list largs = NIL;
1238  limg = gen_nreverse(limg);
1239  FOREACH(entity, e, limg)
1240  largs = CONS(expression, entity_to_expression(e), largs);
1241  gen_free_list(limg), limg = NIL;
1242  *lparams = gen_nconc(largs, *lparams);
1243 }
1244 
1245 /********************************************************* IMAGE OCCURRENCES */
1246 
1247 #define E_WRITE(v) (v)
1248 #define E_READ(v) ((void*)(((_int)v)+1))
1249 
1250 /* return the argument number, starting from 1, of this reference
1251  * or 0 if not found.
1252  */
1253 static int reference_argument_number(const reference r, const list le)
1254 {
1255  int n = 0, i=0;
1256  FOREACH(expression, e, le)
1257  {
1258  i++;
1260  n = i;
1261  }
1262  return n;
1263 }
1264 
1265 /* tell about the image effect. if in doubt, return true.
1266  */
1268  const reference r,
1269  const hash_table signatures)
1270 {
1271  const char* why = "default", *func = "?";
1272  bool written = false;
1274  if (c)
1275  {
1276  entity called = call_function(c);
1277  func = entity_local_name(called);
1279  if (n==0)
1280  written=true, why = "not found";
1281  else
1282  {
1283  const freia_api_t * api = hwac_freia_api(entity_local_name(called));
1284  if (api)
1285  written = n <= (int) api->arg_img_out, why = "api";
1286  else
1287  if (signatures && hash_defined_p(signatures, called))
1288  written = n <= (_int) hash_get(signatures, called), why = "sig";
1289  else
1290  written = true, why = "no sig";
1291  }
1292  }
1293  else
1294  // in doubt, assume a write effect?
1295  pips_internal_error("reference to %s outside of a call?\n",
1297 
1298  pips_debug(8, "reference to %s is %s (%s in %s)\n",
1300  written? "written": "read", why, func);
1301 
1302  return written;
1303 }
1304 
1305 typedef struct {
1306  // built image occurences:
1307  // image -> set of statements with written effects
1308  // image+1 -> set of statements with read effects
1310  // enclosing statement for inner recursion
1312  // set of statements with image operations
1314  // statement -> set of W images
1315  // statement+1 -> set of R images
1317  // helper entity -> number of written image args
1319 } occs_ctx;
1320 
1321 /* hack to help replace use-def chains which did not work initially with C.
1322  * occurrences is: <image entity> -> { set of statements }
1323  * this is really a ugly hack, sorry!
1324  * ??? I should also consider declarations, but as they should only
1325  * contain image allocations so there should be no problem.
1326  */
1327 
1328 static bool check_ref(reference r, occs_ctx * ctx)
1329 {
1330  entity v = reference_variable(r);
1331  if (freia_image_variable_p(v))
1332  {
1333  // ensure that target set exists
1334  if (!hash_defined_p(ctx->occs, v))
1335  {
1337  hash_put(ctx->occs, E_READ(v), set_make(set_pointer));
1338  }
1339  bool written = reference_written_p(r, ctx->signatures);
1340  set stats = (set) hash_get(ctx->occs, written? E_WRITE(v): E_READ(v));
1341  // get containing statement
1342  statement up = ctx->enclosing? ctx->enclosing:
1344  // which MUST exist?
1345  pips_assert("some containing statement", up);
1346  if (ctx->image_stats) {
1347  set sop = (set) hash_get(ctx->image_stats,
1348  written? E_WRITE(up): E_READ(up));
1349  set_add_element(sop, sop, (void*) v);
1350  }
1351  // store result
1352  set_add_element(stats, stats, (void*) up);
1353  if (ctx->image_occs_stats)
1355 
1356  pips_debug(9, "entity %s in statement %"_intFMT"\n",
1357  entity_name(v), statement_number(up));
1358  }
1359  return true;
1360 }
1361 
1362 static void check_ref2(reference r, occs_ctx * ctx)
1363 {
1364  (void) check_ref(r, ctx);
1365 }
1366 
1367 static bool check_stmt(statement s, occs_ctx * ctx)
1368 {
1369  // ensure existing set
1370  if (ctx->image_stats) {
1371  pips_debug(8, "creating for statement %"_intFMT"\n",
1372  statement_number(s));
1375  }
1376  ctx->enclosing = s;
1380  ctx->enclosing = NULL;
1381  return true;
1382 }
1383 
1384 /* @param image_occs_stats set of statements with image occurences (may be NULL)
1385  * @param signatures helper entity -> (_int) # out args
1386  * @return build occurrence hash table: { entity -> set of statements }
1387  */
1389  statement s,
1390  set image_occs_stats,
1391  hash_table image_stats,
1392  const hash_table signatures)
1393 {
1394  pips_debug(7, "entering\n");
1395  occs_ctx ctx = { hash_table_make(hash_pointer, 0), NULL,
1396  image_occs_stats, image_stats, signatures };
1397  gen_context_multi_recurse(s, &ctx,
1400  NULL);
1401  pips_debug(7, "done\n");
1402  return ctx.occs;
1403 }
1404 
1405 /* cleanup occurrence data structure
1406  */
1408 {
1409  HASH_FOREACH(entity, v, set, s, occs)
1410  set_free(s);
1411  hash_table_free(occs);
1412 }
1413 
1414 /************************************************************* VARIOUS TESTS */
1415 
1416 /* @brief whether api available with SPoC
1417  */
1419 {
1420  pips_assert("some api", api!=NULL);
1421  return api->spoc.used!=spoc_not_implemented;
1422 }
1423 
1424 /* @brief whether api available with Ter@pix
1425  */
1427 {
1428  pips_assert("some api", api!=NULL);
1429  // some special cases are handled manually
1430  if (same_string_p(api->function_name, "undefined") ||
1431  // this one is inserted to deal with replicated measures
1432  same_string_p(api->function_name, AIPO "scalar_copy"))
1433  return true;
1434  return api->terapix.cost!=-1;
1435 }
1436 
1437 /******************************************************* CONVOLUTION HELPERS */
1438 
1439 /* @brief is it the convolution special case?
1440  */
1442 {
1443  return same_string_p(dagvtx_operation(v), "convolution");
1444 }
1445 
1446 /* @brief get width & height of convolution
1447  * @return whether they could be extracted
1448  */
1449 bool freia_convolution_width_height(dagvtx v, _int * pw, _int * ph, bool check)
1450 {
1451  // pips_assert("vertex is convolution", ...)
1452  list largs = freia_get_vertex_params(v);
1453  if (check) pips_assert("3 args to convolution", gen_length(largs)==3);
1454  bool bw = expression_integer_value(EXPRESSION(CAR(CDR(largs))), pw);
1455  if (check) pips_assert("constant convolution width", bw);
1456  if (check) pips_assert("odd convolution width", ((*pw)%2)==1);
1457  bool bh = expression_integer_value(EXPRESSION(CAR(CDR(CDR(largs)))), ph);
1458  if (check) pips_assert("constant convolution height", bh);
1459  if (check) pips_assert("odd convolution height", ((*ph)%2)==1);
1460  return bw && bh;
1461 }
1462 
1464 {
1465  HASH_FOREACH(statement, st, set, imgs, s2i)
1466  set_free(imgs);
1467  hash_table_free(s2i);
1468 }
1469 
1470 /****************************************************** NEW IMAGE ALLOCATION */
1471 
1472 /*
1473 static statement image_alloc(entity v)
1474 {
1475  return make_assign_statement
1476  (entity_to_expression(v),
1477  call_to_expression(make_call(local_name_to_top_level_entity(FREIA_ALLOC),
1478  NIL)));
1479 }
1480 */
1481 
1482 /* generate statement: "freia_free(v);"
1483  */
1485 {
1486  return call_to_statement(
1489 }
1490 
1491 struct related_ctx {
1492  const entity img;
1497 };
1498 
1499 /* is there an effect to this image or related images in the statement?
1500  */
1501 
1502 /* are img1 and img2 related?
1503  */
1504 static bool related_images_p(const entity img1, const entity img2,
1505  const hash_table new_images)
1506 {
1507  entity oimg1 = NULL, oimg2 = NULL;
1508  if (img1==img2) return true;
1509  if (hash_defined_p(new_images, img1))
1510  oimg1 = (entity) hash_get(new_images, img1);
1511  if (hash_defined_p(new_images, img2))
1512  oimg2 = (entity) hash_get(new_images, img2);
1513 
1514  pips_debug(9, "images: %s -> %s / %s -> %s\n",
1515  entity_local_name(img1), oimg1? entity_local_name(oimg1): "NONE",
1516  entity_local_name(img2), oimg2? entity_local_name(oimg2): "NONE");
1517 
1518  if (oimg1 && oimg1==img2) return true;
1519  if (oimg2 && img1==oimg2) return true;
1520  // this is really the one which should be triggered?
1521  return oimg1 && oimg2 && oimg1==oimg2;
1522 }
1523 
1524 static bool related_effect(statement s, struct related_ctx * ctx)
1525 {
1526  pips_debug(8, "on statement %"_intFMT"\n", statement_number(s));
1527  entity written = NULL;
1529  {
1530  if (related_images_p(ctx->img, w, ctx->new_images))
1531  {
1532  pips_debug(8, "W relation for %s & %s\n",
1534  ctx->some_effect = true;
1535  gen_recurse_stop(NULL);
1536  return false;
1537  }
1538  written = w;
1539  }
1540  if (!ctx->write_only)
1541  {
1542  pips_assert("some written stuff", written);
1543  SET_FOREACH(entity, r, (set) hash_get(ctx->image_stats, E_READ(s)))
1544  {
1545  if (related_images_p(ctx->img, r, ctx->new_images))
1546  {
1547  pips_debug(8, "R relation for %s & %s\n",
1549  ctx->some_effect = true;
1550  gen_recurse_stop(NULL);
1551  return false;
1552  }
1553  }
1554  }
1555  return true;
1556 }
1557 
1559  statement s,
1560  entity img,
1561  hash_table new_images,
1562  hash_table image_stats,
1563  bool write_only)
1564 {
1565  struct related_ctx ctx = { img, new_images, image_stats, write_only, false };
1567  return ctx.some_effect;
1568 }
1569 
1570 /* tell whether there is no image processing statements between s1 and l2
1571  */
1573  // the new image we are interrested in
1574  entity image,
1575  // new to old image mapping
1577  // [RW](stats) -> sets
1579  // list of statements being considered (within a sequence)
1580  list ls,
1581  // image production statement
1582  statement s1,
1583  // list of "use" statements
1584  list l2,
1585  // set of statements with image occurences
1586  set image_occurences)
1587 {
1588  bool s1_seen = false, in_sequence = false;
1589  pips_assert("consistent statement & list", !gen_in_list_p(s1, l2));
1590  int n2 = gen_length(l2);
1591 
1592  ifdebug(8) {
1593  pips_debug(8, "img=%s s=%"_intFMT"\nls = (\n",
1595  FOREACH(statement, sls, ls)
1596  pips_debug(8, " - %"_intFMT" %s\n", statement_number(sls),
1597  sls==s1? "!": gen_in_list_p(sls, l2)? "*": "");
1598  pips_debug(8, ")\n");
1599  }
1600 
1601  // scan the sequence list, looking for s1 & l2 statements
1602  FOREACH(statement, s, ls)
1603  {
1604  if (!in_sequence && s==s1)
1605  in_sequence = true, s1_seen = true;
1606  else if (in_sequence && gen_in_list_p(s, l2))
1607  {
1608  n2--;
1609  if (n2) {
1610  // we are still going on, BUT we must check that this statement
1611  // does not rewrite the image we are interested in and may change back.
1613  return false;
1614  }
1615  // we stop when we have seen all intermediate statements
1616  else
1617  return true;
1618  }
1619  else if (in_sequence && set_belong_p(image_occurences, s))
1620  {
1621  // let us try to do something intelligent here...
1622  // if images are unrelated to "image", then there will be no interaction
1624  return false;
1625  }
1626  }
1627 
1628  // ??? should really be an error...
1629  pips_user_warning("should not get there: s1 seen=%s, seq=%s, n2=%d\n",
1630  bool_to_string(s1_seen), bool_to_string(in_sequence), n2);
1631 
1632  // let us be optimistic, this is a prototype
1633  return true;
1634 }
1635 
1636 /* insert image allocation if needed, for intermediate image inserted before
1637  * if an image is used only twice, then it is switched back to the initial one
1638  *
1639  * This could/should be improved:
1640  * - temporary images kept could be reused if possible, instead of new ones
1641  * - not sure about the condition to move back to the initial image
1642  *
1643  * @param ls list of statements to consider
1644  * @param images list of entities to check and maybe allocate
1645  * @param init new image -> initial image
1646  * @param signatures helper -> _int # written args ahead (may be NULL)
1647  *
1648  * @return list of actually allocated images
1649  */
1651  list ls, // statement
1652  list images, // entity
1653  // R(entity) and W(entity) -> set of statements
1654  const hash_table occs,
1655  // entity -> entity
1656  const hash_table init,
1657  // entity -> # out image
1658  const hash_table signatures)
1659 {
1660  // check for used images
1661  set img_stats = set_make(set_pointer);
1662  hash_table image_stats_detailed = hash_table_make(hash_pointer, 0);
1663  sequence sq = make_sequence(ls);
1664  hash_table newoccs =
1665  freia_build_image_occurrences((statement) sq, img_stats,
1666  image_stats_detailed, signatures);
1667  sequence_statements(sq) = NIL;
1668  free_sequence(sq);
1669 
1670  list allocated = NIL;
1671  FOREACH(entity, v, images)
1672  {
1673  if (!hash_defined_p(newoccs, v))
1674  // no written occurences, the image is not kept
1675  continue;
1676 
1677  if (get_bool_property("FREIA_REUSE_INITIAL_IMAGES"))
1678  {
1679  set where_write = (set) hash_get(newoccs, E_WRITE(v));
1680  set where_read = (set) hash_get(newoccs, E_READ(v));
1681  int nw = set_size(where_write), nr = set_size(where_read);
1682 
1683  pips_debug(6, "image %s used %d+%d statements\n", entity_name(v), nw, nr);
1684 
1685  // ??? should be used once only in the statement if written!
1686  // how to I know about W/R for helper functions?
1687  // its siblings should also be take into account
1688 
1689  // n>1 ??
1690  // if used only twice, substitude back to initial variable???
1691  // well, it may depends whether the the initial variable is used?
1692  // there is possibly something intelligent to do here, but it should
1693  // be checked carefully...
1694  if (nw==1 && nr>=1 && hash_defined_p(init, v))
1695  {
1696  entity old = (entity) hash_get(init, v);
1697 
1698  // get statements
1699  list l1 = set_to_list(where_write), l2 = set_to_list(where_read);
1700  statement s1 = STATEMENT(CAR(l1));
1701  gen_free_list(l1), l1 = NIL;
1702 
1703  // does not interact with possibly used old
1704  // if we could differentiate read & write, we could do better,
1705  // but the information is not currently available.
1706  bool skip = false;
1707  if (hash_defined_p(newoccs, old))
1708  {
1709  set old_write = (set) hash_get(newoccs, E_WRITE(old));
1710  set old_read = (set) hash_get(newoccs, E_READ(old));
1711  if (set_belong_p(old_write, s1))
1712  skip = true;
1713  else
1714  {
1715  FOREACH(statement, s2, l2)
1716  if (set_belong_p(old_read, s2))
1717  skip = true;
1718  }
1719  // note that we can handle a read in s1 and a write in s2
1720  }
1721 
1722  pips_debug(7, "testing for %s -> %s: %s\n",
1724  skip?"skip":"ok");
1725 
1726  // do we want to switch back?
1727  if (!skip &&
1728  only_minor_statements_in_between(v, init, image_stats_detailed,
1729  ls, s1, l2, img_stats))
1730  {
1731  // yes, they are successive, just remove?? Am I that sure???
1732  // ??? hmmm, maybe we could have :
1733  // X = stuff(...)
1734  // X_1 = stuff(...)
1735  // ... = stuff(X_1, ...)
1736  // ... = stuff(X...)
1737  // where X_1 -> X is just a bad idea because it overwrites X?
1738  // I'm not sure this can happen with AIPO, as X would be X_2
1739  // and will not be changed?
1740  pips_debug(7, "substituting back %s by %s\n",
1742 
1743  // we can perform any substitution here
1744  // note that it may be generated helper functions
1745  freia_switch_image_in_statement(s1, v, old, true);
1746  FOREACH(statement, s2, l2)
1747  freia_switch_image_in_statement(s2, v, old, false);
1748 
1749  // create/update uses of "old" to avoid interactions
1750  if (!hash_defined_p(newoccs, old))
1751  {
1752  hash_put(newoccs, E_WRITE(old), set_make(set_pointer));
1753  hash_put(newoccs, E_READ(old), set_make(set_pointer));
1754  }
1755  set old_write = (set) hash_get(newoccs, E_WRITE(old));
1756  set_add_element(old_write, old_write, s1);
1757  set old_read = (set) hash_get(newoccs, E_READ(old));
1758  FOREACH(statement, s2, l2)
1759  set_add_element(old_read, old_read, s2);
1760  }
1761  else
1762  allocated = CONS(entity, v, allocated);
1763  }
1764  else
1765  allocated = CONS(entity, v, allocated);
1766  }
1767  else
1768  allocated = CONS(entity, v, allocated);
1769  }
1770 
1771  clean_stats_to_image(image_stats_detailed);
1773  set_free(img_stats);
1774 
1775  // allocate those which are finally used
1776  if (allocated)
1777  {
1778  pips_assert("some statements", ls!=NIL);
1779  statement first = STATEMENT(CAR(ls));
1780  statement last = STATEMENT(CAR(gen_last(ls)));
1781  pips_assert("at least two statements", first!=last);
1782 
1783  // insert free_image(v)...
1784  // should insert image allocation statement as the same time
1785  // currently the allocation/deallocation may not be in the same scope!!!
1786  FOREACH(entity, v, images)
1787  {
1788  pips_debug(7, "allocating image %s\n", entity_name(v));
1789  // add_declaration_statement(first, v); // NO, returned
1790  // insert_statement(first, image_alloc(v), true); // NO, init
1791  // ??? deallocation should be at end of allocation block...
1792  entity model = (entity) hash_get(init, v);
1793  bool before = false;
1794  // find free_image(model) in the code
1795  statement fs = freia_memory_management_statement(model, occs, false);
1796  if (!fs)
1797  {
1798  pips_user_warning("not quite sure where to put %s deallocation\n",
1799  entity_name(v));
1800  // hmmm... try at the program level
1802  if (statement_sequence_p(ms))
1803  {
1804  fs = STATEMENT(
1806  // hmmm... does not seem to work properly
1807  //if (statement_call_p(s) &&
1808  // ENTITY_C_RETURN_P(call_function(statement_call(s))))
1809  before = true;
1810  }
1811  }
1812  insert_statement(fs? fs: last, image_free(v), before);
1813  }
1814  }
1815 
1816  return allocated;
1817 }
1818 
1819 /************************************************************* AIPO COUNTERS */
1820 
1821 /* @return the number for FREIA AIPO ops in dag
1822  */
1823 int freia_aipo_count(dag d, int * pa, int * pc)
1824 {
1825  int aipos = 0, copies = 0;
1826  FOREACH(dagvtx, v, dag_vertices(d))
1827  {
1828  string op = dagvtx_function_name(v);
1829  if (strncmp(op, AIPO, strlen(AIPO))==0) aipos++;
1830  // handle exceptions afterwards
1831  if (same_string_p(op, AIPO "copy")) copies++, aipos--;
1832  else if (same_string_p(op, AIPO "cast")) copies++, aipos--;
1833  else if (same_string_p(op, AIPO "scalar_copy")) aipos--;
1834  }
1835  *pa = aipos, *pc = copies;
1836  return aipos+copies;
1837 }
1838 
1839 /******************************************************* BUILD OUTPUT IMAGES */
1840 
1841 static void oi_call_rwt(call c, set images)
1842 {
1843  entity called = call_function(c);
1844  list args = call_arguments(c);
1845  if (!args) return;
1846  if (ENTITY_RETURN_P(called) ||
1848  {
1849  entity var = expression_to_entity(EXPRESSION(CAR(args)));
1850  if (freia_image_variable_p(var))
1851  set_add_element(images, images, var);
1852  }
1853 }
1854 
1855 static void oi_stmt_rwt(statement s, set images)
1856 {
1858  gen_context_recurse(entity_initial(var), images,
1860 }
1861 
1862 /* @return the set of images which are output somehow
1863  * this is a little bit simplistic...
1864  * read output effects of statement?
1865  */
1867 {
1868  set images = set_make(set_pointer);
1869 
1870  // image formal parameters
1872  {
1873  if (freia_image_variable_p(var))
1874  set_add_element(images, images, var);
1875  }
1876 
1877  // some image uses in the code
1878  gen_context_multi_recurse(s, images,
1881  NULL);
1882  return images;
1883 }
1884 
1886 {
1889 }
1890 
1891 /******************************************************** MIGRATE STATEMENTS */
1892 
1893 static string stat_nb(statement s)
1894 {
1895  return i2a((int) statement_number(s));
1896 }
1897 
1898 /*
1899  migrate a subset of statements in a sequence so that they are close together.
1900  the relative order of statements is kept. the sequence is updated.
1901  @param sq sequence to update, may be NULL
1902  @param stats statements to move together
1903  @param before statements that must appear before, may be NULL
1904 */
1905 void freia_migrate_statements(sequence sq, const set stats, const set before)
1906 {
1907  ifdebug(4) {
1908  pips_debug(4, "migrating %d statements in %p\n", set_size(stats), sq);
1909  set_fprint(stderr, "stats", stats, (gen_string_func_t) stat_nb);
1910  set_fprint(stderr, "before", before, (gen_string_func_t) stat_nb);
1911  }
1912 
1913  // nothing to do
1914  if (sq==NULL)
1915  {
1916  pips_assert("nothing to migrate", set_size(stats)<=1);
1917  return;
1918  }
1919 
1920  // nothing to do either
1921  if (set_size(stats)==0)
1922  return;
1923 
1924  // build before/in/end statement lists in reverse order
1925  list lbefore = NIL, lin = NIL, lend = NIL;
1927  {
1928  if (set_belong_p(stats, s))
1929  lin = CONS(statement, s, lin);
1930  else
1931  {
1932  if (before && set_belong_p(before, s))
1933  lbefore = CONS(statement, s, lbefore);
1934  else
1935  {
1936  if (lin)
1937  lend = CONS(statement, s, lend);
1938  else
1939  lbefore = CONS(statement, s, lbefore);
1940  }
1941  }
1942  }
1943 
1944  // check consistency
1945  pips_assert("all statements seen", set_size(stats)==(int) gen_length(lin));
1946 
1947  // update sequence
1949  lin = gen_nconc(gen_nreverse(lin), gen_nreverse(lend));
1950  sequence_statements(sq) = gen_nconc(gen_nreverse(lbefore), lin);
1951 }
1952 
1953 /* extract values from a kernel definition
1954  * return 9 values, expected to be 0/1 elsewhere...
1955  * @return whether it succeeded
1956  */
1958  expression e,
1959  bool strict, // whether all values must be known, if not 1 is assumed
1960  intptr_t * k00, intptr_t * k10, intptr_t * k20,
1961  intptr_t * k01, intptr_t * k11, intptr_t * k21,
1962  intptr_t * k02, intptr_t * k12, intptr_t * k22)
1963 {
1964  // set default value anyway
1965  *k00 = 1, *k10 = 1, *k20 = 1,
1966  *k01 = 1, *k11 = 1, *k21 = 1,
1967  *k02 = 1, *k12 = 1, *k22 = 1;
1968 
1969  // analyse kernel
1970  if (!expression_reference_p(e)) return !strict;
1971  entity var = expression_variable(e);
1972  // ??? should check const...
1973  value val = entity_initial(var);
1974  if (!value_expression_p(val)) return !strict;
1975  expression ival = value_expression(val);
1976  if (!brace_expression_p(ival)) return !strict;
1978  pips_assert("must be a 3x3 kernel...", gen_length(iargs)==9);
1979  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k00) && strict)
1980  return false;
1981  iargs = CDR(iargs);
1982  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k10) && strict)
1983  return false;
1984  iargs = CDR(iargs);
1985  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k20) && strict)
1986  return false;
1987  iargs = CDR(iargs);
1988  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k01) && strict)
1989  return false;
1990  iargs = CDR(iargs);
1991  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k11) && strict)
1992  return false;
1993  iargs = CDR(iargs);
1994  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k21) && strict)
1995  return false;
1996  iargs = CDR(iargs);
1997  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k02) && strict)
1998  return false;
1999  iargs = CDR(iargs);
2000  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k12) && strict)
2001  return false;
2002  iargs = CDR(iargs);
2003  if (!expression_integer_value(EXPRESSION(CAR(iargs)), k22) && strict)
2004  return false;
2005  iargs = CDR(iargs);
2006  pips_assert("end of list reached", iargs==NIL);
2007  return true;
2008 }
2009 
2010 /* vertex-based version
2011  */
2013  dagvtx v, bool strict,
2014  intptr_t * k00, intptr_t * k10, intptr_t *k20,
2015  intptr_t * k01, intptr_t * k11, intptr_t *k21,
2016  intptr_t * k02, intptr_t * k12, intptr_t *k22)
2017 {
2018  list largs = freia_get_vertex_params(v);
2019  // for convolution there is one kernel & two args
2020  // pips_assert("one kernel", gen_length(largs)==1);
2021  expression e = EXPRESSION(CAR(largs));
2022  return freia_extract_kernel(e, strict, k00, k10, k20,
2023  k01, k11, k21, k02, k12, k22);
2024 }
2025 
2026 /* return malloc'ed "foo.database/Src/%{module}_helper_functions.c"
2027  * should it depend on the target? no, because we could mix targets?
2028  */
2029 string helper_file_name(string func_name, string suffix)
2030 {
2031  string src_dir = db_get_directory_name_for_module(func_name);
2032  string fn = strdup(cat(src_dir, "/", func_name, HELPER "functions.", suffix));
2033  free(src_dir);
2034  return fn;
2035 }
call make_call(entity a1, list a2)
Definition: ri.c:269
parameter make_parameter(type a1, mode a2, dummy a3)
Definition: ri.c:1495
type copy_type(type p)
TYPE.
Definition: ri.c:2655
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
instruction make_instruction_call(call _field_)
Definition: ri.c:1184
void free_expression(expression p)
Definition: ri.c:853
void free_instruction(instruction p)
Definition: ri.c:1118
language make_language_c(void)
Definition: ri.c:1253
dummy make_dummy_unknown(void)
Definition: ri.c:617
void free_call(call p)
Definition: ri.c:236
mode make_mode_value(void)
Definition: ri.c:1353
sequence make_sequence(list a)
Definition: ri.c:2125
void free_sequence(sequence p)
Definition: ri.c:2092
struct paramStruct params
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static bool written
Definition: alias_check.c:512
void const char const char const int
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
statement freia_memory_management_statement(entity image, const hash_table occs, bool alloc)
Definition: dag-utils.c:2587
void freia_switch_image_in_statement(statement s, entity old, entity img, bool write)
switch read or written image in statement if this is an AIPO call, only substitute output or input de...
Definition: dag-utils.c:2746
string dagvtx_function_name(const dagvtx v)
Definition: dag-utils.c:126
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
#define min(a, b)
#define max(a, b)
effects load_cumulated_rw_effects(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_write_p(eff)
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
bool malloc_effect_p(effect)
Definition: effects.c:478
#define effects_effects(x)
Definition: effects.h:710
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static void clean_stats_to_image(hash_table s2i)
Definition: freia-utils.c:1463
bool entity_freia_api_p(const entity f)
returns whether the entity is a freia API (AIPO) function.
Definition: freia-utils.c:806
const freia_api_t * hwac_freia_api(const char *function)
freia-utils.c
Definition: freia-utils.c:455
bool is_freia_dealloc(const statement s)
Definition: freia-utils.c:1007
static string stat_nb(statement s)
Definition: freia-utils.c:1893
bool is_freia_alloc(const statement s)
Definition: freia-utils.c:1002
void freia_spoc_set_operation(const freia_api_t *api, _int *type, _int *id)
??? beurk: I keep the operation as two ints for code regeneration.
Definition: freia-utils.c:545
statement freia_copy_image(const entity source, const entity target)
Definition: freia-utils.c:710
#define SGC_W(ag, pref)
Definition: freia-utils.c:80
static bool related_effect(statement s, struct related_ctx *ctx)
Definition: freia-utils.c:1524
entity freia_create_helper_function(const string function_name, list lparams)
Definition: freia-utils.c:1030
set freia_compute_output_images(entity module, statement s)
Definition: freia-utils.c:1866
#define NO_TRPX
Definition: freia-utils.c:65
void freia_add_image_arguments(list limg, list *lparams)
prepend limg images in front of the argument list limg is consummed by the operation.
Definition: freia-utils.c:1234
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
static bool some_related_image_effect(statement s, entity img, hash_table new_images, hash_table image_stats, bool write_only)
Definition: freia-utils.c:1558
static void check_ref2(reference r, occs_ctx *ctx)
Definition: freia-utils.c:1362
list freia_get_vertex_params(const dagvtx v)
Definition: freia-utils.c:578
static entity get_assigned_variable(const statement s)
for "ret = freia_aipo_*()": return the 'ret' variable...
Definition: freia-utils.c:793
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
#define NOPE_SIGMAC
Definition: freia-utils.c:60
static string get_var(string prefix, int *params)
Definition: freia-utils.c:491
list freia_get_params(const freia_api_t *api, list args)
get freia further parameters, skipping image ones
Definition: freia-utils.c:569
void hwac_kill_statement(statement s)
remove contents of statement s.
Definition: freia-utils.c:761
static bool check_stmt(statement s, occs_ctx *ctx)
Definition: freia-utils.c:1367
#define E_WRITE(v)
Definition: freia-utils.c:1247
static bool related_images_p(const entity img1, const entity img2, const hash_table new_images)
is there an effect to this image or related images in the statement?
Definition: freia-utils.c:1504
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
#define TY_PUI
Definition: freia-utils.c:90
static bool lexpression_equal_p(const list l1, const list l2)
Definition: freia-utils.c:953
bool freia_image_variable_p(const entity var)
rather approximative?
Definition: freia-utils.c:768
static bool freia_extract_kernel(expression e, 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)
extract values from a kernel definition return 9 values, expected to be 0/1 elsewhere....
Definition: freia-utils.c:1957
hash_table freia_build_image_occurrences(statement s, set image_occs_stats, hash_table image_stats, const hash_table signatures)
Definition: freia-utils.c:1388
int freia_max_pixel_value(void)
Definition: freia-utils.c:594
#define NOPE_SPOC
Definition: freia-utils.c:57
#define TY_PIN
Definition: freia-utils.c:87
static bool is_freia_this_call(const statement s, const string fname)
Definition: freia-utils.c:995
void freia_close_dep_cache(void)
Definition: freia-utils.c:915
static bool reference_written_p(const reference r, const hash_table signatures)
tell about the image effect.
Definition: freia-utils.c:1267
static void set_add_scalars(set s, const statement stat, const bool written)
append simple scalar entities with written/read effects to s scalars assigned to are ignored (return ...
Definition: freia-utils.c:850
#define OPCL(op)
Definition: freia-utils.c:77
static void oi_call_rwt(call c, set images)
Definition: freia-utils.c:1841
#define TY_UIN
Definition: freia-utils.c:89
void freia_migrate_statements(sequence sq, const set stats, const set before)
Definition: freia-utils.c:1905
#define TRPX_IO(c, op)
Definition: freia-utils.c:71
#define NO_SIGMAC
Definition: freia-utils.c:67
int freia_substitute_by_helper_call(dag d, set global_remainings, set remainings, list ls, const string function_name, list lparams, set helpers, int preceeding)
substitute those statement in ls that are in dag d and accelerated by a call to function_name(lparams...
Definition: freia-utils.c:1073
#define NOPE_MPPA
Definition: freia-utils.c:61
static void oi_stmt_rwt(statement s, set images)
Definition: freia-utils.c:1855
static bool real_freia_scalar_rw_dep(const statement s, const statement t, list *vars)
is there a simple scalar (no image) rw dependency from s to t? WW deps are ignored....
Definition: freia-utils.c:881
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
#define TY_CIP
Definition: freia-utils.c:88
const freia_api_t * get_freia_api(int index)
Definition: freia-utils.c:477
#define NOPE_TRPX
Definition: freia-utils.c:58
bool same_constant_parameters(const dagvtx v1, const dagvtx v2)
tell whether v1 and v2 point to statements with the same parameters.
Definition: freia-utils.c:1014
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
#define TRPX_NG(c, op)
Definition: freia-utils.c:72
static int reference_argument_number(const reference r, const list le)
return the argument number, starting from 1, of this reference or 0 if not found.
Definition: freia-utils.c:1253
call freia_ok(void)
build all is well freia constant
Definition: freia-utils.c:695
static bool check_ref(reference r, occs_ctx *ctx)
hack to help replace use-def chains which did not work initially with C.
Definition: freia-utils.c:1328
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
#define NOPE_OPCL
Definition: freia-utils.c:59
string what_operation(const _int type)
Definition: freia-utils.c:499
bool freia_convolution_width_height(dagvtx v, _int *pw, _int *ph, bool check)
get width & height of convolution
Definition: freia-utils.c:1449
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
void freia_init_dep_cache(void)
Definition: freia-utils.c:909
static statement image_free(entity v)
generate statement: "freia_free(v);"
Definition: freia-utils.c:1484
#define NO_OPCL
Definition: freia-utils.c:66
#define TRPX_OP(c, op)
Definition: freia-utils.c:70
bool freia_aipo_spoc_implemented(const freia_api_t *api)
whether api available with SPoC
Definition: freia-utils.c:1418
#define SGC_WH(ag, pref)
Definition: freia-utils.c:81
#define TRPX_MS(m, c, op)
Definition: freia-utils.c:75
static bool only_minor_statements_in_between(entity image, hash_table new_images, hash_table image_stats, list ls, statement s1, list l2, set image_occurences)
tell whether there is no image processing statements between s1 and l2
Definition: freia-utils.c:1572
#define NO_PARAM
Definition: freia-utils.c:92
static hash_table dep_cache
Definition: freia-utils.c:907
#define TY_INT
Definition: freia-utils.c:86
set freia_compute_current_output_images(void)
Definition: freia-utils.c:1885
string what_operation_shape(const _int type)
SPoC: set shape depending on hardware component used by vertex.
Definition: freia-utils.c:518
static const freia_api_t FREIA_AIPO_API[]
!!! there are some underlying assumptions when using this structure: only one of ALU/POC/MES is used ...
Definition: freia-utils.c:99
bool freia_scalar_rw_dep(const statement s, const statement t, list *vars)
Definition: freia-utils.c:929
bool freia_assignment_p(const entity e)
tell whether it is an assignment to ignore?
Definition: freia-utils.c:703
int freia_aipo_count(dag d, int *pa, int *pc)
Definition: freia-utils.c:1823
int hwac_freia_api_index(const string function)
returns the index of the description of an AIPO function
Definition: freia-utils.c:471
expression freia_get_nth_scalar_param(const dagvtx v, int n)
Definition: freia-utils.c:589
#define NO_POC
Definition: freia-utils.c:53
bool freia_aipo_terapix_implemented(const freia_api_t *api)
whether api available with Ter@pix
Definition: freia-utils.c:1426
#define MPPA(kernel)
Definition: freia-utils.c:83
#define NO_MPPA
Definition: freia-utils.c:68
bool freia_statement_aipo_call_p(const statement s)
returns whether the statement is a FREIA call.
Definition: freia-utils.c:814
#define OPCLK(op, init)
Definition: freia-utils.c:78
#define E_READ(v)
Definition: freia-utils.c:1248
#define NO_SPOC
Definition: freia-utils.c:64
void freia_clean_image_occurrences(hash_table occs)
cleanup occurrence data structure
Definition: freia-utils.c:1407
const freia_api_t * get_freia_api_vtx(dagvtx v)
Definition: freia-utils.c:483
#define NO_MES
Definition: freia-utils.c:54
static statement find_aipo_statement(list ls, bool before)
Definition: freia-utils.c:1147
#define FREIA_IMAGE_TYPE
Definition: freia.h:46
#define cat(args...)
Definition: freia.h:41
#define AIPO
Definition: freia.h:51
#define HELPER
Definition: freia.h:38
#define FREIA_DEFAULT_BPP
Definition: freia.h:53
#define sb_cat(args...)
Definition: freia.h:42
#define FREIA_FREE
Definition: freia.h:49
#define FREIA_ALLOC
Definition: freia.h:48
#define FREIA_OUTPUT
Definition: freia.h:47
#define dagvtx_freia_api(v)
Definition: freia.h:97
@ spoc_not_implemented
Definition: freia_spoc.h:58
@ spoc_measure_0
Definition: freia_spoc.h:50
@ spoc_th_0
Definition: freia_spoc.h:47
@ spoc_output_0
Definition: freia_spoc.h:39
@ spoc_input_0
Definition: freia_spoc.h:36
@ spoc_measure_1
Definition: freia_spoc.h:51
@ spoc_alu
Definition: freia_spoc.h:45
@ spoc_input_1
Definition: freia_spoc.h:37
@ spoc_poc_1
Definition: freia_spoc.h:43
@ spoc_poc_0
Definition: freia_spoc.h:42
@ spoc_th_1
Definition: freia_spoc.h:48
@ spoc_poc_erode
Definition: freia_spoc.h:147
@ spoc_poc_conv
Definition: freia_spoc.h:149
@ spoc_poc_unused
Definition: freia_spoc.h:146
@ spoc_poc_dilate
Definition: freia_spoc.h:148
@ alu_sup_0cst
Definition: freia_spoc.h:111
@ alu_or
Definition: freia_spoc.h:117
@ alu_mul_0cst
Definition: freia_spoc.h:96
@ alu_div_01
Definition: freia_spoc.h:98
@ alu_subsat_0cst
Definition: freia_spoc.h:88
@ alu_sub_0cst
Definition: freia_spoc.h:82
@ alu_inf_01
Definition: freia_spoc.h:107
@ alu_sup_01
Definition: freia_spoc.h:110
@ alu_copy_cst
Definition: freia_spoc.h:126
@ alu_subsat_01
Definition: freia_spoc.h:86
@ alu_add
Definition: freia_spoc.h:74
@ alu_repcst_0
Definition: freia_spoc.h:130
@ alu_abssub
Definition: freia_spoc.h:92
@ alu_addsat
Definition: freia_spoc.h:77
@ alu_sub_cst0
Definition: freia_spoc.h:84
@ alu_and
Definition: freia_spoc.h:114
@ alu_log2_0
Definition: freia_spoc.h:104
@ alu_div_0cst
Definition: freia_spoc.h:100
@ alu_xor_0cst
Definition: freia_spoc.h:121
@ alu_unused
Definition: freia_spoc.h:72
@ alu_div_cst0
Definition: freia_spoc.h:102
@ alu_abssub_0cst
Definition: freia_spoc.h:93
@ alu_addsat_0cst
Definition: freia_spoc.h:78
@ alu_xor
Definition: freia_spoc.h:120
@ alu_or_0cst
Definition: freia_spoc.h:118
@ alu_add_0cst
Definition: freia_spoc.h:75
@ alu_not_0
Definition: freia_spoc.h:123
@ alu_sub_01
Definition: freia_spoc.h:80
@ alu_mul
Definition: freia_spoc.h:95
@ alu_mask_0
Definition: freia_spoc.h:128
@ alu_and_0cst
Definition: freia_spoc.h:115
@ alu_subsat_cst0
Definition: freia_spoc.h:90
@ alu_inf_0cst
Definition: freia_spoc.h:108
@ measure_min
Definition: freia_spoc.h:65
@ measure_vol
Definition: freia_spoc.h:67
@ measure_none
Definition: freia_spoc.h:62
@ measure_max_coord
Definition: freia_spoc.h:64
@ measure_min_coord
Definition: freia_spoc.h:66
@ measure_max
Definition: freia_spoc.h:63
@ spoc_type_sni
Definition: freia_spoc.h:172
@ spoc_type_out
Definition: freia_spoc.h:180
@ spoc_type_mes
Definition: freia_spoc.h:179
@ spoc_type_nop
Definition: freia_spoc.h:174
@ spoc_type_oth
Definition: freia_spoc.h:173
@ spoc_type_inp
Definition: freia_spoc.h:175
@ spoc_type_thr
Definition: freia_spoc.h:178
@ spoc_type_alu
Definition: freia_spoc.h:177
@ spoc_type_poc
Definition: freia_spoc.h:176
#define pstatement_statement_p(x)
#define dagvtx_content(x)
#define vtxcontent_opid(x)
#define pstatement_statement(x)
#define dag_vertices(x)
#define vtxcontent_source(x)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void gen_full_free_list(list l)
Definition: genClib.c:1023
if(!(yy_init))
Definition: genread_lex.c:1029
void free(void *)
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_nthcdr(int n, const list lx)
caution: the first item is 0! was: return( (n<=0) ? l : gen_nthcdr( n-1, CDR( l ))) ; if n>gen_length...
Definition: list.c:700
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
bool statement_call_p(statement)
Definition: statement.c:364
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
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_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
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
#define debug_on(env)
Definition: misc-local.h:157
#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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
string bool_to_string(bool)
Definition: string.c:243
@ hash_string
Definition: newgen_hash.h:32
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
struct __hash_table * hash_table
Define hash_table structure which is hidden.
Definition: newgen_hash.h:43
#define same_string_p(s1, s2)
bool set_empty_p(const set)
tell whether set s is empty.
Definition: set.c:367
set set_intersection(set, const set, const set)
Definition: set.c:229
struct _set_chunk * set
Definition: newgen_set.h:38
list set_to_list(const set)
create a list from a set the set is not freed
Definition: set.c:436
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
int set_size(const set)
returns the number of items in s.
Definition: set.c:359
set set_difference(set, const set, const set)
Definition: set.c:256
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
void set_fprint(FILE *, string, const set, gen_string_func_t)
print set s to file stream out.
Definition: set.c:524
@ 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(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
#define string_undefined
Definition: newgen_types.h:40
#define _intFMT
Definition: newgen_types.h:57
intptr_t _int
_INT
Definition: newgen_types.h:53
struct cons * list
Definition: newgen_types.h:106
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
list lparams
Array bounds.
Definition: reindexing.c:111
static const char * prefix
#define ENTITY_ASSIGN_P(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#define call_to_statement(c)
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define ENTITY_C_RETURN_P(e)
#define module_functional_parameters(func)
#define ENTITY_RETURN_P(e)
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328
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
bool entity_function_p(entity e)
Definition: entity.c:724
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
bool entity_pointer_p(entity e)
Definition: entity.c:745
entity make_empty_function(const char *name, type r, language l)
Definition: entity.c:283
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
bool brace_expression_p(expression e)
Return bool indicating if expression e is a brace expression.
Definition: expression.c:3384
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
entity expression_variable(expression e)
Definition: expression.c:532
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
type ultimate_type(type)
Definition: type.c:3466
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
type expression_to_user_type(expression)
Preserve typedef'ed types when possible.
Definition: type.c:2645
#define basic_pointer(x)
Definition: ri.h:637
#define functional_result(x)
Definition: ri.h:1444
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define basic_typedef_p(x)
Definition: ri.h:641
#define syntax_call_p(x)
Definition: ri.h:2734
#define type_functional(x)
Definition: ri.h:2952
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define basic_typedef(x)
Definition: ri.h:643
#define entity_undefined_p(x)
Definition: ri.h:2762
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
struct _newgen_struct_call_ * call
Definition: ri.h:63
#define sequence_statements(x)
Definition: ri.h:2360
#define syntax_call(x)
Definition: ri.h:2736
#define instruction_call_p(x)
Definition: ri.h:1527
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define value_expression_p(x)
Definition: ri.h:3080
#define expression_syntax(x)
Definition: ri.h:1247
#define value_expression(x)
Definition: ri.h:3082
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
char * strdup()
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
static int lend()
return 1 for 'end' alone on card (up to col.
Definition: split_file.c:242
#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
string function_name
Definition: freia.h:73
spoc_hw_t spoc
Definition: freia.h:89
unsigned int arg_misc_in
Definition: freia.h:83
terapix_hw_t terapix
Definition: freia.h:90
string arg_out_types[3]
Definition: freia.h:85
unsigned int arg_img_out
Definition: freia.h:79
string arg_in_types[3]
Definition: freia.h:86
unsigned int arg_misc_out
Definition: freia.h:82
unsigned int arg_img_in
Definition: freia.h:80
code taken from http://fast-edge.googlecode.com and adapted to c99
Definition: erode_dilate.c:33
hash_table image_stats
Definition: freia-utils.c:1316
statement enclosing
Definition: freia-utils.c:1311
const hash_table signatures
Definition: freia-utils.c:1318
set image_occs_stats
Definition: freia-utils.c:1313
hash_table occs
Definition: freia-utils.c:1309
const hash_table new_images
Definition: freia-utils.c:1493
const hash_table image_stats
Definition: freia-utils.c:1494
const entity img
Definition: freia-utils.c:1492
bool some_effect
Definition: freia-utils.c:1496
uint32_t used
Definition: freia_spoc.h:162