#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Gecode; using boost::dynamic_bitset; using boost::lexical_cast; string S() { return ""; } template string S(T v, Ts... vs) { stringstream ss; ss << v << S(vs...); return ss.str(); } struct Op { string inst; IntVar *v; int delay; }; struct Demultiplexer : public MinimizeScript { IntVarArray op_times; IntVarArray timeDistortions; IntVar maxTimeDistortion; array ops; uint opCount; Demultiplexer(dynamic_bitset<> bits) : op_times(*this, 17, 0, 16), timeDistortions(*this, bits.size(), 0, 170), maxTimeDistortion(*this, 0, 170), opCount(0) { /// post the problem (the instructions and their temporal /// dependencies) // only one op per time slice distinct(*this, op_times); // the final jump auto &jump = op(2, " ijmp"); at(jump, 15); // rising flanks for (uint i=0; i 1) { auto nextOp = op(delay - 1, "; 1 clock cycle delay"); rel(*this, *(o.v) + 1 == *(nextOp.v)); } return o; } /// helper for constraint formulation void after(Op& pre, Op& post, int delay_min=0, int delay_max=-1) { rel(*this, *(pre.v) + pre.delay + delay_min <= *(post.v)); if (delay_max >= 0) rel(*this, *(pre.v) + pre.delay + delay_max >= *(post.v)); } void at(Op& op, int time_min, int time_max=-1) { if (time_max == -1) time_max = time_min; rel(*this, *(op.v) >= time_min); rel(*this, *(op.v) <= time_max); } /// return resulting instruction stream string print() { stringstream ss; print(ss, false); return ss.str(); } /// gecode boilerplate Demultiplexer(bool share, Demultiplexer &o) : MinimizeScript(share, o), ops(o.ops), opCount(o.opCount) { op_times .update(*this, share, o.op_times ); timeDistortions .update(*this, share, o.timeDistortions ); maxTimeDistortion.update(*this, share, o.maxTimeDistortion); } virtual Space* copy(bool share) { return new Demultiplexer(share, *this); } void print(ostream &o, bool printTimes=true) const { multimap timedOps; for (uint i=0; i(argv[1]); set> noSolutions; double maxDev{0}; // find the optimal solution (legal instruction sequence with // minimal deviation from WS2812 specs central delay value) for (uint i=0; i < uint(1)< pattern(bits, i); Demultiplexer init(pattern), *best = nullptr, *cur; BAB search(&init); while (cur = search.next()) { if (best) delete best; best = cur; } if (best) { auto dev = double(best->cost().min()); maxDev = max(maxDev, dev); cout << ".ws2812_mux" << bits << "_pat" << pattern << ":\n; max. time deviation: "; printDev(dev); cout << "; ind. deviations: " << best->timeDistortions << " (decicycles)\n"; best->print(cout, false); cout << endl; delete best; }else{ noSolutions.insert(pattern); } } // terminate if not all solutions have been found if (!noSolutions.empty()) { cerr << "No solutions found for:\n"; for (auto p : noSolutions) cerr << " " << p << endl; cerr << "Total: no solution for " << noSolutions.size() << " of " << (1<(bits, i) << endl; // print statistics cout << ";\n; Maximal deviation of all patterns: "; printDev(maxDev); return 0; }