+ /* check if node can be executed on this unit type */
+ cur_tp_idx = is_valid_unit_type_for_node(cur_tp, cur_node);
+ if (cur_tp_idx < 0)
+ continue;
+
+ /* check all time_steps */
+ for (t = cur_na->asap - 1; t <= cur_na->alap - 1; ++t) {
+ int cst, y_idx;
+ ir_node *irn;
+ int *tmp_idx_1 = NEW_ARR_F(int, 0);
+ int *tmp_idx_m1 = NEW_ARR_F(int, 0);
+
+ snprintf(buf, sizeof(buf), "pressure_cst_n%u_%u_%s", cur_idx, t, cur_tp->name);
+ cst = lpp_add_cst_uniq(lpp, buf, lpp_less, (double)(cur_tp->n_units - 1));
+ DBG((env->dbg, LEVEL_2, "added constraint %s\n", buf));
+ num_cst++;
+
+ /*
+ - accumulate all nodes scheduled on unit type k till t
+ - subtract all nodes died on unit type k till t
+ */
+ foreach_linked_irns(ba->head_ilp_nodes, irn) {
+ be_ilpsched_irn_t *node = get_ilpsched_irn(env, irn);
+ ilpsched_node_attr_t *na = get_ilpsched_node_attr(node);
+ unsigned tn, tmax;
+ int tp_idx;
+
+ tmax = MIN(t, na->alap - 1);
+ tp_idx = is_valid_unit_type_for_node(cur_tp, node);
+
+ /* current unit type is not suitable for current node */
+ if (tp_idx < 0)
+ continue;
+
+ for (tn = na->asap - 1; tn <= tmax; ++tn) {
+ int idx;
+
+ /* node scheduled */
+ idx = ILPVAR_IDX(na, tp_idx, tn);
+ ARR_APP1(int, tmp_idx_1, na->ilp_vars.x[idx]);
+
+ /* node dead */
+ idx = ILPVAR_IDX_DEAD(ba, na, tp_idx, tn);
+ ARR_APP1(int, tmp_idx_m1, na->ilp_vars.d[idx]);
+ }
+ }
+
+ if (ARR_LEN(tmp_idx_1) > 0)
+ lpp_set_factor_fast_bulk(lpp, cst, tmp_idx_1, ARR_LEN(tmp_idx_1), 1.0);
+
+ if (ARR_LEN(tmp_idx_m1) > 0)
+ lpp_set_factor_fast_bulk(lpp, cst, tmp_idx_m1, ARR_LEN(tmp_idx_m1), -1.0);
+
+ /* BEWARE: t is unsigned, so (double)(-t) won't work */
+ y_idx = ILPVAR_IDX(cur_na, cur_tp_idx, t);
+ lpp_set_factor_fast(lpp, cst, cur_na->ilp_vars.y[y_idx], 0.0 - (double)(t));
+
+ DEL_ARR_F(tmp_idx_1);
+ DEL_ARR_F(tmp_idx_m1);
+ }
+ }
+ }
+ ilp_timer_pop();
+ DBG((env->dbg, LEVEL_1, "\t%u pressure constraints (%g sec)\n",
+ num_cst, ilp_timer_elapsed_usec(t_cst) / 1000000.0));
+}
+
+/**
+ * Create ILP pressure constraints, based on alive nodes:
+ * - add additional costs to objective function if a node is scheduled
+ * on a unit although all units of this type are currently occupied
+ */
+static void create_pressure_alive_constraint(be_ilpsched_env_t *env, lpp_t *lpp, be_ilpsched_irn_t *block_node) {
+ char buf[1024];
+ ir_node *cur_irn;
+ unsigned num_cst = 0;
+ ilpsched_block_attr_t *ba = get_ilpsched_block_attr(block_node);
+#ifdef WITH_LIBCORE
+ lc_timer_t *t_cst = lc_timer_register("beilpsched_cst_pressure", "create pressure constraints");
+#endif /* WITH_LIBCORE */
+
+ ilp_timer_push(t_cst);
+ /* y_{nt}^k is set for each node and timestep and unit type */
+ foreach_linked_irns(ba->head_ilp_nodes, cur_irn) {
+ unsigned cur_idx = get_irn_idx(cur_irn);
+ be_ilpsched_irn_t *cur_node = get_ilpsched_irn(env, cur_irn);
+ ilpsched_node_attr_t *cur_na = get_ilpsched_node_attr(cur_node);
+ int glob_type_idx;
+
+ /* we ignore nodes assigned to DUMMY unit here */
+ if (cur_na->is_dummy_node)
+ continue;
+
+ /* for all types */
+ for (glob_type_idx = env->cpu->n_unit_types - 1; glob_type_idx >= 0; --glob_type_idx) {
+ be_execution_unit_type_t *cur_tp = &env->cpu->unit_types[glob_type_idx];
+ int cur_tp_idx;
+ unsigned t;
+
+ /* BEWARE: the DUMMY unit types is not in CPU, so it's skipped automatically */
+
+ /* check if node can be executed on this unit type */
+ cur_tp_idx = is_valid_unit_type_for_node(cur_tp, cur_node);
+ if (cur_tp_idx < 0)
+ continue;
+
+ /* check all time_steps at which the current node can be scheduled */
+ for (t = cur_na->asap - 1; t <= cur_na->alap - 1; ++t) {
+ int cst, y_idx;
+ ir_node *irn;
+ int *tmp_var_idx = NEW_ARR_F(int, 0);
+
+ snprintf(buf, sizeof(buf), "pressure_cst_n%u_%u_%s", cur_idx, t, cur_tp->name);
+ cst = lpp_add_cst_uniq(lpp, buf, lpp_less, (double)(cur_tp->n_units - 1));
+ DBG((env->dbg, LEVEL_2, "added constraint %s\n", buf));
+ num_cst++;
+
+ /* - accumulate all nodes alive at point t on unit type k */
+ foreach_linked_irns(ba->head_ilp_nodes, irn) {
+ be_ilpsched_irn_t *node = get_ilpsched_irn(env, irn);
+ ilpsched_node_attr_t *na = get_ilpsched_node_attr(node);
+ int a_idx, tp_idx;
+
+ /* check if node can be alive here */
+ if (t < na->asap - 1)
+ continue;
+
+ tp_idx = is_valid_unit_type_for_node(cur_tp, node);
+
+ /* current type is not suitable */
+ if (tp_idx < 0)
+ continue;
+
+ a_idx = ILPVAR_IDX_DEAD(ba, na, tp_idx, t);
+ ARR_APP1(int, tmp_var_idx, na->ilp_vars.a[a_idx]);
+ }
+
+ if (ARR_LEN(tmp_var_idx) > 0)
+ lpp_set_factor_fast_bulk(lpp, cst, tmp_var_idx, ARR_LEN(tmp_var_idx), 1.0);
+ DEL_ARR_F(tmp_var_idx);
+
+ /* - num_nodes * y_{nt}^k */
+ y_idx = ILPVAR_IDX(cur_na, cur_tp_idx, t);
+ lpp_set_factor_fast(lpp, cst, cur_na->ilp_vars.y[y_idx], 0.0 - (double)(ba->n_interesting_nodes));
+ }
+ }
+ }
+ ilp_timer_pop();
+ DBG((env->dbg, LEVEL_1, "\t%u pressure constraints (%g sec)\n",
+ num_cst, ilp_timer_elapsed_usec(t_cst) / 1000000.0));
+}
+
+#if 0
+static void create_proj_keep_constraints(be_ilpsched_env_t *env, lpp_t *lpp, be_ilpsched_irn_t *block_node) {
+ char buf[1024];
+ ir_node *irn;
+ unsigned num_cst = 0;
+ ilpsched_block_attr_t *ba = get_ilpsched_block_attr(block_node);
+#ifdef WITH_LIBCORE
+ lc_timer_t *t_cst = lc_timer_register("beilpsched_cst_projkeep", "create proj and keep constraints");
+#endif /* WITH_LIBCORE */
+
+ ilp_timer_push(t_cst);
+ /* check all nodes */
+ foreach_linked_irns(ba->head_ilp_nodes, irn) {
+ be_ilpsched_irn_t *node;
+ ilpsched_node_attr_t *na;
+ unsigned t;
+ ir_node **pk;
+
+ /* only mode_T nodes can have Projs and Keeps assigned */
+ if (get_irn_mode(irn) != mode_T)
+ continue;
+
+ node = get_ilpsched_irn(env, irn);
+ na = get_ilpsched_node_attr(node);
+
+ /* check if has some Projs and Keeps assigned */
+ if (! na->projkeeps)
+ continue;
+
+ /* we can run only once over the queue, so preserve the nodes */
+ pk = NEW_ARR_F(ir_node *, 0);
+ while (! waitq_empty(na->projkeeps))
+ ARR_APP1(ir_node *, pk, waitq_get(na->projkeeps));
+ del_waitq(na->projkeeps);
+ na->projkeeps = NULL;
+
+ /* for all time steps at which this node can be scheduled */
+ for (t = na->asap - 1; t <= na->alap - 1; ++t) {
+ int cst, tp_idx, i;
+ int *tmp_var_idx_n = NEW_ARR_F(int, 0);
+
+ /* add the constraint, assure, that a node is always scheduled along with it's Projs and Keeps */
+ snprintf(buf, sizeof(buf), "projkeep_cst_n%u_%u", get_irn_idx(irn), t);
+ cst = lpp_add_cst_uniq(lpp, buf, lpp_equal, 0.0);