2 * Copyright 2012 INRIA Paris-Rocquencourt
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Tobias Grosser, INRIA Paris-Rocquencourt,
7 * Domaine de Voluceau, Rocquenqourt, B.P. 105,
8 * 78153 Le Chesnay Cedex France
14 #include <cloog/cloog.h>
15 #include <cloog/isl/cloog.h>
21 #include "clast_printer.h"
23 #include "pet_printer.h"
26 /* Derive the output file name from the input file name.
27 * 'input' is the entire path of the input file. The output
28 * is the file name plus the additional extension.
30 * We will basically replace everything after the last point
31 * with '.ppcg.c'. This means file.c becomes file.ppcg.c
33 FILE *get_output_file(const char *input
)
38 const char ppcg_marker
[] = ".ppcg";
41 base
= strrchr(input
, '/');
46 ext
= strrchr(base
, '.');
47 len
= ext
? ext
- base
: strlen(base
);
49 memcpy(name
, base
, len
);
50 strcpy(name
+ len
, ppcg_marker
);
51 strcpy(name
+ len
+ sizeof(ppcg_marker
) - 1, ext
);
53 return fopen(name
, "w");
56 /* Print a memory access 'access' to the printer 'p'.
58 * Given a map [a,b,c] -> {S[i,j] -> A[i,j+a]} we will print: A[i][j+a].
60 * In case the output dimensions is one dimensional and unnamed we assume this
61 * is not a memory access, but just an expression. This means the example
62 * [a,b,c] -> {S[i,j] -> [j+a]} will be printed as: j+a
64 * The code that is printed is C code and the variable parameter and input
65 * dimension names are derived from the isl_dim names.
67 static __isl_give isl_printer
*print_access(__isl_take isl_printer
*p
,
68 __isl_take isl_map
*access
)
73 isl_pw_multi_aff
*pma
;
75 n_index
= isl_map_dim(access
, isl_dim_out
);
76 name
= isl_map_get_tuple_name(access
, isl_dim_out
);
77 pma
= isl_pw_multi_aff_from_map(access
);
78 pma
= isl_pw_multi_aff_coalesce(pma
);
82 index
= isl_pw_multi_aff_get_pw_aff(pma
, 0);
83 p
= isl_printer_print_str(p
, "(");
84 p
= isl_printer_print_pw_aff(p
, index
);
85 p
= isl_printer_print_str(p
, ")");
86 isl_pw_aff_free(index
);
87 isl_pw_multi_aff_free(pma
);
91 p
= isl_printer_print_str(p
, name
);
93 for (i
= 0; i
< n_index
; ++i
) {
96 index
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
98 p
= isl_printer_print_str(p
, "[");
99 p
= isl_printer_print_pw_aff(p
, index
);
100 p
= isl_printer_print_str(p
, "]");
101 isl_pw_aff_free(index
);
104 isl_pw_multi_aff_free(pma
);
109 static __isl_give isl_printer
*print_cpu_access(__isl_take isl_printer
*p
,
110 struct pet_expr
*expr
, void *usr
)
112 isl_map
*access
= isl_map_copy(expr
->acc
.access
);
114 return print_access(p
, access
);
117 static void print_stmt_body(FILE *out
, struct pet_stmt
*stmt
)
119 isl_ctx
*ctx
= isl_set_get_ctx(stmt
->domain
);
122 p
= isl_printer_to_file(ctx
, out
);
123 p
= isl_printer_set_output_format(p
, ISL_FORMAT_C
);
124 p
= print_pet_expr(p
, stmt
->body
, &print_cpu_access
, out
);
128 /* Create a CloogInput data structure that describes the 'scop'.
130 static CloogInput
*cloog_input_from_scop(CloogState
*state
,
131 struct pet_scop
*scop
)
133 CloogDomain
*cloog_context
;
134 CloogUnionDomain
*ud
;
137 isl_union_set
*domain_set
;
138 isl_union_map
*schedule_map
;
140 scop
= pet_scop_align_params(scop
);
142 context
= isl_set_copy(scop
->context
);
143 domain_set
= pet_scop_collect_domains(scop
);
144 schedule_map
= pet_scop_collect_schedule(scop
);
145 schedule_map
= isl_union_map_intersect_domain(schedule_map
, domain_set
);
147 ud
= cloog_union_domain_from_isl_union_map(schedule_map
);
149 cloog_context
= cloog_domain_from_isl_set(context
);
151 input
= cloog_input_alloc(cloog_context
, ud
);
156 /* Print a #define macro for every statement in the 'scop'.
158 static void print_stmt_definitions(struct pet_scop
*scop
, FILE *output
)
162 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
163 struct pet_stmt
*stmt
= scop
->stmts
[i
];
164 const char *name
= isl_set_get_tuple_name(stmt
->domain
);
166 fprintf(output
, "#define %s(", name
);
168 for (j
= 0; j
< isl_set_dim(stmt
->domain
, isl_dim_set
); ++j
) {
172 fprintf(output
, ", ");
174 name
= isl_set_get_dim_name(stmt
->domain
, isl_dim_set
, j
);
175 fprintf(output
, "%s", name
);
178 fprintf(output
, ") ");
180 print_stmt_body(output
, stmt
);
182 fprintf(output
, "\n");
186 /* Code generate the scop 'scop' and print the corresponding C code to
189 static void print_scop(isl_ctx
*ctx
, struct pet_scop
*scop
, FILE *output
)
192 CloogOptions
*options
;
194 struct clast_stmt
*stmt
;
195 struct clast_printer_info code
;
197 state
= cloog_isl_state_malloc(ctx
);
199 options
= cloog_options_malloc(state
);
200 options
->language
= CLOOG_LANGUAGE_C
;
202 options
->strides
= 1;
204 input
= cloog_input_from_scop(state
, scop
);
205 stmt
= cloog_clast_create_from_input(input
, options
);
209 code
.print_user_stmt
= NULL
;
210 code
.print_user_stmt_list
= NULL
;
211 code
.print_for_head
= NULL
;
212 code
.print_for_foot
= NULL
;
214 print_cloog_macros(output
);
215 fprintf(output
, "\n");
216 print_stmt_definitions(scop
, output
);
217 fprintf(output
, "\n");
218 print_clast(&code
, stmt
);
220 cloog_clast_free(stmt
);
221 cloog_options_free(options
);
222 cloog_state_free(state
);
224 fprintf(output
, "\n");
227 int generate_cpu(isl_ctx
*ctx
, struct pet_scop
*scop
,
228 struct ppcg_options
*options
, const char *input
)
236 input_file
= fopen(input
, "r");
237 output_file
= get_output_file(input
);
239 copy_before_scop(input_file
, output_file
);
240 fprintf(output_file
, "/* ppcg generated CPU code */\n\n");
241 print_scop(ctx
, scop
, output_file
);
242 copy_after_scop(input_file
, output_file
);