4 5HMCController::HMCController(const HMCControllerParams* p) : 6 NoncoherentXBar(p), 7 n_master_ports(p->port_master_connection_count), 8 rr_counter(0) 9{ 10 assert(p->port_slave_connection_count == 1); 11} 12 13HMCController* 14HMCControllerParams::create() 15{ 16 return new HMCController(this); 17} 18 19// Since this module is a load distributor, all its master ports have the same 20// range so we should keep only one of the ranges and ignore the others 21void HMCController::recvRangeChange(PortID master_port_id) 22{ 23 if (master_port_id == 0) 24 { 25 gotAllAddrRanges = true; 26 BaseXBar::recvRangeChange(master_port_id); 27 } 28 else 29 gotAddrRanges[master_port_id] = true; 30} 31 32int HMCController::rotate_counter() 33{ 34 int current_value = rr_counter; 35 rr_counter++; 36 if (rr_counter == n_master_ports) 37 rr_counter = 0; 38 return current_value; 39} 40 41bool HMCController::recvTimingReq(PacketPtr pkt, PortID slave_port_id) 42{ 43 // determine the source port based on the id 44 SlavePort *src_port = slavePorts[slave_port_id]; 45 46 // we should never see express snoops on a non-coherent component 47 assert(!pkt->isExpressSnoop()); 48 49 // For now, this is a simple round robin counter, for distribution the 50 // load among the serial links 51 PortID master_port_id = rotate_counter(); 52 53 // test if the layer should be considered occupied for the current 54 // port 55 if (!reqLayers[master_port_id]->tryTiming(src_port)) { 56 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x BUSY\n", 57 src_port->name(), pkt->cmdString(), pkt->getAddr()); 58 return false; 59 } 60 61 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x\n", 62 src_port->name(), pkt->cmdString(), pkt->getAddr()); 63 64 // store size and command as they might be modified when 65 // forwarding the packet 66 unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0; 67 unsigned int pkt_cmd = pkt->cmdToIndex(); 68 69 // store the old header delay so we can restore it if needed 70 Tick old_header_delay = pkt->headerDelay; 71 72 // a request sees the frontend and forward latency 73 Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod(); 74 75 // set the packet header and payload delay 76 calcPacketTiming(pkt, xbar_delay); 77 78 // determine how long to be layer is busy 79 Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay; 80 81 // before forwarding the packet (and possibly altering it), 82 // remember if we are expecting a response 83 const bool expect_response = pkt->needsResponse() && 84 !pkt->cacheResponding(); 85 86 // since it is a normal request, attempt to send the packet 87 bool success = masterPorts[master_port_id]->sendTimingReq(pkt); 88 89 if (!success) { 90 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x RETRY\n", 91 src_port->name(), pkt->cmdString(), pkt->getAddr()); 92 93 // restore the header delay as it is additive 94 pkt->headerDelay = old_header_delay; 95 96 // occupy until the header is sent 97 reqLayers[master_port_id]->failedTiming(src_port, 98 clockEdge(Cycles(1))); 99 100 return false; 101 } 102 103 // remember where to route the response to 104 if (expect_response) { 105 assert(routeTo.find(pkt->req) == routeTo.end()); 106 routeTo[pkt->req] = slave_port_id; 107 } 108 109 reqLayers[master_port_id]->succeededTiming(packetFinishTime); 110 111 // stats updates 112 pktCount[slave_port_id][master_port_id]++; 113 pktSize[slave_port_id][master_port_id] += pkt_size; 114 transDist[pkt_cmd]++; 115 116 return true; 117}
| 5 6HMCController::HMCController(const HMCControllerParams* p) : 7 NoncoherentXBar(p), 8 n_master_ports(p->port_master_connection_count), 9 rr_counter(0) 10{ 11 assert(p->port_slave_connection_count == 1); 12} 13 14HMCController* 15HMCControllerParams::create() 16{ 17 return new HMCController(this); 18} 19 20// Since this module is a load distributor, all its master ports have the same 21// range so we should keep only one of the ranges and ignore the others 22void HMCController::recvRangeChange(PortID master_port_id) 23{ 24 if (master_port_id == 0) 25 { 26 gotAllAddrRanges = true; 27 BaseXBar::recvRangeChange(master_port_id); 28 } 29 else 30 gotAddrRanges[master_port_id] = true; 31} 32 33int HMCController::rotate_counter() 34{ 35 int current_value = rr_counter; 36 rr_counter++; 37 if (rr_counter == n_master_ports) 38 rr_counter = 0; 39 return current_value; 40} 41 42bool HMCController::recvTimingReq(PacketPtr pkt, PortID slave_port_id) 43{ 44 // determine the source port based on the id 45 SlavePort *src_port = slavePorts[slave_port_id]; 46 47 // we should never see express snoops on a non-coherent component 48 assert(!pkt->isExpressSnoop()); 49 50 // For now, this is a simple round robin counter, for distribution the 51 // load among the serial links 52 PortID master_port_id = rotate_counter(); 53 54 // test if the layer should be considered occupied for the current 55 // port 56 if (!reqLayers[master_port_id]->tryTiming(src_port)) { 57 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x BUSY\n", 58 src_port->name(), pkt->cmdString(), pkt->getAddr()); 59 return false; 60 } 61 62 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x\n", 63 src_port->name(), pkt->cmdString(), pkt->getAddr()); 64 65 // store size and command as they might be modified when 66 // forwarding the packet 67 unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0; 68 unsigned int pkt_cmd = pkt->cmdToIndex(); 69 70 // store the old header delay so we can restore it if needed 71 Tick old_header_delay = pkt->headerDelay; 72 73 // a request sees the frontend and forward latency 74 Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod(); 75 76 // set the packet header and payload delay 77 calcPacketTiming(pkt, xbar_delay); 78 79 // determine how long to be layer is busy 80 Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay; 81 82 // before forwarding the packet (and possibly altering it), 83 // remember if we are expecting a response 84 const bool expect_response = pkt->needsResponse() && 85 !pkt->cacheResponding(); 86 87 // since it is a normal request, attempt to send the packet 88 bool success = masterPorts[master_port_id]->sendTimingReq(pkt); 89 90 if (!success) { 91 DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x RETRY\n", 92 src_port->name(), pkt->cmdString(), pkt->getAddr()); 93 94 // restore the header delay as it is additive 95 pkt->headerDelay = old_header_delay; 96 97 // occupy until the header is sent 98 reqLayers[master_port_id]->failedTiming(src_port, 99 clockEdge(Cycles(1))); 100 101 return false; 102 } 103 104 // remember where to route the response to 105 if (expect_response) { 106 assert(routeTo.find(pkt->req) == routeTo.end()); 107 routeTo[pkt->req] = slave_port_id; 108 } 109 110 reqLayers[master_port_id]->succeededTiming(packetFinishTime); 111 112 // stats updates 113 pktCount[slave_port_id][master_port_id]++; 114 pktSize[slave_port_id][master_port_id] += pkt_size; 115 transDist[pkt_cmd]++; 116 117 return true; 118}
|