diff options
Diffstat (limited to 'src/mem/bus.cc')
-rw-r--r-- | src/mem/bus.cc | 117 |
1 files changed, 73 insertions, 44 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 0c0e3c3e2..c89455f02 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Andreas Hansson + * William Wang */ /** @@ -72,12 +73,14 @@ Bus::Bus(const BusParams *p) // create the ports based on the size of the master and slave // vector ports, and the presence of the default master - // id used to index into interfaces which is a flat vector of all - // ports + // id used to index into master and slave ports, that currently + // has holes to be able to use the id to index into either int id = 0; for (int i = 0; i < p->port_master_connection_count; ++i) { std::string portName = csprintf("%s-p%d", name(), id); - interfaces.push_back(new BusPort(portName, this, id)); + BusMasterPort* bp = new BusMasterPort(portName, this, id); + masterPorts.push_back(bp); + slavePorts.push_back(NULL); ++id; } @@ -86,7 +89,9 @@ Bus::Bus(const BusParams *p) if (p->port_default_connection_count) { defaultPortId = id; std::string portName = csprintf("%s-default", name()); - interfaces.push_back(new BusPort(portName, this, id)); + BusMasterPort* bp = new BusMasterPort(portName, this, id); + masterPorts.push_back(bp); + slavePorts.push_back(NULL); ++id; // this is an additional master port ++nbrMasterPorts; @@ -96,44 +101,55 @@ Bus::Bus(const BusParams *p) // nbrMasterPorts in the vector for (int i = 0; i < p->port_slave_connection_count; ++i) { std::string portName = csprintf("%s-p%d", name(), id); - interfaces.push_back(new BusPort(portName, this, id)); + BusSlavePort* bp = new BusSlavePort(portName, this, id); + masterPorts.push_back(NULL); + slavePorts.push_back(bp); ++id; } clearPortCache(); } -Port * -Bus::getPort(const std::string &if_name, int idx) +MasterPort & +Bus::getMasterPort(const std::string &if_name, int idx) { if (if_name == "master") { // the master index translates directly to the interfaces // vector as they are stored first - return interfaces[idx]; - } else if (if_name == "slave") { - // the slaves are stored after the masters and we must thus - // offset the slave index with the number of master ports - return interfaces[nbrMasterPorts + idx]; + return *masterPorts[idx]; } else if (if_name == "default") { - return interfaces[defaultPortId]; + return *masterPorts[defaultPortId]; } else { - panic("No port %s %d on bus %s\n", if_name, idx, name()); + return MemObject::getMasterPort(if_name, idx); + } +} + +SlavePort & +Bus::getSlavePort(const std::string &if_name, int idx) +{ + if (if_name == "slave") { + return *slavePorts[nbrMasterPorts + idx]; + } else { + return MemObject::getSlavePort(if_name, idx); } } void Bus::init() { - std::vector<BusPort*>::iterator intIter; + std::vector<BusSlavePort*>::iterator intIter; // iterate over our interfaces and determine which of our neighbours // are snooping and add them as snoopers - for (intIter = interfaces.begin(); intIter != interfaces.end(); + for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++) { - if ((*intIter)->getPeer()->isSnooping()) { - DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", - (*intIter)->getPeer()->name()); - snoopPorts.push_back(*intIter); + // since there are holes in the vector, check for NULL + if (*intIter != NULL) { + if ((*intIter)->getMasterPort().isSnooping()) { + DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", + (*intIter)->getMasterPort().name()); + snoopPorts.push_back(*intIter); + } } } } @@ -194,7 +210,9 @@ Bus::recvTiming(PacketPtr pkt) // get the source id and port Packet::NodeID src_id = pkt->getSrc(); - BusPort *src_port = interfaces[src_id]; + // determine the source port based on the id + Port *src_port = slavePorts[src_id] ? + (Port*) slavePorts[src_id] : (Port*) masterPorts[src_id]; // If the bus is busy, or other devices are in line ahead of the current // one, put this device on the retry list. @@ -218,14 +236,14 @@ Bus::recvTiming(PacketPtr pkt) int dest_id; Port *dest_port; - if (dest == Packet::Broadcast) { + if (pkt->isRequest()) { // the packet is a memory-mapped request and should be broadcasted to // our snoopers - assert(pkt->isRequest()); + assert(dest == Packet::Broadcast); SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we got this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it @@ -241,16 +259,28 @@ Bus::recvTiming(PacketPtr pkt) // determine the destination based on the address and forward // through the corresponding master port dest_id = findPort(pkt->getAddr()); - dest_port = interfaces[dest_id]; + dest_port = masterPorts[dest_id]; } else { // the packet is a response, and it should always go back to // the port determined by the destination field dest_id = dest; assert(dest_id != src_id); // catch infinite loops - assert(dest_id < interfaces.size()); - dest_port = interfaces[dest_id]; + dest_port = slavePorts[dest_id] ? + (Port*) slavePorts[dest_id] : (Port*) masterPorts[dest_id]; + + // a normal response from the memory system (i.e. from a + // connected slave) should always go back to the master + // that issued it through one of our slave ports, however + // if this is a snoop response it could go either way, for + // example, it could be coming from a slave port + // connecting an L1 with a coherent master and another L1 + // coherent master (one of our slave ports), or coming + // from the L1 and going to the L2 slave port (through one + // of our master ports) } + assert(dest_port != NULL); + // if this is a snoop from a slave (corresponding to our own // master), i.e. the memory side of the bus, then do not send it // back to where it came from @@ -318,8 +348,6 @@ Bus::retryWaiting() // send a retry to the port at the head of the retry list inRetry = true; - DPRINTF(Bus, "Sending a retry to %s\n", - retryList.front()->getPeer()->name()); // note that we might have blocked on the receiving port being // busy (rather than the bus itself) and now call retry before the @@ -427,7 +455,7 @@ Bus::recvAtomic(PacketPtr pkt) SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we could have gotten this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came @@ -464,7 +492,7 @@ Bus::recvAtomic(PacketPtr pkt) // master), i.e. the memory side of the bus, then do not send it // back to where it came from if (dest_id != src_id) { - response_latency = interfaces[dest_id]->sendAtomic(pkt); + response_latency = masterPorts[dest_id]->sendAtomic(pkt); } // if we got a response from a snooper, restore it here @@ -504,7 +532,7 @@ Bus::recvFunctional(PacketPtr pkt) SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we could have gotten this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came @@ -528,7 +556,7 @@ Bus::recvFunctional(PacketPtr pkt) // master), i.e. the memory side of the bus, then do not send // it back to where it came from, if (dest_id != src_id) { - interfaces[dest_id]->sendFunctional(pkt); + masterPorts[dest_id]->sendFunctional(pkt); } } } @@ -551,7 +579,8 @@ Bus::recvRangeChange(int id) defaultRange.clear(); // Only try to update these ranges if the user set a default responder. if (useDefaultRange) { - AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges(); + AddrRangeList ranges = + masterPorts[id]->getSlavePort().getAddrRanges(); for(iter = ranges.begin(); iter != ranges.end(); iter++) { defaultRange.push_back(*iter); DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", @@ -560,8 +589,8 @@ Bus::recvRangeChange(int id) } } else { - assert(id < interfaces.size() && id >= 0); - BusPort *port = interfaces[id]; + assert(id < masterPorts.size() && id >= 0); + BusMasterPort *port = masterPorts[id]; // Clean out any previously existent ids for (PortIter portIter = portMap.begin(); @@ -572,7 +601,7 @@ Bus::recvRangeChange(int id) portIter++; } - ranges = port->getPeer()->getAddrRanges(); + ranges = port->getSlavePort().getAddrRanges(); for (iter = ranges.begin(); iter != ranges.end(); iter++) { DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", @@ -580,8 +609,8 @@ Bus::recvRangeChange(int id) if (portMap.insert(*iter, id) == portMap.end()) { int conflict_id = portMap.find(*iter)->second; fatal("%s has two ports with same range:\n\t%s\n\t%s\n", - name(), interfaces[id]->getPeer()->name(), - interfaces[conflict_id]->getPeer()->name()); + name(), masterPorts[id]->getSlavePort().name(), + masterPorts[conflict_id]->getSlavePort().name()); } } } @@ -589,10 +618,10 @@ Bus::recvRangeChange(int id) // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - std::vector<BusPort*>::const_iterator intIter; + std::vector<BusSlavePort*>::const_iterator intIter; - for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - if ((*intIter)->getId() != id) + for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++) + if (*intIter != NULL && (*intIter)->getId() != id) (*intIter)->sendRangeChange(); inRecvRangeChange.erase(id); @@ -640,7 +669,7 @@ Bus::getAddrRanges(int id) } bool -Bus::isSnooping(int id) +Bus::isSnooping(int id) const { // in essence, answer the question if there are snooping ports return !snoopPorts.empty(); @@ -656,7 +685,7 @@ Bus::findBlockSize(int id) PortIter p_end = portMap.end(); for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) { - unsigned tmp_bs = interfaces[p_iter->second]->peerBlockSize(); + unsigned tmp_bs = masterPorts[p_iter->second]->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; } |