1/* 2 * Copyright (c) 2011-2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 128 unchanged lines hidden (view full) --- 137bool 138CoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id) 139{ 140 // determine the source port based on the id 141 SlavePort *src_port = slavePorts[slave_port_id]; 142 143 // remember if the packet is an express snoop 144 bool is_express_snoop = pkt->isExpressSnoop(); |
145 bool is_inhibited = pkt->memInhibitAsserted(); 146 // for normal requests, going downstream, the express snoop flag 147 // and the inhibited flag should always be the same 148 assert(is_express_snoop == is_inhibited); |
149 150 // determine the destination based on the address 151 PortID master_port_id = findPort(pkt->getAddr()); 152 153 // test if the crossbar should be considered occupied for the current 154 // port, and exclude express snoops from the check 155 if (!is_express_snoop && !reqLayers[master_port_id]->tryTiming(src_port)) { 156 DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n", --- 5 unchanged lines hidden (view full) --- 162 src_port->name(), pkt->cmdString(), is_express_snoop, 163 pkt->getAddr()); 164 165 // store size and command as they might be modified when 166 // forwarding the packet 167 unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0; 168 unsigned int pkt_cmd = pkt->cmdToIndex(); 169 |
170 calcPacketTiming(pkt); 171 Tick packetFinishTime = pkt->lastWordDelay + curTick(); 172 173 // uncacheable requests need never be snooped 174 if (!pkt->req->isUncacheable() && !system->bypassCaches()) { 175 // the packet is a memory-mapped request and should be 176 // broadcasted to our snoopers but the source 177 if (snoopFilter) { --- 5 unchanged lines hidden (view full) --- 183 pkt->cmdString(), pkt->getAddr(), sf_res.first.size(), 184 sf_res.second); 185 forwardTiming(pkt, slave_port_id, sf_res.first); 186 } else { 187 forwardTiming(pkt, slave_port_id); 188 } 189 } 190 |
191 // remember if the packet will generate a snoop response 192 const bool expect_snoop_resp = !is_inhibited && pkt->memInhibitAsserted(); 193 const bool expect_response = pkt->needsResponse() && 194 !pkt->memInhibitAsserted(); |
195 |
196 // Note: Cannot create a copy of the full packet, here. 197 MemCmd orig_cmd(pkt->cmd); 198 199 // since it is a normal request, attempt to send the packet 200 bool success = masterPorts[master_port_id]->sendTimingReq(pkt); 201 202 if (snoopFilter && !pkt->req->isUncacheable() 203 && !system->bypassCaches()) { --- 5 unchanged lines hidden (view full) --- 209 // phase tracking. 210 MemCmd tmp_cmd(pkt->cmd); 211 pkt->cmd = orig_cmd; 212 // Let the snoop filter know about the success of the send operation 213 snoopFilter->updateRequest(pkt, *src_port, !success); 214 pkt->cmd = tmp_cmd; 215 } 216 |
217 // check if we were successful in sending the packet onwards 218 if (!success) { 219 // express snoops and inhibited packets should never be forced 220 // to retry 221 assert(!is_express_snoop); 222 assert(!pkt->memInhibitAsserted()); 223 224 // undo the calculation so we can check for 0 again 225 pkt->firstWordDelay = pkt->lastWordDelay = 0; 226 227 DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n", 228 src_port->name(), pkt->cmdString(), pkt->getAddr()); 229 230 // update the layer state and schedule an idle event 231 reqLayers[master_port_id]->failedTiming(src_port, 232 clockEdge(headerCycles)); |
233 } else { |
234 // express snoops currently bypass the crossbar state entirely 235 if (!is_express_snoop) { 236 // if this particular request will generate a snoop 237 // response 238 if (expect_snoop_resp) { 239 // we should never have an exsiting request outstanding 240 assert(outstandingSnoop.find(pkt->req) == 241 outstandingSnoop.end()); 242 outstandingSnoop.insert(pkt->req); |
243 |
244 // basic sanity check on the outstanding snoops 245 panic_if(outstandingSnoop.size() > 512, 246 "Outstanding snoop requests exceeded 512\n"); 247 } |
248 |
249 // remember where to route the normal response to 250 if (expect_response || expect_snoop_resp) { 251 assert(routeTo.find(pkt->req) == routeTo.end()); 252 routeTo[pkt->req] = slave_port_id; |
253 |
254 panic_if(routeTo.size() > 512, 255 "Routing table exceeds 512 packets\n"); 256 } |
257 258 // update the layer state and schedule an idle event |
259 reqLayers[master_port_id]->succeededTiming(packetFinishTime); 260 } |
261 |
262 // stats updates only consider packets that were successfully sent |
263 pktCount[slave_port_id][master_port_id]++; 264 pktSize[slave_port_id][master_port_id] += pkt_size; 265 transDist[pkt_cmd]++; |
266 267 if (is_express_snoop) 268 snoops++; |
269 } 270 271 return success; 272} 273 274bool 275CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id) 276{ 277 // determine the source port based on the id 278 MasterPort *src_port = masterPorts[master_port_id]; 279 |
280 // determine the destination 281 const auto route_lookup = routeTo.find(pkt->req); 282 assert(route_lookup != routeTo.end()); 283 const PortID slave_port_id = route_lookup->second; |
284 assert(slave_port_id != InvalidPortID); 285 assert(slave_port_id < respLayers.size()); 286 287 // test if the crossbar should be considered occupied for the 288 // current port 289 if (!respLayers[slave_port_id]->tryTiming(src_port)) { 290 DPRINTF(CoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n", 291 src_port->name(), pkt->cmdString(), pkt->getAddr()); --- 6 unchanged lines hidden (view full) --- 298 // store size and command as they might be modified when 299 // forwarding the packet 300 unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0; 301 unsigned int pkt_cmd = pkt->cmdToIndex(); 302 303 calcPacketTiming(pkt); 304 Tick packetFinishTime = pkt->lastWordDelay + curTick(); 305 |
306 if (snoopFilter && !pkt->req->isUncacheable() && !system->bypassCaches()) { 307 // let the snoop filter inspect the response and update its state 308 snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]); 309 } 310 |
311 // send the packet through the destination slave port 312 bool success M5_VAR_USED = slavePorts[slave_port_id]->sendTimingResp(pkt); 313 314 // currently it is illegal to block responses... can lead to 315 // deadlock 316 assert(success); 317 |
318 // remove the request from the routing table 319 routeTo.erase(route_lookup); 320 |
321 respLayers[slave_port_id]->succeededTiming(packetFinishTime); 322 323 // stats updates 324 pktCount[slave_port_id][master_port_id]++; 325 pktSize[slave_port_id][master_port_id] += pkt_size; 326 transDist[pkt_cmd]++; 327 328 return true; --- 8 unchanged lines hidden (view full) --- 337 338 // update stats here as we know the forwarding will succeed 339 transDist[pkt->cmdToIndex()]++; 340 snoops++; 341 342 // we should only see express snoops from caches 343 assert(pkt->isExpressSnoop()); 344 |
345 // remeber if the packet is inhibited so we can see if it changes 346 const bool is_inhibited = pkt->memInhibitAsserted(); |
347 348 if (snoopFilter) { 349 // let the Snoop Filter work its magic and guide probing 350 auto sf_res = snoopFilter->lookupSnoop(pkt); 351 // No timing here: packetFinishTime += sf_res.second * clockPeriod(); 352 DPRINTF(CoherentXBar, "recvTimingSnoopReq: src %s %s 0x%x"\ 353 " SF size: %i lat: %i\n", masterPorts[master_port_id]->name(), 354 pkt->cmdString(), pkt->getAddr(), sf_res.first.size(), 355 sf_res.second); 356 357 // forward to all snoopers 358 forwardTiming(pkt, InvalidPortID, sf_res.first); 359 } else { 360 forwardTiming(pkt, InvalidPortID); 361 } 362 |
363 // if we can expect a response, remember how to route it 364 if (!is_inhibited && pkt->memInhibitAsserted()) { 365 assert(routeTo.find(pkt->req) == routeTo.end()); 366 routeTo[pkt->req] = master_port_id; 367 } 368 |
369 // a snoop request came from a connected slave device (one of 370 // our master ports), and if it is not coming from the slave 371 // device responsible for the address range something is 372 // wrong, hence there is nothing further to do as the packet 373 // would be going back to where it came from 374 assert(master_port_id == findPort(pkt->getAddr())); 375} 376 377bool 378CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) 379{ 380 // determine the source port based on the id 381 SlavePort* src_port = slavePorts[slave_port_id]; 382 |
383 // get the destination 384 const auto route_lookup = routeTo.find(pkt->req); 385 assert(route_lookup != routeTo.end()); 386 const PortID dest_port_id = route_lookup->second; |
387 assert(dest_port_id != InvalidPortID); 388 389 // determine if the response is from a snoop request we 390 // created as the result of a normal request (in which case it |
391 // should be in the outstandingSnoop), or if we merely forwarded |
392 // someone else's snoop request |
393 const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) == 394 outstandingSnoop.end(); |
395 396 // test if the crossbar should be considered occupied for the 397 // current port, note that the check is bypassed if the response 398 // is being passed on as a normal response since this is occupying 399 // the response layer rather than the snoop response layer 400 if (forwardAsSnoop) { 401 assert(dest_port_id < snoopLayers.size()); 402 if (!snoopLayers[dest_port_id]->tryTiming(src_port)) { --- 45 unchanged lines hidden (view full) --- 448 assert(success); 449 450 snoopLayers[dest_port_id]->succeededTiming(packetFinishTime); 451 } else { 452 // we got a snoop response on one of our slave ports, 453 // i.e. from a coherent master connected to the crossbar, and 454 // since we created the snoop request as part of recvTiming, 455 // this should now be a normal response again |
456 outstandingSnoop.erase(pkt->req); |
457 |
458 // this is a snoop response from a coherent master, hence it 459 // should never go back to where the snoop response came from, 460 // but instead to where the original request came from |
461 assert(slave_port_id != dest_port_id); 462 463 if (snoopFilter) { 464 // update the probe filter so that it can properly track the line 465 snoopFilter->updateSnoopResponse(pkt, *slavePorts[slave_port_id], 466 *slavePorts[dest_port_id]); 467 } 468 --- 13 unchanged lines hidden (view full) --- 482 483 // currently it is illegal to block responses... can lead 484 // to deadlock 485 assert(success); 486 487 respLayers[dest_port_id]->succeededTiming(packetFinishTime); 488 } 489 |
490 // remove the request from the routing table 491 routeTo.erase(route_lookup); 492 |
493 // stats updates 494 transDist[pkt_cmd]++; 495 snoops++; 496 497 return true; 498} 499 500 --- 332 unchanged lines hidden --- |