2 * Copyright 2011 Leiden University. All rights reserved.
7 #include <libxml/xmlwriter.h>
10 #include <isl/space.h>
15 #include <isl/ast_build.h>
16 #include <isl/union_map.h>
20 static void writeVar(xmlTextWriterPtr writer
, adg_var
*var
)
25 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
26 BAD_CAST var
->get_expr());
30 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"dataType",
31 BAD_CAST
isl_id_get_name(var
->type
));
35 static void writeVar(xmlTextWriterPtr writer
, const char *type
, adg_var
*var
)
39 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
42 writeVar(writer
, var
);
44 rc
= xmlTextWriterEndElement(writer
);
48 static void writeArg(xmlTextWriterPtr writer
, const char *type
, adg_arg
*arg
)
52 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
55 writeVar(writer
, arg
->var
);
59 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
63 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
64 BAD_CAST
"return_value");
66 case adg_arg_reference
:
67 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"pass",
68 BAD_CAST
"reference");
76 rc
= xmlTextWriterEndElement(writer
);
80 /* Print "v * name" onto os.
82 static void print_term(std::ostringstream
&os
, __isl_keep isl_val
*v
,
85 if (!isl_val_is_one(v
)) {
86 os
<< isl_val_get_num_si(v
);
92 static void print_aff_expr(std::ostringstream
&os
, __isl_keep isl_aff
*aff
);
94 /* Print "v * div(aff)" onto os.
96 static void print_term(std::ostringstream
&os
, __isl_keep isl_val
*v
,
97 __isl_take isl_aff
*aff
)
101 if (!isl_val_is_one(v
)) {
102 os
<< isl_val_get_num_si(v
);
105 d
= isl_aff_get_denominator_val(aff
);
106 aff
= isl_aff_scale_val(aff
, isl_val_copy(d
));
108 print_aff_expr(os
, aff
);
110 os
<< isl_val_get_num_si(d
);
116 /* Print "aff" onto os.
118 static void print_aff_expr(std::ostringstream
&os
, __isl_keep isl_aff
*aff
)
122 enum isl_dim_type types
[] = { isl_dim_in
, isl_dim_param
, isl_dim_div
};
123 int n_type
= sizeof(types
)/sizeof(*types
);
125 d
= isl_aff_get_denominator_val(aff
);
126 if (!isl_val_is_one(d
))
128 for (int t
= 0; t
< n_type
; ++t
) {
129 for (int i
= 0; i
< isl_aff_dim(aff
, types
[t
]); ++i
) {
130 v
= isl_aff_get_coefficient_val(aff
, types
[t
], i
);
131 if (isl_val_is_zero(v
)) {
135 if (!first
&& isl_val_is_pos(v
))
137 if (types
[t
] == isl_dim_div
) {
139 div
= isl_aff_get_div(aff
, i
);
140 print_term(os
, v
, div
);
143 name
= isl_aff_get_dim_name(aff
, types
[t
], i
);
144 print_term(os
, v
, name
);
151 v
= isl_aff_get_constant_val(aff
);
152 if (first
|| !isl_val_is_zero(v
)) {
153 if (!first
&& isl_val_is_pos(v
))
155 os
<< isl_val_get_num_si(v
);
159 if (!isl_val_is_one(d
)) {
161 os
<< isl_val_get_num_si(d
);
166 struct print_pw_aff_data
{
167 std::ostringstream
&os
;
168 std::vector
<isl_id
*> &iterators
;
171 print_pw_aff_data(std::ostringstream
&os
,
172 std::vector
<isl_id
*> &iterators
) :
173 os(os
), iterators(iterators
), first(true) {}
177 static isl_stat
print_pw_aff_piece(__isl_take isl_set
*set
,
178 __isl_take isl_aff
*aff
, void *user
);
181 /* Print a single piece of an isl_pw_aff.
182 * We currently assume that there is only a single piece
183 * and abort if there happens to be more than one.
185 static isl_stat
print_pw_aff_piece(__isl_take isl_set
*set
,
186 __isl_take isl_aff
*aff
, void *user
)
188 struct print_pw_aff_data
*data
= (struct print_pw_aff_data
*) user
;
192 print_aff_expr(data
->os
, aff
);
201 static void print_pw_aff_expr(std::ostringstream
&os
, __isl_keep isl_pw_aff
*pa
,
202 std::vector
<isl_id
*> &iterators
)
204 struct print_pw_aff_data
data(os
, iterators
);
205 isl_pw_aff_foreach_piece(pa
, &print_pw_aff_piece
, &data
);
208 static void writeExpr(xmlTextWriterPtr writer
, const char *type
,
209 const char *expr_name
, adg_expr
*expr
, adg
*graph
)
212 std::ostringstream strm
;
214 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
218 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
219 BAD_CAST
isl_id_get_name(expr
->name
));
223 print_pw_aff_expr(strm
, expr
->expr
, graph
->iterators
);
224 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST expr_name
,
225 BAD_CAST strm
.str().c_str());
228 rc
= xmlTextWriterEndElement(writer
);
232 /* Write out the rows of "mat", each prefixed by the integer "ineq".
233 * The rows are separated by ";". If first is false, then we
234 * also include a ";" before the first row.
236 static void writeMatrix(std::ostream
&os
, __isl_keep isl_mat
*mat
,
237 int ineq
, bool first
)
242 for (i
= 0; i
< isl_mat_rows(mat
); ++i
) {
247 for (j
= 0; j
< isl_mat_cols(mat
); ++j
) {
248 v
= isl_mat_get_element_val(mat
, i
, j
);
249 os
<< ", " << isl_val_get_num_si(v
);
255 /* Find the number of dynamic control variables in "space".
257 * The dynamic control variables, if any, are located in the range
258 * of a wrapped map, with the (possibly lifted) iteration domain
259 * in the domain. After adding the dynamic control variables, the
260 * result may have been lifted as well, so we need dig through
261 * any possible lifting of the form
263 * D -> [D -> local[..]]
265 * until we arrive at the iteration domain, in which case there
266 * are no dynamic control variables, or until we find the control
269 static int n_dynamic_in_space(__isl_take isl_space
*space
)
273 if (!isl_space_is_wrapping(space
)) {
274 isl_space_free(space
);
277 space
= isl_space_unwrap(space
);
278 if (isl_space_has_tuple_id(space
, isl_dim_out
))
279 return n_dynamic_in_space(isl_space_domain(space
));
280 n
= isl_space_dim(space
, isl_dim_out
);
281 isl_space_free(space
);
285 /* Find the position of the first dynamic control variable in "space".
287 * See n_dynamic_in_space.
289 static int pos_dynamic_in_space(__isl_take isl_space
*space
)
293 if (!isl_space_is_wrapping(space
)) {
294 isl_space_free(space
);
297 space
= isl_space_unwrap(space
);
298 if (isl_space_has_tuple_id(space
, isl_dim_out
))
299 return pos_dynamic_in_space(isl_space_domain(space
));
300 pos
= isl_space_dim(space
, isl_dim_in
);
301 isl_space_free(space
);
305 /* Write a matrix corresponding to the constraints of "bset".
306 * The order of the dimensions in the matrix is a follows.
308 * iterators static_controls dynamic_controls parameters constant
310 * Inside "bset", however, in the set dimensions, the dynamic
311 * controls may appear in the middle of the static controls.
313 * We therefore need to move the dynamic controls.
314 * "pos_dynamic" indicates the position of the first dynamic control.
315 * "n_dynamic" indicates the number of dynamic controls.
317 static void writeMatrix(xmlTextWriterPtr writer
, const char *name
,
318 __isl_keep isl_basic_set
*bset
, int n_dynamic
)
322 std::ostringstream strm
;
324 int n_set
= isl_basic_set_dim(bset
, isl_dim_set
);
325 int pos_dynamic
= pos_dynamic_in_space(isl_basic_set_get_space(bset
));
327 rc
= xmlTextWriterStartElement(writer
, BAD_CAST name
);
331 mat
= isl_basic_set_equalities_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
, 0, first
);
335 first
= isl_mat_rows(mat
) == 0;
338 mat
= isl_basic_set_inequalities_matrix(bset
,
339 isl_dim_set
, isl_dim_div
, isl_dim_param
, isl_dim_cst
);
340 mat
= isl_mat_move_cols(mat
, n_set
- n_dynamic
, pos_dynamic
, n_dynamic
);
341 writeMatrix(strm
, mat
, 1, first
);
345 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"matrix",
346 BAD_CAST strm
.str().c_str());
349 rc
= xmlTextWriterEndElement(writer
);
353 /* Print the coefficients of the affine expression "aff",
354 * separated by commas.
356 * Note that the set dimensions of "aff" are given in the order
358 * iterators static_and_dynamic_controls
360 * while the coefficients should be printed in the order
362 * iterators static_controls dynamic_controls parameters constant
364 static void print_aff_coefficients(std::ostringstream
&os
,
365 __isl_keep isl_aff
*aff
)
374 space
= isl_aff_get_domain_space(aff
);
375 pos_dynamic
= pos_dynamic_in_space(isl_space_copy(space
));
376 n_dynamic
= n_dynamic_in_space(space
);
377 n_index
= isl_aff_dim(aff
, isl_dim_in
) - n_dynamic
;
379 for (int i
= 0; i
< pos_dynamic
; ++i
) {
382 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, i
);
383 os
<< isl_val_get_num_si(v
);
388 for (int i
= pos_dynamic
; i
< n_index
; ++i
) {
391 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, n_dynamic
+ i
);
392 os
<< isl_val_get_num_si(v
);
397 for (int i
= 0; i
< n_dynamic
; ++i
) {
400 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
,
402 os
<< isl_val_get_num_si(v
);
407 for (int i
= 0; i
< isl_aff_dim(aff
, isl_dim_param
); ++i
) {
410 v
= isl_aff_get_coefficient_val(aff
, isl_dim_param
, i
);
411 os
<< isl_val_get_num_si(v
);
418 v
= isl_aff_get_constant_val(aff
);
419 os
<< isl_val_get_num_si(v
);
423 /* Write out "map" in the form of a matrix, with each row
424 * corresponding to an affine expression.
426 static void writeMatrix(xmlTextWriterPtr writer
, const char *name
,
427 __isl_keep isl_multi_aff
*map
)
430 std::ostringstream strm
;
433 rc
= xmlTextWriterStartElement(writer
, BAD_CAST name
);
437 n
= isl_multi_aff_dim(map
, isl_dim_out
);
438 for (int i
= 0; i
< n
; ++i
) {
442 aff
= isl_multi_aff_get_aff(map
, i
);
443 print_aff_coefficients(strm
, aff
);
448 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"matrix",
449 BAD_CAST strm
.str().c_str());
452 rc
= xmlTextWriterEndElement(writer
);
456 struct write_bound_data
{
457 xmlTextWriterPtr writer
;
462 static isl_stat
write_bound(__isl_take isl_basic_set
*bset
, void *user
)
466 std::ostringstream strm
;
467 write_bound_data
*data
= (write_bound_data
*) user
;
468 xmlTextWriterPtr writer
= data
->writer
;
470 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"linearbound");
473 for (int i
= 0; i
< data
->graph
->iterators
.size(); ++i
) {
476 strm
<< isl_id_get_name(data
->graph
->iterators
[i
]);
479 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"index",
480 BAD_CAST strm
.str().c_str());
484 for (int i
= 0; i
< data
->domain
->controls
.size(); ++i
) {
487 strm
<< isl_id_get_name(data
->domain
->controls
[i
]->name
);
489 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"staticControl",
490 BAD_CAST strm
.str().c_str());
494 for (int i
= 0; i
< data
->domain
->filters
.size(); ++i
) {
497 strm
<< data
->domain
->filters
[i
]->get_expr();
499 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"dynamicControl",
500 BAD_CAST strm
.str().c_str());
504 nparam
= isl_basic_set_dim(bset
, isl_dim_param
);
505 for (int i
= 0; i
< nparam
; ++i
) {
508 strm
<< isl_basic_set_get_dim_name(bset
, isl_dim_param
, i
);
510 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"parameter",
511 BAD_CAST strm
.str().c_str());
514 bset
= isl_basic_set_remove_redundancies(bset
);
515 writeMatrix(writer
, "constraint", bset
, data
->domain
->filters
.size());
517 isl_basic_set_free(bset
);
519 if (data
->graph
->context
&&
520 !isl_set_plain_is_universe(data
->graph
->context
)) {
521 assert(isl_set_n_basic_set(data
->graph
->context
) == 1);
522 bset
= isl_set_simple_hull(isl_set_copy(data
->graph
->context
));
523 bset
= isl_basic_set_remove_redundancies(bset
);
524 writeMatrix(writer
, "context", bset
, 0);
525 isl_basic_set_free(bset
);
528 for (int i
= 0; i
< data
->domain
->controls
.size(); ++i
)
529 writeExpr(writer
, "control", "exp", data
->domain
->controls
[i
],
532 rc
= xmlTextWriterEndElement(writer
);
538 static void writeDomain(xmlTextWriterPtr writer
, adg_domain
*domain
, adg
*graph
)
541 write_bound_data data
= { writer
, domain
, graph
};
543 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"domain");
546 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
550 rc
= isl_set_foreach_basic_set(domain
->bounds
, &write_bound
, &data
);
553 rc
= xmlTextWriterEndElement(writer
);
557 static void writePort(xmlTextWriterPtr writer
, adg_port
*port
, bool output
,
563 type
= output
? "outport" : "inport";
565 rc
= xmlTextWriterStartElement(writer
, BAD_CAST type
);
569 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
570 BAD_CAST
isl_id_get_name(port
->name
));
571 assert(port
->node_name
);
572 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"node",
573 BAD_CAST
isl_id_get_name(port
->node_name
));
574 assert(port
->edge_name
);
575 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"edge",
576 BAD_CAST
isl_id_get_name(port
->edge_name
));
578 for (int i
= 0; i
< port
->vars
.size(); ++i
)
579 writeVar(writer
, "bindvariable", port
->vars
[i
]);
581 writeDomain(writer
, port
->domain
, graph
);
583 rc
= xmlTextWriterEndElement(writer
);
587 static void writeGate(xmlTextWriterPtr writer
, adg_gate
*gate
, adg
*graph
)
591 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"invar");
595 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
596 BAD_CAST
isl_id_get_name(gate
->name
));
598 assert(gate
->in
&& gate
->in
->access
);
599 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"realName",
600 BAD_CAST gate
->in
->get_expr());
603 writeVar(writer
, "bindvariable", gate
->out
);
605 writeDomain(writer
, gate
->domain
, graph
);
607 rc
= xmlTextWriterEndElement(writer
);
611 static void writeFunction(xmlTextWriterPtr writer
, adg_function
*fn
, adg
*graph
)
615 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"function");
619 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
620 BAD_CAST
isl_id_get_name(fn
->name
));
622 for (int i
= 0; i
< fn
->in
.size(); ++i
)
623 writeArg(writer
, "inargument", fn
->in
[i
]);
624 for (int i
= 0; i
< fn
->out
.size(); ++i
)
625 writeArg(writer
, "outargument", fn
->out
[i
]);
626 for (int i
= 0; i
< fn
->ctrl
.size(); ++i
)
627 writeExpr(writer
, "ctrlvar", "iterator", fn
->ctrl
[i
], graph
);
629 writeDomain(writer
, fn
->domain
, graph
);
631 rc
= xmlTextWriterEndElement(writer
);
635 /* The gates should be printed after the input ports because
636 * they may use data read through an input port.
638 static void writeNode(xmlTextWriterPtr writer
, adg_node
*node
, adg
*graph
)
642 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"node");
646 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
647 BAD_CAST
isl_id_get_name(node
->name
));
649 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"levelUpNode",
653 for (int i
= 0; i
< node
->input_ports
.size(); ++i
)
654 writePort(writer
, node
->input_ports
[i
], false, graph
);
656 for (int i
= 0; i
< node
->gates
.size(); ++i
)
657 writeGate(writer
, node
->gates
[i
], graph
);
659 for (int i
= 0; i
< node
->output_ports
.size(); ++i
)
660 writePort(writer
, node
->output_ports
[i
], true, graph
);
662 for (int i
= 0; i
< node
->expressions
.size(); ++i
)
663 writeExpr(writer
, "expression", "value",
664 node
->expressions
[i
], graph
);
666 writeFunction(writer
, node
->function
, graph
);
668 writeDomain(writer
, node
->domain
, graph
);
670 rc
= xmlTextWriterEndElement(writer
);
674 static void writeEdge(xmlTextWriterPtr writer
, adg_edge
*edge
)
677 std::ostringstream strm
;
680 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"edge");
684 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
685 BAD_CAST
isl_id_get_name(edge
->name
));
688 assert(edge
->from_port_name
);
689 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"fromPort",
690 BAD_CAST
isl_id_get_name(edge
->from_port_name
));
693 assert(edge
->from_node_name
);
694 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"fromNode",
695 BAD_CAST
isl_id_get_name(edge
->from_node_name
));
698 assert(edge
->to_port_name
);
699 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"toPort",
700 BAD_CAST
isl_id_get_name(edge
->to_port_name
));
703 assert(edge
->to_node_name
);
704 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"toNode",
705 BAD_CAST
isl_id_get_name(edge
->to_node_name
));
708 s
= isl_val_to_str(edge
->value_size
);
709 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"size", BAD_CAST s
);
713 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"linearization");
716 switch (edge
->type
) {
718 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
721 case adg_edge_sticky_fifo
:
722 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
723 BAD_CAST
"sticky_fifo");
725 case adg_edge_shift_register
:
726 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
727 BAD_CAST
"shift_register");
729 case adg_edge_broadcast
:
730 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
731 BAD_CAST
"BroadcastInOrder");
733 case adg_edge_generic
:
734 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"type",
735 BAD_CAST
"GenericOutOfOrder");
743 rc
= xmlTextWriterEndElement(writer
);
746 writeMatrix(writer
, "mapping", edge
->map
);
748 rc
= xmlTextWriterEndElement(writer
);
752 static void writeParam(xmlTextWriterPtr writer
, adg_param
*param
, adg
*graph
)
755 std::ostringstream strm
;
757 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"parameter");
761 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
762 BAD_CAST
isl_id_get_name(param
->name
));
767 print_aff_expr(strm
, param
->lb
);
768 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"lb",
769 BAD_CAST strm
.str().c_str());
775 print_aff_expr(strm
, param
->ub
);
776 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"ub",
777 BAD_CAST strm
.str().c_str());
783 print_aff_expr(strm
, param
->val
);
784 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"value",
785 BAD_CAST strm
.str().c_str());
789 rc
= xmlTextWriterEndElement(writer
);
793 static void writeADG(xmlTextWriterPtr writer
, adg
*graph
)
797 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"adg");
801 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"name",
802 BAD_CAST
isl_id_get_name(graph
->name
));
804 rc
= xmlTextWriterWriteAttribute(writer
, BAD_CAST
"levelUpNode",
808 for (int i
= 0; i
< graph
->params
.size(); ++i
)
809 writeParam(writer
, graph
->params
[i
], graph
);
811 for (int i
= 0; i
< graph
->nodes
.size(); ++i
)
812 writeNode(writer
, graph
->nodes
[i
], graph
);
814 for (int i
= 0; i
< graph
->edges
.size(); ++i
)
815 writeEdge(writer
, graph
->edges
[i
]);
817 rc
= xmlTextWriterEndElement(writer
);
821 /* Project out all the lifted variables that used to be
822 * existentially quantified. In other words, undo the lifting.
823 * Also project out the dynamic control variables.
825 static __isl_give isl_set
*unwrap(__isl_take isl_set
*dom
)
827 if (!isl_set_is_wrapping(dom
))
829 return unwrap(isl_map_domain(isl_set_unwrap(dom
)));
832 /* Project out all the lifted variables that used to be
833 * existentially quantified. In other words, undo the lifting.
834 * Turn the dynamic control variables into parameters.
835 * The names of those parameters are taken from "filters".
837 static __isl_give isl_set
*unwrap_filtered(__isl_take isl_set
*dom
,
838 std::vector
<adg_var
*> &filters
)
844 if (!isl_set_is_wrapping(dom
))
847 map
= isl_set_unwrap(dom
);
848 if (isl_map_has_tuple_name(map
, isl_dim_out
))
849 return unwrap_filtered(isl_map_domain(map
), filters
);
851 nparam
= isl_map_dim(map
, isl_dim_param
);
853 map
= isl_map_add_dims(map
, isl_dim_param
, n
);
854 for (i
= 0; i
< n
; ++i
) {
857 id
= isl_pw_multi_aff_get_tuple_id(filters
[i
]->access
,
859 map
= isl_map_set_dim_id(map
, isl_dim_param
, nparam
+ i
, id
);
860 map
= isl_map_equate(map
, isl_dim_param
, nparam
+ i
,
864 return unwrap(isl_map_domain(map
));
867 /* Construct a schedule by adding an extra pair of dimensions to
868 * domain->schedule, fixed to "offset1" and "offset2"
869 * and setting the input name to "name".
871 * If "filtered" is set, then the dynamic control variables are preserved
872 * (as parameters) in the resulting schedule.
874 static __isl_give isl_map
*domain_schedule(adg_node
*node
, adg_domain
*domain
,
875 int offset1
, int offset2
, __isl_take isl_id
*name
, bool filtered
)
881 n_out
= isl_map_dim(node
->schedule
, isl_dim_out
);
883 dom
= isl_set_copy(domain
->bounds
);
885 dom
= unwrap_filtered(dom
, domain
->filters
);
889 sched
= isl_map_copy(node
->schedule
);
890 sched
= isl_map_intersect_domain(sched
, dom
);
891 sched
= isl_map_add_dims(sched
, isl_dim_out
, 2);
892 sched
= isl_map_fix_si(sched
, isl_dim_out
, n_out
, offset1
);
893 sched
= isl_map_fix_si(sched
, isl_dim_out
, n_out
+ 1, offset2
);
894 sched
= isl_map_set_tuple_id(sched
, isl_dim_in
, name
);
899 static __isl_give isl_map
*port_schedule(adg_node
*node
, adg_port
*port
,
900 int offset
, bool filtered
)
902 return domain_schedule(node
, port
->domain
, offset
, port
->arg_pos
,
903 isl_id_copy(port
->name
), filtered
);
906 static __isl_give isl_map
*gate_schedule(adg_node
*node
, adg_gate
*gate
,
907 int offset
, bool filtered
)
909 return domain_schedule(node
, gate
->domain
, offset
, 0,
910 isl_id_copy(gate
->name
), filtered
);
913 /* Construct a schedule for all elements in the node.
914 * We add an extra dimension to node->schedule to ensure that
915 * the different elements are executed in the right order:
916 * input ports, gates, function, output ports.
917 * The input ports themselves are ordered according to the access nr.
919 * If "filtered" is set, then the dynamic control variables are preserved
920 * (as parameters) in the resulting schedule.
922 static __isl_give isl_union_map
*collect_node_schedule(adg_node
*node
, int n
,
926 isl_union_map
*sched
;
929 n_out
= isl_map_dim(node
->schedule
, isl_dim_out
);
931 sched_f
= domain_schedule(node
, node
->function
->domain
, 4 * n
+ 2, 0,
932 isl_id_copy(node
->name
), filtered
);
933 sched
= isl_union_map_from_map(sched_f
);
935 for (int i
= 0; i
< node
->input_ports
.size(); ++i
) {
937 sched_p
= port_schedule(node
, node
->input_ports
[i
], 4 * n
+ 0,
939 sched
= isl_union_map_add_map(sched
, sched_p
);
942 for (int i
= 0; i
< node
->gates
.size(); ++i
) {
944 sched_p
= gate_schedule(node
, node
->gates
[i
], 4 * n
+ 1,
946 sched
= isl_union_map_add_map(sched
, sched_p
);
949 for (int i
= 0; i
< node
->output_ports
.size(); ++i
) {
951 sched_p
= port_schedule(node
, node
->output_ports
[i
], 4 * n
+ 3,
953 sched
= isl_union_map_add_map(sched
, sched_p
);
959 /* Construct a schedule for all nodes in the graph.
961 * If "filtered" is set, then the dynamic control variables are preserved
962 * (as parameters) in the resulting schedule.
964 static isl_union_map
*collect_schedule(adg
*graph
, bool filtered
)
966 isl_space
*space
= isl_set_get_space(graph
->context
);
967 isl_union_map
*sched
= isl_union_map_empty(space
);
969 for (int i
= 0; i
< graph
->nodes
.size(); ++i
) {
970 isl_union_map
*sched_i
;
971 sched_i
= collect_node_schedule(graph
->nodes
[i
], i
, filtered
);
972 sched
= isl_union_map_union(sched
, sched_i
);
978 /* Set the "atomic" option on all the dimensions of a schedule
979 * of dimension "sched_len".
981 static __isl_give isl_ast_build
*set_atomic(
982 __isl_take isl_ast_build
*context
, int sched_len
)
988 ctx
= isl_ast_build_get_ctx(context
);
990 space
= isl_space_alloc(ctx
, 0, sched_len
, 1);
991 space
= isl_space_set_tuple_name(space
, isl_dim_out
, "atomic");
992 opt
= isl_union_map_from_map(isl_map_universe(space
));
994 context
= isl_ast_build_set_options(context
, opt
);
999 /* This function is called for each leaf in the AST constructed
1000 * from the schedule without dynamic control variables.
1001 * Continue constructing an inner AST for the schedule with
1002 * the dynamic control variables as parameters.
1004 static __isl_give isl_ast_node
*create_leaf(__isl_take isl_ast_build
*build
,
1008 isl_union_map
*sched
;
1009 isl_union_map
*sched2
= (isl_union_map
*) user
;
1011 sched
= isl_ast_build_get_schedule(build
);
1012 sched
= isl_union_map_range_product(sched
, isl_union_map_copy(sched2
));
1013 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
1014 isl_ast_build_free(build
);
1019 /* Does the adg contain any dynamic control variables?
1021 static bool any_filters(adg
*graph
)
1023 for (int i
= 0; i
< graph
->nodes
.size(); ++i
) {
1024 adg_node
*node
= graph
->nodes
[i
];
1026 for (int j
= 0; j
< node
->input_ports
.size(); ++j
)
1027 if (node
->input_ports
[j
]->domain
->filters
.size() > 0)
1029 for (int j
= 0; j
< node
->gates
.size(); ++j
)
1030 if (node
->gates
[j
]->domain
->filters
.size() > 0)
1032 for (int j
= 0; j
< node
->output_ports
.size(); ++j
)
1033 if (node
->output_ports
[j
]->domain
->filters
.size() > 0)
1040 /* Construct a schedule, convert it to an AST and then
1041 * write out the AST using writeAST.
1043 * To handle dynamic control variables, we construct two schedules,
1044 * one (sched) with the dynamic control variables projected out and
1045 * one (sched2) with the dynamic control variables as parameters.
1047 * We construct an AST for the first schedule and within each leaf
1048 * of the AST, we construct an AST for the second schedule.
1049 * This inner AST will essentially reflect the conditions on
1050 * the dynamic control variables.
1052 * Note that we only need to create this second schedule if there actually
1053 * are any dynamic control variables.
1055 static void writeAST(xmlTextWriterPtr writer
, adg
*graph
)
1058 isl_ctx
*ctx
= isl_set_get_ctx(graph
->context
);
1059 isl_union_map
*sched
, *sched2
= NULL
;
1060 isl_ast_build
*build
;
1062 isl_id_list
*iterators
;
1065 isl_options_set_ast_build_atomic_upper_bound(ctx
, 1);
1066 isl_options_set_ast_build_prefer_pdiv(ctx
, 1);
1067 isl_options_set_ast_build_allow_else(ctx
, 0);
1068 isl_options_set_ast_build_allow_or(ctx
, 0);
1070 has_filters
= any_filters(graph
);
1072 sched
= collect_schedule(graph
, false);
1074 sched2
= collect_schedule(graph
, true);
1076 iterators
= isl_id_list_alloc(ctx
, graph
->all_iterators
.size());
1077 for (int i
= 0; i
< graph
->all_iterators
.size(); ++i
)
1078 iterators
= isl_id_list_add(iterators
,
1079 isl_id_copy(graph
->all_iterators
[i
]));
1080 build
= isl_ast_build_from_context(isl_set_copy(graph
->context
));
1081 build
= isl_ast_build_set_iterators(build
, iterators
);
1083 build
= isl_ast_build_set_create_leaf(build
,
1084 &create_leaf
, sched2
);
1085 build
= set_atomic(build
, graph
->all_iterators
.size() + 2);
1086 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
1087 isl_ast_build_free(build
);
1089 writeAST(writer
, tree
);
1091 isl_union_map_free(sched2
);
1092 isl_ast_node_free(tree
);
1095 /* Write out an XML representation of "graph" to "out".
1096 * The adg part is obtained by scanning the data structure.
1097 * The ast part is obtained by generating code based on the domain schedules.
1099 void adg_print_xml(adg
*graph
, FILE *out
)
1102 xmlTextWriterPtr writer
;
1107 writer
= xmlNewTextWriterDoc(&doc
, 0);
1110 rc
= xmlTextWriterStartDocument(writer
, NULL
, NULL
, NULL
);
1113 rc
= xmlTextWriterStartDTD(writer
, BAD_CAST
"sadg",
1114 BAD_CAST
"-//LIACS//DTD ESPAM 1//EN",
1115 BAD_CAST
"http://www.liacs.nl/~cserc/dtd/espam_1.dtd");
1117 rc
= xmlTextWriterEndDTD(writer
);
1120 rc
= xmlTextWriterStartElement(writer
, BAD_CAST
"sadg");
1123 writeADG(writer
, graph
);
1124 writeAST(writer
, graph
);
1126 rc
= xmlTextWriterEndElement(writer
);
1129 rc
= xmlTextWriterEndDocument(writer
);
1132 xmlFreeTextWriter(writer
);
1134 rc
= xmlDocFormatDump(out
, doc
, 1);