2 * Copyright 2011 Leiden University. All rights reserved.
7 #include <libxml/xmlwriter.h>
8 #include <isl/ast_build.h>
9 #include <isl/union_map.h>
13 static void writeVar(xmlTextWriterPtr writer
, adg_var
*var
)
18 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
19 BAD_CAST var
->get_expr());
23 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"dataType",
24 BAD_CAST
isl_id_get_name(var
->type
));
28 static void writeVar(xmlTextWriterPtr writer
, const char *type
, adg_var
*var
)
32 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
35 writeVar(writer
, var
);
37 rc
= xmlTextWriterEndElement(writer
);
41 static void writeArg(xmlTextWriterPtr writer
, const char *type
, adg_arg
*arg
)
45 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
48 writeVar(writer
, arg
->var
);
52 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
56 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
57 BAD_CAST
"return_value");
59 case adg_arg_reference
:
60 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
61 BAD_CAST
"reference");
69 rc
= xmlTextWriterEndElement(writer
);
73 /* Print "v * name" onto os.
75 static void print_term(std::ostringstream
&os
, __isl_keep isl_val
*v
,
78 if (!isl_val_is_one(v
)) {
79 os
<< isl_val_get_num_si(v
);
85 static void print_aff_expr(std::ostringstream
&os
, __isl_keep isl_aff
*aff
);
87 /* Print "v * div(aff)" onto os.
89 static void print_term(std::ostringstream
&os
, __isl_keep isl_val
*v
,
90 __isl_take isl_aff
*aff
)
94 if (!isl_val_is_one(v
)) {
95 os
<< isl_val_get_num_si(v
);
98 d
= isl_aff_get_denominator_val(aff
);
99 aff
= isl_aff_scale_val(aff
, isl_val_copy(d
));
101 print_aff_expr(os
, aff
);
103 os
<< isl_val_get_num_si(d
);
109 /* Print "aff" onto os.
111 static void print_aff_expr(std::ostringstream
&os
, __isl_keep isl_aff
*aff
)
115 enum isl_dim_type types
[] = { isl_dim_in
, isl_dim_param
, isl_dim_div
};
116 int n_type
= sizeof(types
)/sizeof(*types
);
118 d
= isl_aff_get_denominator_val(aff
);
119 if (!isl_val_is_one(d
))
121 for (int t
= 0; t
< n_type
; ++t
) {
122 for (int i
= 0; i
< isl_aff_dim(aff
, types
[t
]); ++i
) {
123 v
= isl_aff_get_coefficient_val(aff
, types
[t
], i
);
124 if (isl_val_is_zero(v
)) {
128 if (!first
&& isl_val_is_pos(v
))
130 if (types
[t
] == isl_dim_div
) {
132 div
= isl_aff_get_div(aff
, i
);
133 print_term(os
, v
, div
);
136 name
= isl_aff_get_dim_name(aff
, types
[t
], i
);
137 print_term(os
, v
, name
);
144 v
= isl_aff_get_constant_val(aff
);
145 if (first
|| !isl_val_is_zero(v
)) {
146 if (!first
&& isl_val_is_pos(v
))
148 os
<< isl_val_get_num_si(v
);
152 if (!isl_val_is_one(d
)) {
154 os
<< isl_val_get_num_si(d
);
159 struct print_pw_aff_data
{
160 std::ostringstream
&os
;
161 std::vector
<isl_id
*> &iterators
;
164 print_pw_aff_data(std::ostringstream
&os
,
165 std::vector
<isl_id
*> &iterators
) :
166 os(os
), iterators(iterators
), first(true) {}
170 static isl_stat
print_pw_aff_piece(__isl_take isl_set
*set
,
171 __isl_take isl_aff
*aff
, void *user
);
174 /* Print a single piece of an isl_pw_aff.
175 * We currently assume that there is only a single piece
176 * and abort if there happens to be more than one.
178 static isl_stat
print_pw_aff_piece(__isl_take isl_set
*set
,
179 __isl_take isl_aff
*aff
, void *user
)
181 struct print_pw_aff_data
*data
= (struct print_pw_aff_data
*) user
;
185 print_aff_expr(data
->os
, aff
);
194 static void print_pw_aff_expr(std::ostringstream
&os
, __isl_keep isl_pw_aff
*pa
,
195 std::vector
<isl_id
*> &iterators
)
197 struct print_pw_aff_data
data(os
, iterators
);
198 isl_pw_aff_foreach_piece(pa
, &print_pw_aff_piece
, &data
);
201 static void writeExpr(xmlTextWriterPtr writer
, const char *type
,
202 const char *expr_name
, adg_expr
*expr
, adg
*graph
)
205 std::ostringstream strm
;
207 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
211 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
212 BAD_CAST
isl_id_get_name(expr
->name
));
216 print_pw_aff_expr(strm
, expr
->expr
, graph
->iterators
);
217 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST expr_name
,
218 BAD_CAST strm
.str().c_str());
221 rc
= xmlTextWriterEndElement(writer
);
225 /* Write out the rows of "mat", each prefixed by the integer "ineq".
226 * The rows are separated by ";". If first is false, then we
227 * also include a ";" before the first row.
229 static void writeMatrix(std::ostream
&os
, __isl_keep isl_mat
*mat
,
230 int ineq
, bool first
)
235 for (i
= 0; i
< isl_mat_rows(mat
); ++i
) {
240 for (j
= 0; j
< isl_mat_cols(mat
); ++j
) {
241 v
= isl_mat_get_element_val(mat
, i
, j
);
242 os
<< ", " << isl_val_get_num_si(v
);
248 /* Find the number of dynamic control variables in "space".
250 * The dynamic control variables, if any, are located in the range
251 * of a wrapped map, with the (possibly lifted) iteration domain
252 * in the domain. After adding the dynamic control variables, the
253 * result may have been lifted as well, so we need dig through
254 * any possible lifting of the form
256 * D -> [D -> local[..]]
258 * until we arrive at the iteration domain, in which case there
259 * are no dynamic control variables, or until we find the control
262 static int n_dynamic_in_space(__isl_take isl_space
*space
)
266 if (!isl_space_is_wrapping(space
)) {
267 isl_space_free(space
);
270 space
= isl_space_unwrap(space
);
271 if (isl_space_has_tuple_id(space
, isl_dim_out
))
272 return n_dynamic_in_space(isl_space_domain(space
));
273 n
= isl_space_dim(space
, isl_dim_out
);
274 isl_space_free(space
);
278 /* Find the position of the first dynamic control variable in "space".
280 * See n_dynamic_in_space.
282 static int pos_dynamic_in_space(__isl_take isl_space
*space
)
286 if (!isl_space_is_wrapping(space
)) {
287 isl_space_free(space
);
290 space
= isl_space_unwrap(space
);
291 if (isl_space_has_tuple_id(space
, isl_dim_out
))
292 return pos_dynamic_in_space(isl_space_domain(space
));
293 pos
= isl_space_dim(space
, isl_dim_in
);
294 isl_space_free(space
);
298 /* Write a matrix corresponding to the constraints of "bset".
299 * The order of the dimensions in the matrix is a follows.
301 * iterators static_controls dynamic_controls parameters constant
303 * Inside "bset", however, in the set dimensions, the dynamic
304 * controls may appear in the middle of the static controls.
306 * We therefore need to move the dynamic controls.
307 * "pos_dynamic" indicates the position of the first dynamic control.
308 * "n_dynamic" indicates the number of dynamic controls.
310 static void writeMatrix(xmlTextWriterPtr writer
, const char *name
,
311 __isl_keep isl_basic_set
*bset
, int n_dynamic
)
315 std::ostringstream strm
;
317 int n_set
= isl_basic_set_dim(bset
, isl_dim_set
);
318 int pos_dynamic
= pos_dynamic_in_space(isl_basic_set_get_space(bset
));
320 rc
= xmlTextWriterStartElement(writer
, BAD_CAST name
);
324 mat
= isl_basic_set_equalities_matrix(bset
,
325 isl_dim_set
, isl_dim_div
, isl_dim_param
, isl_dim_cst
);
326 mat
= isl_mat_move_cols(mat
, n_set
- n_dynamic
, pos_dynamic
, n_dynamic
);
327 writeMatrix(strm
, mat
, 0, first
);
328 first
= isl_mat_rows(mat
) == 0;
331 mat
= isl_basic_set_inequalities_matrix(bset
,
332 isl_dim_set
, isl_dim_div
, isl_dim_param
, isl_dim_cst
);
333 mat
= isl_mat_move_cols(mat
, n_set
- n_dynamic
, pos_dynamic
, n_dynamic
);
334 writeMatrix(strm
, mat
, 1, first
);
338 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"matrix",
339 BAD_CAST strm
.str().c_str());
342 rc
= xmlTextWriterEndElement(writer
);
346 /* Print the coefficients of the affine expression "aff",
347 * separated by commas.
349 * Note that the set dimensions of "aff" are given in the order
351 * iterators static_and_dynamic_controls
353 * while the coefficients should be printed in the order
355 * iterators static_controls dynamic_controls parameters constant
357 static void print_aff_coefficients(std::ostringstream
&os
,
358 __isl_keep isl_aff
*aff
)
367 space
= isl_aff_get_domain_space(aff
);
368 pos_dynamic
= pos_dynamic_in_space(isl_space_copy(space
));
369 n_dynamic
= n_dynamic_in_space(space
);
370 n_index
= isl_aff_dim(aff
, isl_dim_in
) - n_dynamic
;
372 for (int i
= 0; i
< pos_dynamic
; ++i
) {
375 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, i
);
376 os
<< isl_val_get_num_si(v
);
381 for (int i
= pos_dynamic
; i
< n_index
; ++i
) {
384 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, n_dynamic
+ i
);
385 os
<< isl_val_get_num_si(v
);
390 for (int i
= 0; i
< n_dynamic
; ++i
) {
393 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
,
395 os
<< isl_val_get_num_si(v
);
400 for (int i
= 0; i
< isl_aff_dim(aff
, isl_dim_param
); ++i
) {
403 v
= isl_aff_get_coefficient_val(aff
, isl_dim_param
, i
);
404 os
<< isl_val_get_num_si(v
);
411 v
= isl_aff_get_constant_val(aff
);
412 os
<< isl_val_get_num_si(v
);
416 /* Write out "map" in the form of a matrix, with each row
417 * corresponding to an affine expression.
419 static void writeMatrix(xmlTextWriterPtr writer
, const char *name
,
420 __isl_keep isl_multi_aff
*map
)
423 std::ostringstream strm
;
426 rc
= xmlTextWriterStartElement(writer
, BAD_CAST name
);
430 n
= isl_multi_aff_dim(map
, isl_dim_out
);
431 for (int i
= 0; i
< n
; ++i
) {
435 aff
= isl_multi_aff_get_aff(map
, i
);
436 print_aff_coefficients(strm
, aff
);
441 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"matrix",
442 BAD_CAST strm
.str().c_str());
445 rc
= xmlTextWriterEndElement(writer
);
449 struct write_bound_data
{
450 xmlTextWriterPtr writer
;
455 static isl_stat
write_bound(__isl_take isl_basic_set
*bset
, void *user
)
459 std::ostringstream strm
;
460 write_bound_data
*data
= (write_bound_data
*) user
;
461 xmlTextWriterPtr writer
= data
->writer
;
463 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"linearbound");
466 for (int i
= 0; i
< data
->graph
->iterators
.size(); ++i
) {
469 strm
<< isl_id_get_name(data
->graph
->iterators
[i
]);
472 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"index",
473 BAD_CAST strm
.str().c_str());
477 for (int i
= 0; i
< data
->domain
->controls
.size(); ++i
) {
480 strm
<< isl_id_get_name(data
->domain
->controls
[i
]->name
);
482 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"staticControl",
483 BAD_CAST strm
.str().c_str());
487 for (int i
= 0; i
< data
->domain
->filters
.size(); ++i
) {
490 strm
<< data
->domain
->filters
[i
]->get_expr();
492 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"dynamicControl",
493 BAD_CAST strm
.str().c_str());
497 nparam
= isl_basic_set_dim(bset
, isl_dim_param
);
498 for (int i
= 0; i
< nparam
; ++i
) {
501 strm
<< isl_basic_set_get_dim_name(bset
, isl_dim_param
, i
);
503 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"parameter",
504 BAD_CAST strm
.str().c_str());
507 bset
= isl_basic_set_remove_redundancies(bset
);
508 writeMatrix(writer
, "constraint", bset
, data
->domain
->filters
.size());
510 isl_basic_set_free(bset
);
512 if (data
->graph
->context
&&
513 !isl_set_plain_is_universe(data
->graph
->context
)) {
514 assert(isl_set_n_basic_set(data
->graph
->context
) == 1);
515 bset
= isl_set_simple_hull(isl_set_copy(data
->graph
->context
));
516 bset
= isl_basic_set_remove_redundancies(bset
);
517 writeMatrix(writer
, "context", bset
, 0);
518 isl_basic_set_free(bset
);
521 for (int i
= 0; i
< data
->domain
->controls
.size(); ++i
)
522 writeExpr(writer
, "control", "exp", data
->domain
->controls
[i
],
525 rc
= xmlTextWriterEndElement(writer
);
531 static void writeDomain(xmlTextWriterPtr writer
, adg_domain
*domain
, adg
*graph
)
534 write_bound_data data
= { writer
, domain
, graph
};
536 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"domain");
539 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
543 rc
= isl_set_foreach_basic_set(domain
->bounds
, &write_bound
, &data
);
546 rc
= xmlTextWriterEndElement(writer
);
550 static void writePort(xmlTextWriterPtr writer
, adg_port
*port
, bool output
,
556 type
= output
? "outport" : "inport";
558 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
562 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
563 BAD_CAST
isl_id_get_name(port
->name
));
564 assert(port
->node_name
);
565 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"node",
566 BAD_CAST
isl_id_get_name(port
->node_name
));
567 assert(port
->edge_name
);
568 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"edge",
569 BAD_CAST
isl_id_get_name(port
->edge_name
));
571 for (int i
= 0; i
< port
->vars
.size(); ++i
)
572 writeVar(writer
, "bindvariable", port
->vars
[i
]);
574 writeDomain(writer
, port
->domain
, graph
);
576 rc
= xmlTextWriterEndElement(writer
);
580 static void writeGate(xmlTextWriterPtr writer
, adg_gate
*gate
, adg
*graph
)
584 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"invar");
588 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
589 BAD_CAST
isl_id_get_name(gate
->name
));
591 assert(gate
->in
&& gate
->in
->access
);
592 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"realName",
593 BAD_CAST gate
->in
->get_expr());
596 writeVar(writer
, "bindvariable", gate
->out
);
598 writeDomain(writer
, gate
->domain
, graph
);
600 rc
= xmlTextWriterEndElement(writer
);
604 static void writeFunction(xmlTextWriterPtr writer
, adg_function
*fn
, adg
*graph
)
608 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"function");
612 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
613 BAD_CAST
isl_id_get_name(fn
->name
));
615 for (int i
= 0; i
< fn
->in
.size(); ++i
)
616 writeArg(writer
, "inargument", fn
->in
[i
]);
617 for (int i
= 0; i
< fn
->out
.size(); ++i
)
618 writeArg(writer
, "outargument", fn
->out
[i
]);
619 for (int i
= 0; i
< fn
->ctrl
.size(); ++i
)
620 writeExpr(writer
, "ctrlvar", "iterator", fn
->ctrl
[i
], graph
);
622 writeDomain(writer
, fn
->domain
, graph
);
624 rc
= xmlTextWriterEndElement(writer
);
628 /* The gates should be printed after the input ports because
629 * they may use data read through an input port.
631 static void writeNode(xmlTextWriterPtr writer
, adg_node
*node
, adg
*graph
)
635 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"node");
639 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
640 BAD_CAST
isl_id_get_name(node
->name
));
642 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"levelUpNode",
646 for (int i
= 0; i
< node
->input_ports
.size(); ++i
)
647 writePort(writer
, node
->input_ports
[i
], false, graph
);
649 for (int i
= 0; i
< node
->gates
.size(); ++i
)
650 writeGate(writer
, node
->gates
[i
], graph
);
652 for (int i
= 0; i
< node
->output_ports
.size(); ++i
)
653 writePort(writer
, node
->output_ports
[i
], true, graph
);
655 for (int i
= 0; i
< node
->expressions
.size(); ++i
)
656 writeExpr(writer
, "expression", "value",
657 node
->expressions
[i
], graph
);
659 writeFunction(writer
, node
->function
, graph
);
661 writeDomain(writer
, node
->domain
, graph
);
663 rc
= xmlTextWriterEndElement(writer
);
667 static void writeEdge(xmlTextWriterPtr writer
, adg_edge
*edge
)
670 std::ostringstream strm
;
673 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"edge");
677 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
678 BAD_CAST
isl_id_get_name(edge
->name
));
681 assert(edge
->from_port_name
);
682 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"fromPort",
683 BAD_CAST
isl_id_get_name(edge
->from_port_name
));
686 assert(edge
->from_node_name
);
687 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"fromNode",
688 BAD_CAST
isl_id_get_name(edge
->from_node_name
));
691 assert(edge
->to_port_name
);
692 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"toPort",
693 BAD_CAST
isl_id_get_name(edge
->to_port_name
));
696 assert(edge
->to_node_name
);
697 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"toNode",
698 BAD_CAST
isl_id_get_name(edge
->to_node_name
));
701 s
= isl_val_to_str(edge
->value_size
);
702 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"size", BAD_CAST s
);
706 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"linearization");
709 switch (edge
->type
) {
711 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
714 case adg_edge_sticky_fifo
:
715 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
716 BAD_CAST
"sticky_fifo");
718 case adg_edge_shift_register
:
719 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
720 BAD_CAST
"shift_register");
722 case adg_edge_broadcast
:
723 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
724 BAD_CAST
"BroadcastInOrder");
726 case adg_edge_generic
:
727 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
728 BAD_CAST
"GenericOutOfOrder");
736 rc
= xmlTextWriterEndElement(writer
);
739 writeMatrix(writer
, "mapping", edge
->map
);
741 rc
= xmlTextWriterEndElement(writer
);
745 static void writeParam(xmlTextWriterPtr writer
, adg_param
*param
, adg
*graph
)
748 std::ostringstream strm
;
750 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"parameter");
754 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
755 BAD_CAST
isl_id_get_name(param
->name
));
760 print_aff_expr(strm
, param
->lb
);
761 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"lb",
762 BAD_CAST strm
.str().c_str());
768 print_aff_expr(strm
, param
->ub
);
769 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"ub",
770 BAD_CAST strm
.str().c_str());
776 print_aff_expr(strm
, param
->val
);
777 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"value",
778 BAD_CAST strm
.str().c_str());
782 rc
= xmlTextWriterEndElement(writer
);
786 static void writeADG(xmlTextWriterPtr writer
, adg
*graph
)
790 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"adg");
794 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
795 BAD_CAST
isl_id_get_name(graph
->name
));
797 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"levelUpNode",
801 for (int i
= 0; i
< graph
->params
.size(); ++i
)
802 writeParam(writer
, graph
->params
[i
], graph
);
804 for (int i
= 0; i
< graph
->nodes
.size(); ++i
)
805 writeNode(writer
, graph
->nodes
[i
], graph
);
807 for (int i
= 0; i
< graph
->edges
.size(); ++i
)
808 writeEdge(writer
, graph
->edges
[i
]);
810 rc
= xmlTextWriterEndElement(writer
);
814 /* Project out all the lifted variables that used to be
815 * existentially quantified. In other words, undo the lifting.
816 * Also project out the dynamic control variables.
818 static __isl_give isl_set
*unwrap(__isl_take isl_set
*dom
)
820 if (!isl_set_is_wrapping(dom
))
822 return unwrap(isl_map_domain(isl_set_unwrap(dom
)));
825 /* Project out all the lifted variables that used to be
826 * existentially quantified. In other words, undo the lifting.
827 * Turn the dynamic control variables into parameters.
828 * The names of those parameters are taken from "filters".
830 static __isl_give isl_set
*unwrap_filtered(__isl_take isl_set
*dom
,
831 std::vector
<adg_var
*> &filters
)
837 if (!isl_set_is_wrapping(dom
))
840 map
= isl_set_unwrap(dom
);
841 if (isl_map_has_tuple_name(map
, isl_dim_out
))
842 return unwrap_filtered(isl_map_domain(map
), filters
);
844 nparam
= isl_map_dim(map
, isl_dim_param
);
846 map
= isl_map_add_dims(map
, isl_dim_param
, n
);
847 for (i
= 0; i
< n
; ++i
) {
850 id
= isl_pw_multi_aff_get_tuple_id(filters
[i
]->access
,
852 map
= isl_map_set_dim_id(map
, isl_dim_param
, nparam
+ i
, id
);
853 map
= isl_map_equate(map
, isl_dim_param
, nparam
+ i
,
857 return unwrap(isl_map_domain(map
));
860 /* Construct a schedule by adding an extra pair of dimensions to
861 * domain->schedule, fixed to "offset1" and "offset2"
862 * and setting the input name to "name".
864 * If "filtered" is set, then the dynamic control variables are preserved
865 * (as parameters) in the resulting schedule.
867 static __isl_give isl_map
*domain_schedule(adg_node
*node
, adg_domain
*domain
,
868 int offset1
, int offset2
, __isl_take isl_id
*name
, bool filtered
)
874 n_out
= isl_map_dim(node
->schedule
, isl_dim_out
);
876 dom
= isl_set_copy(domain
->bounds
);
878 dom
= unwrap_filtered(dom
, domain
->filters
);
882 sched
= isl_map_copy(node
->schedule
);
883 sched
= isl_map_intersect_domain(sched
, dom
);
884 sched
= isl_map_add_dims(sched
, isl_dim_out
, 2);
885 sched
= isl_map_fix_si(sched
, isl_dim_out
, n_out
, offset1
);
886 sched
= isl_map_fix_si(sched
, isl_dim_out
, n_out
+ 1, offset2
);
887 sched
= isl_map_set_tuple_id(sched
, isl_dim_in
, name
);
892 static __isl_give isl_map
*port_schedule(adg_node
*node
, adg_port
*port
,
893 int offset
, bool filtered
)
895 return domain_schedule(node
, port
->domain
, offset
, port
->arg_pos
,
896 isl_id_copy(port
->name
), filtered
);
899 static __isl_give isl_map
*gate_schedule(adg_node
*node
, adg_gate
*gate
,
900 int offset
, bool filtered
)
902 return domain_schedule(node
, gate
->domain
, offset
, 0,
903 isl_id_copy(gate
->name
), filtered
);
906 /* Construct a schedule for all elements in the node.
907 * We add an extra dimension to node->schedule to ensure that
908 * the different elements are executed in the right order:
909 * input ports, gates, function, output ports.
910 * The input ports themselves are ordered according to the access nr.
912 * If "filtered" is set, then the dynamic control variables are preserved
913 * (as parameters) in the resulting schedule.
915 static __isl_give isl_union_map
*collect_node_schedule(adg_node
*node
, int n
,
919 isl_union_map
*sched
;
922 n_out
= isl_map_dim(node
->schedule
, isl_dim_out
);
924 sched_f
= domain_schedule(node
, node
->function
->domain
, 4 * n
+ 2, 0,
925 isl_id_copy(node
->name
), filtered
);
926 sched
= isl_union_map_from_map(sched_f
);
928 for (int i
= 0; i
< node
->input_ports
.size(); ++i
) {
930 sched_p
= port_schedule(node
, node
->input_ports
[i
], 4 * n
+ 0,
932 sched
= isl_union_map_add_map(sched
, sched_p
);
935 for (int i
= 0; i
< node
->gates
.size(); ++i
) {
937 sched_p
= gate_schedule(node
, node
->gates
[i
], 4 * n
+ 1,
939 sched
= isl_union_map_add_map(sched
, sched_p
);
942 for (int i
= 0; i
< node
->output_ports
.size(); ++i
) {
944 sched_p
= port_schedule(node
, node
->output_ports
[i
], 4 * n
+ 3,
946 sched
= isl_union_map_add_map(sched
, sched_p
);
952 /* Construct a schedule for all nodes in the graph.
954 * If "filtered" is set, then the dynamic control variables are preserved
955 * (as parameters) in the resulting schedule.
957 static isl_union_map
*collect_schedule(adg
*graph
, bool filtered
)
959 isl_space
*space
= isl_set_get_space(graph
->context
);
960 isl_union_map
*sched
= isl_union_map_empty(space
);
962 for (int i
= 0; i
< graph
->nodes
.size(); ++i
) {
963 isl_union_map
*sched_i
;
964 sched_i
= collect_node_schedule(graph
->nodes
[i
], i
, filtered
);
965 sched
= isl_union_map_union(sched
, sched_i
);
971 /* Set the "atomic" option on all the dimensions of a schedule
972 * of dimension "sched_len".
974 static __isl_give isl_ast_build
*set_atomic(
975 __isl_take isl_ast_build
*context
, int sched_len
)
981 ctx
= isl_ast_build_get_ctx(context
);
983 space
= isl_space_alloc(ctx
, 0, sched_len
, 1);
984 space
= isl_space_set_tuple_name(space
, isl_dim_out
, "atomic");
985 opt
= isl_union_map_from_map(isl_map_universe(space
));
987 context
= isl_ast_build_set_options(context
, opt
);
992 /* This function is called for each leaf in the AST constructed
993 * from the schedule without dynamic control variables.
994 * Continue constructing an inner AST for the schedule with
995 * the dynamic control variables as parameters.
997 static __isl_give isl_ast_node
*create_leaf(__isl_take isl_ast_build
*build
,
1001 isl_union_map
*sched
;
1002 isl_union_map
*sched2
= (isl_union_map
*) user
;
1004 sched
= isl_ast_build_get_schedule(build
);
1005 sched
= isl_union_map_range_product(sched
, isl_union_map_copy(sched2
));
1006 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
1007 isl_ast_build_free(build
);
1012 /* Does the adg contain any dynamic control variables?
1014 static bool any_filters(adg
*graph
)
1016 for (int i
= 0; i
< graph
->nodes
.size(); ++i
) {
1017 adg_node
*node
= graph
->nodes
[i
];
1019 for (int j
= 0; j
< node
->input_ports
.size(); ++j
)
1020 if (node
->input_ports
[j
]->domain
->filters
.size() > 0)
1022 for (int j
= 0; j
< node
->gates
.size(); ++j
)
1023 if (node
->gates
[j
]->domain
->filters
.size() > 0)
1025 for (int j
= 0; j
< node
->output_ports
.size(); ++j
)
1026 if (node
->output_ports
[j
]->domain
->filters
.size() > 0)
1033 /* Construct a schedule, convert it to an AST and then
1034 * write out the AST using writeAST.
1036 * To handle dynamic control variables, we construct two schedules,
1037 * one (sched) with the dynamic control variables projected out and
1038 * one (sched2) with the dynamic control variables as parameters.
1040 * We construct an AST for the first schedule and within each leaf
1041 * of the AST, we construct an AST for the second schedule.
1042 * This inner AST will essentially reflect the conditions on
1043 * the dynamic control variables.
1045 * Note that we only need to create this second schedule if there actually
1046 * are any dynamic control variables.
1048 static void writeAST(xmlTextWriterPtr writer
, adg
*graph
)
1051 isl_ctx
*ctx
= isl_set_get_ctx(graph
->context
);
1052 isl_union_map
*sched
, *sched2
= NULL
;
1053 isl_ast_build
*build
;
1055 isl_id_list
*iterators
;
1058 isl_options_set_ast_build_atomic_upper_bound(ctx
, 1);
1059 isl_options_set_ast_build_prefer_pdiv(ctx
, 1);
1060 isl_options_set_ast_build_allow_else(ctx
, 0);
1061 isl_options_set_ast_build_allow_or(ctx
, 0);
1063 has_filters
= any_filters(graph
);
1065 sched
= collect_schedule(graph
, false);
1067 sched2
= collect_schedule(graph
, true);
1069 iterators
= isl_id_list_alloc(ctx
, graph
->all_iterators
.size());
1070 for (int i
= 0; i
< graph
->all_iterators
.size(); ++i
)
1071 iterators
= isl_id_list_add(iterators
,
1072 isl_id_copy(graph
->all_iterators
[i
]));
1073 build
= isl_ast_build_from_context(isl_set_copy(graph
->context
));
1074 build
= isl_ast_build_set_iterators(build
, iterators
);
1076 build
= isl_ast_build_set_create_leaf(build
,
1077 &create_leaf
, sched2
);
1078 build
= set_atomic(build
, graph
->all_iterators
.size() + 2);
1079 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
1080 isl_ast_build_free(build
);
1082 writeAST(writer
, tree
);
1084 isl_union_map_free(sched2
);
1085 isl_ast_node_free(tree
);
1088 /* Write out an XML representation of "graph" to "out".
1089 * The adg part is obtained by scanning the data structure.
1090 * The ast part is obtained by generating code based on the domain schedules.
1092 void adg_print_xml(adg
*graph
, FILE *out
)
1095 xmlTextWriterPtr writer
;
1100 writer
= xmlNewTextWriterDoc(&doc
, 0);
1103 rc
= xmlTextWriterStartDocument(writer
, NULL
, NULL
, NULL
);
1106 rc
= xmlTextWriterStartDTD(writer
, BAD_CAST
"sadg",
1107 BAD_CAST
"-//LIACS//DTD ESPAM 1//EN",
1108 BAD_CAST
"http://www.liacs.nl/~cserc/dtd/espam_1.dtd");
1110 rc
= xmlTextWriterEndDTD(writer
);
1113 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"sadg");
1116 writeADG(writer
, graph
);
1117 writeAST(writer
, graph
);
1119 rc
= xmlTextWriterEndElement(writer
);
1122 rc
= xmlTextWriterEndDocument(writer
);
1125 xmlFreeTextWriter(writer
);
1127 rc
= xmlDocFormatDump(out
, doc
, 1);