25 #include <gurobi_c++.h>
32 std::string arch_name,
33 std::string supported_ops_file_name)
38 std::string network_latency_filename = supported_ops_file_name;
39 if (supported_ops_file_name.empty()) {
40 std::string cgrame_rootdir =
"CGRA_ME_ROOTDIR";
41 std::string dir = std::getenv(cgrame_rootdir.c_str());
42 dir = dir +
"/src/sched/" + arch_name +
"_supported_ops.dot";
43 network_latency_filename = dir;
49 for (
const auto& mrrg_node : classes.function_nodes) {
57 std::cout <<
"[INFO] Getting network latency from DOT file: " << network_latency_filename<< std::endl;
58 auto network_latency_ifstream = std::ifstream(network_latency_filename);
59 parsed_network_latency_dot =
parseDot(network_latency_ifstream, network_latency_filename);
61 for (
const auto& v : parsed_network_latency_dot.
allNodes()) {
63 const auto& v_attrs = parsed_network_latency_dot.
attributes(v);
66 for (
const auto& out_edge : parsed_network_latency_dot.
outEdges(v)) {
68 const auto& e_attrs = parsed_network_latency_dot.
attributes(out_edge);
69 std::string out_name = parsed_network_latency_dot.
name(v);
70 std::string in_name = parsed_network_latency_dot.
name(parsed_network_latency_dot.
target(out_edge));
73 OpCodeEdge op_code_edge = {out_op_code, in_op_code};
89 if (!val)
return false;
90 for (
auto& sink_op : val->
output) {
107 for (
auto& edge : op->
input) {
120 if (source_op == sink_op)
return -1;
121 if (ignore_backedge) {
138 throw cgrame_error(
"ERR: Alias edge: " + val->
getName() +
" does not connect a load to a store");
148 +
" does not connect store to another store/load");
151 throw cgrame_error(
"ERR: Alias edge: " + val->
getName() +
" does not connect to a store or a load");
153 return -latency + (II * val->
dist);
155 assert(0 &&
"ERROR: edge does not have a kind");
165 const int diff_constr_var_count = 2;
167 int ind[diff_constr_var_count];
168 double value[diff_constr_var_count];
174 double fd = -(
static_cast<double>(op_pair.second));
177 int err = GRBaddconstr(model, diff_constr_var_count, ind, value, GRB_LESS_EQUAL, fd, val_name.c_str());
181 for (
const auto& val : *edge_v) {
183 for (
const auto& sink_op : val->output) {
184 int dist =
calcEdgeDist(val, sink_op, II, ignore_backedge);
185 if (dist == -1)
continue;
197 double fd = -(
static_cast<double>(dist));
198 std::string val_name;
208 int err = GRBaddconstr(model, diff_constr_var_count, ind, value, GRB_LESS_EQUAL, fd, val_name.c_str());
212 val_name = val_name +
"_1";
214 GRBaddconstr(model, diff_constr_var_count, ind, value, GRB_GREATER_EQUAL, fd, val_name.c_str());
218 val_name = val_name +
"_1";
220 GRBaddconstr(model, diff_constr_var_count, ind, value, GRB_GREATER_EQUAL, fd, val_name.c_str());
223 if ( err )
return err;
226 is_exit_pred[ind[0]] =
false;
242 double fd = -(
static_cast<double>(d));
244 int err = GRBaddconstr(model, diff_constr_var_count, ind, value, GRB_LESS_EQUAL, fd, nm.c_str());
256 int node_count = ops.size();
257 int ext_node_count = node_count;
258 int exit_id = ext_node_count++;
261 GRBmodel* model = NULL;
264 double* sol =
new double[ext_node_count];
265 double* obj =
new double[ext_node_count];
266 double* lower_bound =
new double[ext_node_count];
267 double* upper_bound = NULL;
270 int result_max_step = -1;
272 const char* log_file_nm = (algo ==
SchedType::ASAP) ?
"asap.log" :
"alap.log";
274 const char* lp_file_nm = (algo ==
SchedType::ASAP) ?
"asap.lp" :
"alap.lp";
275 const char* iis_file_nm = (algo ==
SchedType::ASAP) ?
"asap.ilp" :
"alap.ilp";
278 err = GRBemptyenv(&env);
280 err = GRBsetstrparam(env,
"LogFile", log_file_nm);
282 err = GRBsetintparam(env,
"LogToConsole", 0);
284 err = GRBstartenv(env);
288 err = GRBnewmodel(env, &model, model_nm, 0, NULL, NULL, NULL, NULL, NULL);
292 memset(lower_bound, 0, ext_node_count *
sizeof(
double));
293 for (
int i = 0; i < node_count; i++) {
296 lower_bound[exit_id] = 0;
299 upper_bound =
new double[ext_node_count];
300 for (
int i = 0; i < node_count; i++) {
301 upper_bound[i] = max_cycles;
303 upper_bound[exit_id] = max_cycles;
306 for (
int i = 0; i < node_count; i++) {
311 err = GRBaddvars(model, ext_node_count, 0, NULL, NULL, NULL, obj, lower_bound, upper_bound, NULL, NULL);
314 err = GRBsetintattr(model, GRB_INT_ATTR_MODELSENSE, (algo ==
SchedType::ASAP) ? GRB_MINIMIZE : GRB_MAXIMIZE);
320 err = GRBoptimize(model);
323 err = GRBwrite(model, lp_file_nm);
326 err = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &opt_status);
329 if (opt_status == GRB_INFEASIBLE) {
330 for (
int i = 0; i < ops.size(); i++) {
331 std::cout << i <<
" " << ops[i]->getName() << std::endl;
333 GRBcomputeIIS(model);
334 GRBwrite(model, iis_file_nm);
337 assert(opt_status == GRB_OPTIMAL);
339 err = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &obj_val);
342 err = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, ext_node_count, sol);
345 for (
int i = 0; i < node_count; i++) {
353 result_max_step =
static_cast<int>(sol[exit_id]);
358 std::string err_msg(GRBgeterrormsg(env));
370 delete [] lower_bound;
371 delete [] upper_bound;
373 return result_max_step;
384 last_use.emplace(op, exit_id);
390 last_use.emplace(op, exit_id);
394 if (val->
output.size() == 1) {
396 }
else if (val->
output.size() > 1) {
397 int lu_id = ext_node_count++;
398 last_use.emplace(op, lu_id);
409 if (val->
output.size() == 1)
continue;
410 for (
auto& sink_op : val->
output) {
411 int Kdiff_constr_var_count = 2;
412 int ind[Kdiff_constr_var_count];
413 double value[Kdiff_constr_var_count];
415 int lu_id = last_use[op];
423 int err = GRBaddconstr(model, Kdiff_constr_var_count, ind, value, GRB_LESS_EQUAL, fd, nm.c_str());
434 int node_count = ops.size();
435 int ext_node_count = node_count;
436 int exit_id = ext_node_count++;
439 std::map<OpGraphOp*, int> last_use;
444 GRBmodel* model = NULL;
446 double* sol =
new double[ext_node_count];
447 double* obj =
new double[ext_node_count];
448 double* lower_bound =
new double[ext_node_count];
451 int result_max_step = -1;
458 err = GRBemptyenv(&env);
460 err = GRBsetstrparam(env,
"LogFile", log_file_nm);
462 err = GRBsetintparam(env,
"LogToConsole", 0);
464 err = GRBstartenv(env);
468 err = GRBnewmodel(env, &model, model_nm, 0, NULL, NULL, NULL, NULL, NULL);
473 for (
int i = 0; i < node_count; i++) {
479 for (
int i = 0; i < ext_node_count; i++) {
483 if (last_use.find(op) == last_use.end()) {
484 throw cgrame_error(
"ERR: LRO operation: " + op->getName() +
" has no entry to last use table");
487 obj[last_use[op]] = obj[last_use[op]] + 1.0;
488 obj[op_index] = obj[op_index] - 1.0;
495 memset(lower_bound, 0, ext_node_count *
sizeof(
double));
496 for (
int i = 0; i < ext_node_count; i++) {
499 lower_bound[exit_id] = 0;
500 err = GRBaddvars(model, ext_node_count, 0, NULL, NULL, NULL, obj, lower_bound, NULL, NULL, NULL);
503 err = GRBsetintattr(model, GRB_INT_ATTR_MODELSENSE, GRB_MINIMIZE);
514 err = GRBoptimize(model);
517 err = GRBwrite(model, lp_file_nm);
520 err = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &opt_status);
523 if (opt_status == GRB_INFEASIBLE)
525 assert(opt_status == GRB_OPTIMAL);
527 err = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &obj_val);
530 err = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, ext_node_count, sol);
535 using PN = std::pair<int, OpGraphOp*>;
536 using MinPrioQueue = std::priority_queue<PN, std::vector<PN>, std::greater<PN>>;
537 MinPrioQueue p_queue;
540 std::vector<std::vector<bool>> rsrv_station
541 (II, std::vector<bool>(mrrgNodesByCycle.function_nodes[II-1].size(),
false));
543 int scheduled_node_count = 0;
546 while (scheduled_node_count < node_count) {
552 while (!p_queue.empty()) {
553 PN temp = p_queue.top();
556 bool back_search_fail =
true;
558 scheduled_node_count++;
562 for (
int i = 0; i < mrrgNodesByCycle.function_nodes[step%II].size(); i++) {
563 if (rsrv_station[s%II][i])
continue;
564 if (!mrrgNodesByCycle.function_nodes[step%II][i]->canMapOp(temp.second))
continue;
567 double fd =
static_cast<double>(step);
569 int err = GRBaddconstr(model, 1, &ind, &val, GRB_EQUAL, fd, e_nm.c_str());
571 err = GRBwrite(model, lp_file_nm);
573 err = GRBoptimize(model);
575 err = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &opt_status);
577 assert(opt_status == GRB_OPTIMAL);
578 err = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, ext_node_count, sol);
580 rsrv_station[s%II][i] =
true;
581 scheduled_node_count++;
582 back_search_fail =
false;
586 if (back_search_fail) {
589 double fd =
static_cast<double>(step + 1);
591 int err = GRBaddconstr(model, 1, &ind, &val, GRB_GREATER_EQUAL, fd, e_nm.c_str());
593 err = GRBoptimize(model);
595 err = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &opt_status);
597 if (opt_status == GRB_INFEASIBLE) {
600 assert(opt_status == GRB_OPTIMAL);
601 err = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, ext_node_count, sol);
607 if (step > 10 * node_count) {
612 for (
int i = 0; i < node_count; i++) {
619 result_max_step =
static_cast<int>(sol[exit_id]);
625 std::string err_msg(GRBgeterrormsg(env));
640 return result_max_step;