55 std::optional<PortConnection>
56 getConnectionThroughWire(Operation *op,
Port masterPort)
const {
57 LLVM_DEBUG(llvm::dbgs() <<
"Wire:" << *op <<
" "
58 << stringifyWireBundle(masterPort.bundle) <<
" "
59 << masterPort.channel <<
"\n");
60 for (
auto wireOp : device.getOps<WireOp>()) {
61 if (wireOp.getSource().getDefiningOp() == op &&
62 wireOp.getSourceBundle() == masterPort.bundle) {
63 Operation *other = wireOp.getDest().getDefiningOp();
64 Port otherPort = {wireOp.getDestBundle(), masterPort.channel};
65 LLVM_DEBUG(llvm::dbgs() <<
"Connects To:" << *other <<
" "
66 << stringifyWireBundle(otherPort.bundle) <<
" "
67 << otherPort.channel <<
"\n");
71 if (wireOp.getDest().getDefiningOp() == op &&
72 wireOp.getDestBundle() == masterPort.bundle) {
73 Operation *other = wireOp.getSource().getDefiningOp();
74 Port otherPort = {wireOp.getSourceBundle(), masterPort.channel};
75 LLVM_DEBUG(llvm::dbgs() <<
"Connects To:" << *other <<
" "
76 << stringifyWireBundle(otherPort.bundle) <<
" "
77 << otherPort.channel <<
"\n");
81 LLVM_DEBUG(llvm::dbgs() <<
"*** Missing Wire!\n");
85 std::vector<PortMaskValue>
86 getConnectionsThroughSwitchbox(Region &r,
Port sourcePort)
const {
87 LLVM_DEBUG(llvm::dbgs() <<
"Switchbox:\n");
89 std::vector<PortMaskValue> portSet;
90 for (
auto connectOp : b.getOps<ConnectOp>()) {
91 if (connectOp.sourcePort() == sourcePort) {
93 portSet.push_back({connectOp.destPort(), maskValue});
94 LLVM_DEBUG(llvm::dbgs()
95 <<
"To:" << stringifyWireBundle(connectOp.destPort().bundle)
96 <<
" " << connectOp.destPort().channel <<
"\n");
99 for (
auto connectOp : b.getOps<PacketRulesOp>()) {
100 if (connectOp.sourcePort() == sourcePort) {
101 LLVM_DEBUG(llvm::dbgs()
103 << stringifyWireBundle(connectOp.sourcePort().bundle) <<
" "
104 << sourcePort.channel <<
"\n");
105 for (
auto masterSetOp : b.getOps<MasterSetOp>())
106 for (Value amsel : masterSetOp.getAmsels())
108 connectOp.getRules().front().getOps<PacketRuleOp>()) {
109 if (ruleOp.getAmsel() == amsel) {
110 LLVM_DEBUG(llvm::dbgs()
112 << stringifyWireBundle(masterSetOp.destPort().bundle)
113 <<
" " << masterSetOp.destPort().channel <<
"\n");
114 MaskValue maskValue = {ruleOp.maskInt(), ruleOp.valueInt()};
115 portSet.push_back({masterSetOp.destPort(), maskValue});
123 std::vector<PacketConnection>
124 maskSwitchboxConnections(Operation *switchOp,
125 std::vector<PortMaskValue> nextPortMaskValues,
127 std::vector<PacketConnection> worklist;
128 for (
auto &nextPortMaskValue : nextPortMaskValues) {
129 Port nextPort = nextPortMaskValue.port;
130 MaskValue nextMaskValue = nextPortMaskValue.mv;
131 int maskConflicts = nextMaskValue.
mask & maskValue.
mask;
132 LLVM_DEBUG(llvm::dbgs() <<
"Mask: " << maskValue.
mask <<
" "
133 << maskValue.
value <<
"\n");
134 LLVM_DEBUG(llvm::dbgs() <<
"NextMask: " << nextMaskValue.
mask <<
" "
135 << nextMaskValue.
value <<
"\n");
136 LLVM_DEBUG(llvm::dbgs() << maskConflicts <<
"\n");
138 if ((maskConflicts & nextMaskValue.
value) !=
139 (maskConflicts & maskValue.
value)) {
145 (nextMaskValue.
mask & nextMaskValue.
value)};
146 auto nextConnection = getConnectionThroughWire(switchOp, nextPort);
152 worklist.push_back({*nextConnection, newMaskValue});
164 LLVM_DEBUG(llvm::dbgs()
165 <<
"getConnectedTile(" << stringifyWireBundle(
port.bundle) <<
" "
166 <<
port.channel <<
")");
167 LLVM_DEBUG(tileOp.dump());
170 std::vector<PacketConnection> connectedTiles;
173 std::vector<PacketConnection> worklist;
176 auto t = getConnectionThroughWire(tileOp.getOperation(),
port);
180 return connectedTiles;
181 worklist.push_back({*t, {0, 0}});
183 while (!worklist.empty()) {
188 Operation *other = portConnection.
op;
189 Port otherPort = portConnection.
port;
192 connectedTiles.push_back(t);
193 }
else if (
auto switchOp = dyn_cast_or_null<SwitchboxOp>(other)) {
194 std::vector<PortMaskValue> nextPortMaskValues =
195 getConnectionsThroughSwitchbox(switchOp.getConnections(),
197 std::vector<PacketConnection> newWorkList =
198 maskSwitchboxConnections(switchOp, nextPortMaskValues, maskValue);
200 worklist.insert(worklist.end(), newWorkList.begin(), newWorkList.end());
201 if (!nextPortMaskValues.empty() && newWorkList.empty()) {
204 LLVM_DEBUG(llvm::dbgs() <<
"No rule matched incoming packet here: ");
205 LLVM_DEBUG(other->dump());
207 }
else if (
auto switchOp = dyn_cast_or_null<ShimMuxOp>(other)) {
208 std::vector<PortMaskValue> nextPortMaskValues =
209 getConnectionsThroughSwitchbox(switchOp.getConnections(),
211 std::vector<PacketConnection> newWorkList =
212 maskSwitchboxConnections(switchOp, nextPortMaskValues, maskValue);
214 worklist.insert(worklist.end(), newWorkList.begin(), newWorkList.end());
215 if (!nextPortMaskValues.empty() && newWorkList.empty()) {
218 LLVM_DEBUG(llvm::dbgs() <<
"No rule matched incoming packet here: ");
219 LLVM_DEBUG(other->dump());
222 LLVM_DEBUG(llvm::dbgs()
223 <<
"*** Connection Terminated at unknown operation: ");
224 LLVM_DEBUG(other->dump());
227 return connectedTiles;