update isl to version 0.10
[ppcg.git] / cpu.c
blob0ecbce7ec68a33a2a46b36eed3299ea38db51939
1 /*
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
9 */
11 #include <limits.h>
12 #include <stdio.h>
14 #include <cloog/cloog.h>
15 #include <cloog/isl/cloog.h>
16 #include <isl/aff.h>
17 #include <isl/ctx.h>
18 #include <isl/map.h>
19 #include <pet.h>
21 #include "clast_printer.h"
22 #include "cpu.h"
23 #include "pet_printer.h"
24 #include "rewrite.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)
35 char name[PATH_MAX];
36 const char *base;
37 const char *ext;
38 const char ppcg_marker[] = ".ppcg";
39 int len;
41 base = strrchr(input, '/');
42 if (base)
43 base++;
44 else
45 base = 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)
69 int i;
70 const char *name;
71 unsigned n_index;
72 isl_printer *prn;
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);
82 if (name == NULL) {
83 isl_pw_aff *index;
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);
91 return;
94 fprintf(out, "%s", name);
96 for (i = 0; i < n_index; ++i) {
97 isl_pw_aff *index;
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;
130 CloogInput *input;
131 isl_set *context;
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);
148 return input;
151 /* Print a #define macro for every statement in the 'scop'.
153 static void print_stmt_definitions(struct pet_scop *scop, FILE *output)
155 int i, j;
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) {
164 const char *name;
166 if (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
182 * 'output'.
184 static void print_scop(isl_ctx *ctx, struct pet_scop *scop, FILE *output)
186 CloogState *state;
187 CloogOptions *options;
188 CloogInput *input;
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;
196 options->otl = 1;
197 options->strides = 1;
199 input = cloog_input_from_scop(state, scop);
200 stmt = cloog_clast_create_from_input(input, options);
202 code.indent = 0;
203 code.dst = output;
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)
225 FILE *input_file;
226 FILE *output_file;
228 if (!scop)
229 return -1;
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);
239 fclose(output_file);
240 fclose(input_file);
242 return 0;