19 DeviceOp device, function_ref<std::optional<End>(StringAttr)> endOf) {
20 for (
auto sequence : device.getOps<RuntimeSequenceOp>()) {
21 DenseMap<Operation *, int64_t> position, end;
23 std::function<void(Operation *)> number = [&](Operation *op) {
24 position[op] = next++;
25 for (Region ®ion : op->getRegions())
26 for (Block &block : region)
27 for (Operation &nested : block)
33 auto &byFifo = spans.emplace_back();
34 DenseMap<Value, AIEX::DMAConfigureTaskForOp> tasks;
35 auto note = [&](Operation *op, StringAttr symbol,
bool issues) {
36 std::optional<End> shimEnd = endOf(symbol);
39 int64_t from = position[op], to = position[op];
40 for (Operation *parent = op->getParentOp(); parent != sequence;
41 parent = parent->getParentOp())
42 if (isa<LoopLikeOpInterface>(parent)) {
43 from = position[parent];
46 Span &span = byFifo[shimEnd->fifo];
47 span.sends |= shimEnd->sends;
48 span.first = std::min(span.first, from);
49 span.last = std::max(span.last, to);
50 int64_t &mark = issues ? span.lastIssue : span.lastDone;
51 mark = std::max(mark, to);
53 auto noteTask = [&](Operation *op, Value task,
bool issues) {
54 if (
auto configure = tasks.lookup(task))
55 note(op, configure.getAlloc().getRootReference(), issues);
57 sequence.walk([&](Operation *op) {
58 if (
auto memcpy = dyn_cast<AIEX::NpuDmaMemcpyNdOp>(op))
59 note(op, memcpy.getMetadata().getRootReference(),
true);
60 else if (
auto wait = dyn_cast<AIEX::NpuDmaWaitOp>(op))
61 note(op, wait.getSymbolAttr().getAttr(),
false);
62 else if (
auto configure = dyn_cast<AIEX::DMAConfigureTaskForOp>(op))
63 tasks[configure.getResult()] = configure;
64 else if (
auto start = dyn_cast<AIEX::DMAStartTaskOp>(op))
65 noteTask(op, start.getTask(),
true);
66 else if (
auto await = dyn_cast<AIEX::DMAAwaitTaskOp>(op))
67 noteTask(op, await.getTask(),
false);
70 else if (
auto free = dyn_cast<AIEX::DMAFreeTaskOp>(op))
71 noteTask(op, free.getTask(),
false);
81 bool aUsed =
false, bUsed =
false;
82 for (
auto &byFifo : spans) {
83 auto sa = byFifo.find(a), sb = byFifo.find(b);
84 aUsed |= sa != byFifo.end();
85 bUsed |= sb != byFifo.end();
86 if (sa == byFifo.end() || sb == byFifo.end())
88 auto before = [](
const Span &x,
const Span &y) {
89 return !x.sends && x.last < y.first && x.lastDone > x.lastIssue;
91 if (!before(sa->second, sb->second) && !before(sb->second, sa->second))
94 return aUsed && bUsed;
99 auto order = llvm::to_vector(llvm::seq<unsigned>(0, ends.size()));
100 llvm::stable_sort(order, [&](
unsigned x,
unsigned y) {
101 return ends[x].getValue() < ends[y].getValue();
103 SmallVector<SmallVector<unsigned>> result;
104 for (
unsigned end : order) {
105 auto *group = llvm::find_if(result, [&](ArrayRef<unsigned> members) {
107 members, [&](
unsigned m) {
return apart(ends[m], ends[end]); });
109 if (group == result.end())
110 result.push_back({end});
112 group->push_back(end);