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 output file 'out'.
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 void print_access(__isl_take isl_map
*access
, FILE *out
)
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
);
79 prn
= isl_printer_to_file(isl_map_get_ctx(access
), out
);
80 prn
= isl_printer_set_output_format(prn
, ISL_FORMAT_C
);
84 index
= isl_pw_multi_aff_get_pw_aff(pma
, 0);
85 isl_printer_print_str(prn
, "(");
86 prn
= isl_printer_print_pw_aff(prn
, index
);
87 isl_printer_print_str(prn
, ")");
88 isl_pw_aff_free(index
);
89 isl_printer_free(prn
);
90 isl_pw_multi_aff_free(pma
);
94 fprintf(out
, "%s", name
);
96 for (i
= 0; i
< n_index
; ++i
) {
99 index
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
101 isl_printer_print_str(prn
, "[");
102 prn
= isl_printer_print_pw_aff(prn
, index
);
103 isl_printer_print_str(prn
, "]");
104 isl_pw_aff_free(index
);
107 isl_printer_free(prn
);
108 isl_pw_multi_aff_free(pma
);
111 static void print_cpu_access(struct pet_expr
*expr
, void *usr
)
113 FILE *out
= (FILE *) usr
;
114 isl_map
*access
= isl_map_copy(expr
->acc
.access
);
115 print_access(access
, out
);
118 static void print_stmt_body(FILE *out
, struct pet_stmt
*stmt
)
120 print_pet_expr(out
, stmt
->body
, print_cpu_access
, out
);
123 /* Create a CloogInput data structure that describes the 'scop'.
125 static CloogInput
*cloog_input_from_scop(CloogState
*state
,
126 struct pet_scop
*scop
)
128 CloogDomain
*cloog_context
;
129 CloogUnionDomain
*ud
;
132 isl_union_set
*domain_set
;
133 isl_union_map
*schedule_map
;
135 scop
= pet_scop_align_params(scop
);
137 context
= isl_set_copy(scop
->context
);
138 domain_set
= pet_scop_collect_domains(scop
);
139 schedule_map
= pet_scop_collect_schedule(scop
);
140 schedule_map
= isl_union_map_intersect_domain(schedule_map
, domain_set
);
142 ud
= cloog_union_domain_from_isl_union_map(schedule_map
);
144 cloog_context
= cloog_domain_from_isl_set(context
);
146 input
= cloog_input_alloc(cloog_context
, ud
);
151 /* Print a #define macro for every statement in the 'scop'.
153 static void print_stmt_definitions(struct pet_scop
*scop
, FILE *output
)
157 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
158 struct pet_stmt
*stmt
= scop
->stmts
[i
];
159 const char *name
= isl_set_get_tuple_name(stmt
->domain
);
161 fprintf(output
, "#define %s(", name
);
163 for (j
= 0; j
< isl_set_dim(stmt
->domain
, isl_dim_set
); ++j
) {
167 fprintf(output
, ", ");
169 name
= isl_set_get_dim_name(stmt
->domain
, isl_dim_set
, j
);
170 fprintf(output
, "%s", name
);
173 fprintf(output
, ") ");
175 print_stmt_body(output
, stmt
);
177 fprintf(output
, "\n");
181 /* Code generate the scop 'scop' and print the corresponding C code to
184 static void print_scop(isl_ctx
*ctx
, struct pet_scop
*scop
, FILE *output
)
187 CloogOptions
*options
;
189 struct clast_stmt
*stmt
;
190 struct clast_printer_info code
;
192 state
= cloog_isl_state_malloc(ctx
);
194 options
= cloog_options_malloc(state
);
195 options
->language
= CLOOG_LANGUAGE_C
;
197 options
->strides
= 1;
199 input
= cloog_input_from_scop(state
, scop
);
200 stmt
= cloog_clast_create_from_input(input
, options
);
204 code
.print_user_stmt
= NULL
;
205 code
.print_user_stmt_list
= NULL
;
206 code
.print_for_head
= NULL
;
207 code
.print_for_foot
= NULL
;
209 print_cloog_macros(output
);
210 fprintf(output
, "\n");
211 print_stmt_definitions(scop
, output
);
212 fprintf(output
, "\n");
213 print_clast(&code
, stmt
);
215 cloog_clast_free(stmt
);
216 cloog_options_free(options
);
217 cloog_state_free(state
);
219 fprintf(output
, "\n");
222 int generate_cpu(isl_ctx
*ctx
, struct pet_scop
*scop
,
223 struct ppcg_options
*options
, const char *input
)
231 input_file
= fopen(input
, "r");
232 output_file
= get_output_file(input
);
234 copy_before_scop(input_file
, output_file
);
235 fprintf(output_file
, "/* ppcg generated CPU code */\n\n");
236 print_scop(ctx
, scop
, output_file
);
237 copy_after_scop(input_file
, output_file
);