size_t schedule_chain::find_unit(const schedule_unit *unit) const { size_t i = 0; while(i < get_unit_count()) { if(get_unit_at(i) == unit) break; i++; } return i; }
size_t schedule_chain::compute_rp_against_dag(const schedule_dag& dag, bool ignore_external_reg) const { std::map< schedule_dep::reg_t, size_t > nb_use_left; size_t rp = 0; /* if the chain is only a subgraph of the DAG, handle it */ if(get_unit_count() < dag.get_units().size() && ignore_external_reg) { schedule_dag *cpy = dag.dup(); for(size_t u = 0; u < dag.get_units().size(); u++) { bool ok = false; for(size_t i = 0; i < get_unit_count(); i++) ok = ok || get_unit_at(i) == dag.get_units()[u]; if(!ok) cpy->remove_unit(dag.get_units()[u]); } size_t rp = compute_rp_against_dag(*cpy); delete cpy; return rp; } for(size_t i = 0; i < get_unit_count(); i++) { const schedule_unit *unit = get_unit_at(i); /* use & destroy regs */ std::set< schedule_dep::reg_t > set; std::set< schedule_dep::reg_t >::iterator it; set = dag.get_reg_use(unit); for(it = set.begin(); it != set.end(); ++it) { assert(nb_use_left.find(*it) != nb_use_left.end() && "Used variable is not alive !"); assert(nb_use_left[*it] > 0 && "Variable is use more times than expected !"); nb_use_left[*it]--; if(nb_use_left[*it] == 0) nb_use_left.erase(*it); } /* update RP */ rp = std::max(rp, nb_use_left.size() + unit->internal_register_pressure()); /* create regs */ set = dag.get_reg_create(unit); for(it = set.begin(); it != set.end(); ++it) { assert(nb_use_left.find(*it) == nb_use_left.end() && "Created variable is already alive ! Either this is wrong or f****d up with physical registers, " "check with schedule_chain::check_against_dag"); nb_use_left[*it] = 0; for(size_t i = 0; i < dag.get_succs(unit).size(); i++) { const schedule_dep& dep = dag.get_succs(unit)[i]; if(dep.is_data() && dep.reg() == *it) nb_use_left[*it]++; } } /* update RP */ rp = std::max(rp, nb_use_left.size()); } if(ignore_external_reg) { assert(nb_use_left.size() == 0 && "Variables still alive at end of schedule !"); } else { rp = std::max(rp, nb_use_left.size()); } return rp; }
bool schedule_chain::check_against_dag(const schedule_dag& dag) const { #if 1 #define fail(msg) return false #else #define fail(msg) std::runtime_error(msg) #endif /* trivial check */ if(dag.get_units().size() != get_unit_count()) fail("schedule_chain::check_against_dag detected a unit count mismatch"); /* first build a map of positions */ std::map< const schedule_unit *, size_t > pos; for(size_t i = 0; i < get_unit_count(); i++) pos[get_unit_at(i)] = i; /* then check each dependency is satisfied */ for(size_t i = 0; i < dag.get_deps().size(); i++) { const schedule_dep& d = dag.get_deps()[i]; if(pos.find(d.from()) == pos.end() || pos.find(d.to()) == pos.end()) fail("schedule_chain::check_against_dag detected unscheduled unit"); if(pos[d.from()] >= pos[d.to()]) fail("schedule_chain::check_against_dag detected unsatisfied dependency"); } /* then check that the same physical register is not alive twice at the same time */ std::map< schedule_dep::reg_t, size_t > phys_reg_uses; for(size_t i = 0; i < get_unit_count(); i++) { const schedule_unit *unit = get_unit_at(i); /* destroy physical registers if any */ for(size_t j = 0; j < dag.get_preds(unit).size(); j++) { const schedule_dep& dep = dag.get_preds(unit)[j]; if(!dep.is_phys()) continue; assert(phys_reg_uses.find(dep.reg()) != phys_reg_uses.end() && "inconsistent phys reg uses map"); /* remove this unit from the use count of the physical register */ if((--phys_reg_uses[dep.reg()]) == 0) /* if the set is now empty, remove entry */ phys_reg_uses.erase(dep.reg()); } /* create physical registers if any */ for(size_t j = 0; j < dag.get_succs(unit).size(); j++) { const schedule_dep& dep = dag.get_succs(unit)[j]; if(!dep.is_phys()) continue; /* if the physical register is already alive, then the schedule is not valid */ if(phys_reg_uses.find(dep.reg()) != phys_reg_uses.end()) fail("schedule_chain::check_against_dag detected that the same physical register is alive at the same point" "but with different creators, this will result in miscompilation!"); } for(size_t j = 0; j < dag.get_succs(unit).size(); j++) { const schedule_dep& dep = dag.get_succs(unit)[j]; if(!dep.is_phys()) continue; phys_reg_uses[dep.reg()]++; } } assert(phys_reg_uses.size() == 0 && "not all physical register have been destroyed: partial dag ?"); return true; }
void user_daemon_t::handle_parameters(int argc, char *argv[]) { bool_t instance_specified, unit_specified; co_command_line_params_t cmdline; co_rc_t rc; rc = co_cmdline_params_alloc(&argv[1], argc-1, &cmdline); if (!CO_OK(rc)) { log("error parsing arguments\n"); throw user_daemon_exception_t(rc); } try { rc = co_cmdline_params_one_arugment_int_parameter(cmdline, "-i", &instance_specified, (int *)¶m_instance); if (!CO_OK(rc)) { syntax(); throw user_daemon_exception_t(rc); } rc = co_cmdline_params_one_arugment_int_parameter(cmdline, "-u", &unit_specified, ¶m_index); if (!CO_OK(rc)) { syntax(); throw user_daemon_exception_t(rc); } handle_extended_parameters(cmdline); rc = co_cmdline_params_check_for_no_unparsed_parameters(cmdline, PTRUE); if (!CO_OK(rc)) { syntax(); throw user_daemon_exception_t(rc); } if (!instance_specified && !unit_specified) { rc = CO_RC(OK); syntax(); throw user_daemon_exception_t(rc); } verify_parameters(); if ((param_index < 0) || (param_index >= get_unit_count())) { syntax(); log("invalid unit index: %d\n", param_index); throw user_daemon_exception_t(rc); } if (!instance_specified) { syntax(); log("coLinux instance not specificed\n"); throw user_daemon_exception_t(rc); } } catch(...) { co_cmdline_params_free(cmdline); throw; } }