# HG changeset patch # User Brad Beckmann <brad.beckm...@amd.com> # Date 1260657437 28800 # Node ID fa98d755bc7afb680785e9fb2cb711c42514b815 # Parent d9f2104b2c11b32657c6fd30623a2a881a6e93ed ruby: Added pio port support to Ruby Port Added a pio port to RubyPort so that pio requests from the cpus can be routed to m5 devices. The code compiles, but has not yet been tested.
diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/RubyPort.cc --- a/src/mem/ruby/system/RubyPort.cc Sat Dec 12 14:37:16 2009 -0800 +++ b/src/mem/ruby/system/RubyPort.cc Sat Dec 12 14:37:17 2009 -0800 @@ -2,10 +2,9 @@ #include "mem/ruby/system/RubyPort.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" -//void (*RubyPort::m_hit_callback)(int64_t) = NULL; uint16_t RubyPort::m_num_ports = 0; -RubyPort::RequestMap RubyPort::pending_requests; +RubyPort::RequestMap RubyPort::pending_cpu_requests; RubyPort::RubyPort(const Params *p) : MemObject(p), @@ -20,6 +19,7 @@ m_port_id = m_num_ports++; m_request_cnt = 0; m_hit_callback = NULL; + pio_port = NULL; assert(m_num_ports <= 2048); // see below for reason } @@ -34,21 +34,47 @@ { if (if_name == "port") { return new M5Port(csprintf("%s-port%d", name(), idx), this); + } else if (if_name == "pio_port") { + // + // ensure there is only one pio port + // + assert(pio_port == NULL); + + pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), + this); + + return pio_port; } else if (if_name == "funcmem_port") { return &funcMemPort; } return NULL; } +RubyPort::PioPort::PioPort(const std::string &_name, + RubyPort *_port) + : SimpleTimingPort(_name, _port) +{ + DPRINTF(Ruby, "creating port to ruby sequencer to cpu %s\n", _name); + ruby_port = _port; +} + RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port) : SimpleTimingPort(_name, _port) { - DPRINTF(Ruby, "creating port to ruby memory %s\n", _name); + DPRINTF(Ruby, "creating port from ruby sequcner to cpu %s\n", _name); ruby_port = _port; } Tick +RubyPort::PioPort::recvAtomic(PacketPtr pkt) +{ + panic("RubyPort::PioPort::recvAtomic() not implemented!\n"); + return 0; +} + + +Tick RubyPort::M5Port::recvAtomic(PacketPtr pkt) { panic("RubyPort::M5Port::recvAtomic() not implemented!\n"); @@ -57,6 +83,36 @@ bool +RubyPort::PioPort::recvTiming(PacketPtr pkt) +{ + // + // In FS mode, ruby memory will receive pio responses from devices and + // it must forward these responses back to the particular CPU. + // + DPRINTF(MemoryAccess, + "Pio response for address %#x\n", + pkt->getAddr()); + + assert(pkt->isResponse()); + + // + // First we must retrieve the request port from the sender State + // + RubyPort::SenderState *senderState = + safe_cast<RubyPort::SenderState *>(pkt->senderState); + M5Port *port = senderState->port; + assert(port != NULL); + + // pop the sender state from the packet + pkt->senderState = senderState->saved; + delete senderState; + + port->sendTiming(pkt); + + return true; +} + +bool RubyPort::M5Port::recvTiming(PacketPtr pkt) { DPRINTF(MemoryAccess, @@ -66,28 +122,6 @@ //dsm: based on SimpleTimingPort::recvTiming(pkt); // - // In FS mode, ruby memory will receive pio responses from devices and - // it must forward these responses back to the particular CPU. - // -#if 0 - if (pkt->isResponse() != false && isPioAddress(pkt->getAddr()) != false) { - DPRINTF(MemoryAccess, - "Pio Response callback %#x\n", - pkt->getAddr()); - SenderState *senderState = safe_cast<SenderState *>(pkt->senderState); - M5Port *port = senderState->port; - - // pop the sender state from the packet - pkt->senderState = senderState->saved; - delete senderState; - - port->sendTiming(pkt); - - return true; - } -#endif - - // // After checking for pio responses, the remainder of packets // received by ruby should only be M5 requests, which should never // get nacked. There used to be code to hanldle nacks here, but @@ -106,13 +140,19 @@ // // Check for pio requests and directly send them to the dedicated - // pio_port. + // pio port. // -#if 0 - if (isPioAddress(pkt->getAddr()) != false) { - return ruby_mem->pio_port->sendTiming(pkt); + if (!isPhysMemAddress(pkt->getAddr())) { + assert(ruby_port->pio_port != NULL); + + // + // Save the port in the sender state object to be used later to + // route the response + // + pkt->senderState = new SenderState(this, pkt->senderState); + + return ruby_port->pio_port->sendTiming(pkt); } -#endif // // For DMA and CPU requests, translate them to ruby requests before @@ -144,7 +184,7 @@ } // Save the request for the callback - RubyPort::pending_requests[req_id] = new RequestCookie(pkt, this); + RubyPort::pending_cpu_requests[req_id] = new RequestCookie(pkt, this); return true; } @@ -154,16 +194,14 @@ { // // Note: This single fuction can be called by cpu and dma ports, - // as well as the functional port. The functional port prevents - // us from replacing this single function with separate port - // functions. + // as well as the functional port. // - RequestMap::iterator i = pending_requests.find(req_id); - if (i == pending_requests.end()) + RequestMap::iterator i = pending_cpu_requests.find(req_id); + if (i == pending_cpu_requests.end()) panic("could not find pending request %d\n", req_id); RequestCookie *cookie = i->second; - pending_requests.erase(i); + pending_cpu_requests.erase(i); Packet *pkt = cookie->pkt; M5Port *port = cookie->m5Port; @@ -204,24 +242,50 @@ } bool +RubyPort::PioPort::sendTiming(PacketPtr pkt) +{ + schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0 + return true; +} + +bool +RubyPort::M5Port::isPhysMemAddress(Addr addr) +{ + AddrRangeList physMemAddrList; + bool snoop = false; + ruby_port->funcMemPort.getPeerAddressRanges(physMemAddrList, snoop); + for(AddrRangeIter iter = physMemAddrList.begin(); + iter != physMemAddrList.end(); + iter++) { + if (addr >= iter->start && addr <= iter->end) { + DPRINTF(MemoryAccess, "Request found in %#llx - %#llx range\n", + iter->start, iter->end); + return true; + } + } + assert(isPioAddress(addr)); + return false; +} + +bool RubyPort::M5Port::isPioAddress(Addr addr) { -#if 0 AddrRangeList pioAddrList; bool snoop = false; - if (ruby_mem->pio_port == NULL) { + if (ruby_port->pio_port == NULL) { return false; } - ruby_mem->pio_port->getPeerAddressRanges(pioAddrList, snoop); - for(AddrRangeIter iter = pioAddrList.begin(); iter != pioAddrList.end(); iter++) { + ruby_port->pio_port->getPeerAddressRanges(pioAddrList, snoop); + for(AddrRangeIter iter = pioAddrList.begin(); + iter != pioAddrList.end(); + iter++) { if (addr >= iter->start && addr <= iter->end) { DPRINTF(MemoryAccess, "Pio request found in %#llx - %#llx range\n", iter->start, iter->end); return true; } } -#endif return false; } diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/RubyPort.hh --- a/src/mem/ruby/system/RubyPort.hh Sat Dec 12 14:37:16 2009 -0800 +++ b/src/mem/ruby/system/RubyPort.hh Sat Dec 12 14:37:17 2009 -0800 @@ -35,10 +35,39 @@ private: bool isPioAddress(Addr addr); + bool isPhysMemAddress(Addr addr); }; friend class M5Port; + class PioPort : public SimpleTimingPort + { + + RubyPort *ruby_port; + + public: + PioPort(const std::string &_name, + RubyPort *_port); + bool sendTiming(PacketPtr pkt); + + protected: + virtual bool recvTiming(PacketPtr pkt); + virtual Tick recvAtomic(PacketPtr pkt); + }; + + friend class PioPort; + + struct SenderState : public Packet::SenderState + { + M5Port* port; + Packet::SenderState *saved; + + SenderState(M5Port* _port, + Packet::SenderState *sender_state = NULL) + : port(_port), saved(sender_state) + {} + }; + typedef RubyPortParams Params; RubyPort(const Params *p); virtual ~RubyPort() {} @@ -89,6 +118,7 @@ int m_version; AbstractController* m_controller; MessageBuffer* m_mandatory_q_ptr; + PioPort* pio_port; private: static uint16_t m_num_ports; @@ -104,7 +134,7 @@ }; typedef std::map<int64_t, RequestCookie*> RequestMap; - static RequestMap pending_requests; + static RequestMap pending_cpu_requests; FunctionalPort funcMemPort; }; diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/Sequencer.py --- a/src/mem/ruby/system/Sequencer.py Sat Dec 12 14:37:16 2009 -0800 +++ b/src/mem/ruby/system/Sequencer.py Sat Dec 12 14:37:17 2009 -0800 @@ -7,6 +7,7 @@ abstract = True port = VectorPort("M5 port") version = Param.Int(0, "") + pio_port = Port("Ruby_pio_port") class RubySequencer(RubyPort): type = 'RubySequencer' _______________________________________________ m5-dev mailing list m5-dev@m5sim.org http://m5sim.org/mailman/listinfo/m5-dev