io_device.hh revision 2521
11049Sbinkertn@umich.edu/* 21049Sbinkertn@umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 31049Sbinkertn@umich.edu * All rights reserved. 41049Sbinkertn@umich.edu * 51049Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 61049Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 71049Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 81049Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 91049Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 101049Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 111049Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 121049Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 131049Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 141049Sbinkertn@umich.edu * this software without specific prior written permission. 151049Sbinkertn@umich.edu * 161049Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171049Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181049Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191049Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201049Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211049Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221049Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231049Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241049Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251049Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261049Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271049Sbinkertn@umich.edu */ 281049Sbinkertn@umich.edu 291049Sbinkertn@umich.edu#ifndef __DEV_IO_DEVICE_HH__ 301049Sbinkertn@umich.edu#define __DEV_IO_DEVICE_HH__ 311049Sbinkertn@umich.edu 321049Sbinkertn@umich.edu#include "base/chunk_generator.hh" 331049Sbinkertn@umich.edu#include "mem/port.hh" 341049Sbinkertn@umich.edu#include "sim/eventq.hh" 351049Sbinkertn@umich.edu#include "sim/sim_object.hh" 361049Sbinkertn@umich.edu 371049Sbinkertn@umich.educlass Platform; 381049Sbinkertn@umich.educlass PioDevice; 391049Sbinkertn@umich.educlass DmaDevice; 401049Sbinkertn@umich.edu 411049Sbinkertn@umich.edu/** 421049Sbinkertn@umich.edu * The PioPort class is a programmed i/o port that all devices that are 431049Sbinkertn@umich.edu * sensitive to an address range use. The port takes all the memory 441162Sbinkertn@umich.edu * access types and roles them into one read() and write() call that the device 451049Sbinkertn@umich.edu * must respond to. The device must also provide the addressRanges() function 461165Sbinkertn@umich.edu * with which it returns the address ranges it is interested in. An extra 471162Sbinkertn@umich.edu * sendTiming() function is implemented which takes an delay. In this way the 481049Sbinkertn@umich.edu * device can immediatly call sendTiming(pkt, time) after processing a request 491049Sbinkertn@umich.edu * and the request will be handled by the port even if the port bus the device 501049Sbinkertn@umich.edu * connects to is blocked. 511049Sbinkertn@umich.edu */ 521049Sbinkertn@umich.educlass PioPort : public Port 531049Sbinkertn@umich.edu{ 541162Sbinkertn@umich.edu protected: 551162Sbinkertn@umich.edu /** The device that this port serves. */ 561049Sbinkertn@umich.edu PioDevice *device; 571162Sbinkertn@umich.edu 581162Sbinkertn@umich.edu /** The platform that device/port are in. This is used to select which mode 591165Sbinkertn@umich.edu * we are currently operating in. */ 601049Sbinkertn@umich.edu Platform *platform; 611049Sbinkertn@umich.edu 621049Sbinkertn@umich.edu /** A list of outgoing timing response packets that haven't been serviced 631049Sbinkertn@umich.edu * yet. */ 641049Sbinkertn@umich.edu std::list<Packet*> transmitList; 651049Sbinkertn@umich.edu 661049Sbinkertn@umich.edu /** The current status of the peer(bus) that we are connected to. */ 671049Sbinkertn@umich.edu Status peerStatus; 681049Sbinkertn@umich.edu 691162Sbinkertn@umich.edu virtual bool recvTiming(Packet &pkt); 701162Sbinkertn@umich.edu 711049Sbinkertn@umich.edu virtual Tick recvAtomic(Packet &pkt); 721049Sbinkertn@umich.edu 731049Sbinkertn@umich.edu virtual void recvFunctional(Packet &pkt) ; 741049Sbinkertn@umich.edu 751049Sbinkertn@umich.edu virtual void recvStatusChange(Status status) 761049Sbinkertn@umich.edu { peerStatus = status; } 771049Sbinkertn@umich.edu 781049Sbinkertn@umich.edu virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); 791049Sbinkertn@umich.edu 801049Sbinkertn@umich.edu /** 811049Sbinkertn@umich.edu * This class is used to implemented sendTiming() with a delay. When a delay 821049Sbinkertn@umich.edu * is requested a new event is created. When the event time expires it 831049Sbinkertn@umich.edu * attempts to send the packet. If it cannot, the packet is pushed onto the 841049Sbinkertn@umich.edu * transmit list to be sent when recvRetry() is called. */ 851049Sbinkertn@umich.edu class SendEvent : public Event 861049Sbinkertn@umich.edu { 871049Sbinkertn@umich.edu PioPort *port; 881049Sbinkertn@umich.edu Packet packet; 891049Sbinkertn@umich.edu 901049Sbinkertn@umich.edu SendEvent(PioPort *p, Packet &pkt, Tick t) 911049Sbinkertn@umich.edu : Event(&mainEventQueue), packet(pkt) 921049Sbinkertn@umich.edu { schedule(curTick + t); } 931049Sbinkertn@umich.edu 941049Sbinkertn@umich.edu virtual void process(); 951049Sbinkertn@umich.edu 961049Sbinkertn@umich.edu virtual const char *description() 971049Sbinkertn@umich.edu { return "Future scheduled sendTiming event"; } 981049Sbinkertn@umich.edu 991049Sbinkertn@umich.edu friend class PioPort; 1001049Sbinkertn@umich.edu }; 1011049Sbinkertn@umich.edu 1021049Sbinkertn@umich.edu /** Schedule a sendTiming() event to be called in the future. */ 1031049Sbinkertn@umich.edu void sendTiming(Packet &pkt, Tick time) 1041049Sbinkertn@umich.edu { new PioPort::SendEvent(this, pkt, time); } 1051049Sbinkertn@umich.edu 1061049Sbinkertn@umich.edu /** This function pops the last element off the transmit list and sends it.*/ 1071049Sbinkertn@umich.edu virtual Packet *recvRetry(); 1081049Sbinkertn@umich.edu 1091049Sbinkertn@umich.edu public: 1101049Sbinkertn@umich.edu PioPort(PioDevice *dev, Platform *p); 1111049Sbinkertn@umich.edu 1121049Sbinkertn@umich.edu friend class PioPort::SendEvent; 1131049Sbinkertn@umich.edu}; 1141049Sbinkertn@umich.edu 1151049Sbinkertn@umich.educlass DmaPort : public Port 1161049Sbinkertn@umich.edu{ 1171049Sbinkertn@umich.edu protected: 1181049Sbinkertn@umich.edu PioDevice *device; 1191049Sbinkertn@umich.edu std::list<Packet*> transmitList; 1201049Sbinkertn@umich.edu Event *completionEvent; 1211049Sbinkertn@umich.edu 1221049Sbinkertn@umich.edu 1231049Sbinkertn@umich.edu virtual bool recvTiming(Packet &pkt); 1241049Sbinkertn@umich.edu virtual Tick recvAtomic(Packet &pkt) 1251049Sbinkertn@umich.edu { panic("dma port shouldn't be used for pio access."); } 1261049Sbinkertn@umich.edu virtual void recvFunctional(Packet &pkt) 1271049Sbinkertn@umich.edu { panic("dma port shouldn't be used for pio access."); } 1281049Sbinkertn@umich.edu 1291049Sbinkertn@umich.edu virtual void recvStatusChange(Status status) 1301049Sbinkertn@umich.edu { ; } 1311049Sbinkertn@umich.edu 1321049Sbinkertn@umich.edu virtual Packet *recvRetry() ; 1331049Sbinkertn@umich.edu 1341049Sbinkertn@umich.edu virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 1351049Sbinkertn@umich.edu { resp.clear(); snoop.clear(); } 1361049Sbinkertn@umich.edu 1371049Sbinkertn@umich.edu class SendEvent : public Event 1381049Sbinkertn@umich.edu { 1391049Sbinkertn@umich.edu DmaPort *port; 1401049Sbinkertn@umich.edu Packet packet; 1411049Sbinkertn@umich.edu 1421049Sbinkertn@umich.edu SendEvent(PioPort *p, Packet &pkt, Tick t) 1431049Sbinkertn@umich.edu : Event(&mainEventQueue), packet(pkt) 1441049Sbinkertn@umich.edu { schedule(curTick + t); } 1451049Sbinkertn@umich.edu 1461049Sbinkertn@umich.edu virtual void process(); 1471049Sbinkertn@umich.edu 1481049Sbinkertn@umich.edu virtual const char *description() 1491049Sbinkertn@umich.edu { return "Future scheduled sendTiming event"; } 1501049Sbinkertn@umich.edu 1511049Sbinkertn@umich.edu friend class DmaPort; 1521049Sbinkertn@umich.edu }; 1531049Sbinkertn@umich.edu 1541049Sbinkertn@umich.edu void dmaAction(Command cmd, DmaPort port, Addr addr, int size, 1551049Sbinkertn@umich.edu Event *event, uint8_t *data = NULL); 1561049Sbinkertn@umich.edu 1571049Sbinkertn@umich.edu void sendDma(Packet &pkt); 1581049Sbinkertn@umich.edu 1591049Sbinkertn@umich.edu public: 1601049Sbinkertn@umich.edu DmaPort(DmaDevice *dev); 1611049Sbinkertn@umich.edu 1621049Sbinkertn@umich.edu friend class DmaPort::SendEvent; 1631049Sbinkertn@umich.edu 1641049Sbinkertn@umich.edu}; 1651049Sbinkertn@umich.edu 1661049Sbinkertn@umich.edu/** 1671049Sbinkertn@umich.edu * This device is the base class which all devices senstive to an address range 1681049Sbinkertn@umich.edu * inherit from. There are three pure virtual functions which all devices must 1691049Sbinkertn@umich.edu * implement addressRanges(), read(), and write(). The magic do choose which 1701049Sbinkertn@umich.edu * mode we are in, etc is handled by the PioPort so the device doesn't have to 1711049Sbinkertn@umich.edu * bother. 1721049Sbinkertn@umich.edu */ 1731049Sbinkertn@umich.edu 1741049Sbinkertn@umich.educlass PioDevice : public SimObject 1751049Sbinkertn@umich.edu{ 1761076Sbinkertn@umich.edu protected: 1771049Sbinkertn@umich.edu 1781049Sbinkertn@umich.edu /** The platform we are in. This is used to decide what type of memory 1791165Sbinkertn@umich.edu * transaction we should perform. */ 1801165Sbinkertn@umich.edu Platform *platform; 1811165Sbinkertn@umich.edu 1821165Sbinkertn@umich.edu /** The pioPort that handles the requests for us and provides us requests 1831165Sbinkertn@umich.edu * that it sees. */ 1841165Sbinkertn@umich.edu PioPort *pioPort; 1851165Sbinkertn@umich.edu 1861165Sbinkertn@umich.edu virtual void addressRanges(AddrRangeList &range_list) = 0; 1871165Sbinkertn@umich.edu 1881165Sbinkertn@umich.edu /** As far as the devices are concerned they only accept atomic transactions 1891165Sbinkertn@umich.edu * which are converted to either a write or a read. */ 1901165Sbinkertn@umich.edu Tick recvAtomic(Packet &pkt) 1911165Sbinkertn@umich.edu { return pkt.cmd == Read ? this->read(pkt) : this->write(pkt); } 1921165Sbinkertn@umich.edu 1931165Sbinkertn@umich.edu /** Pure virtual function that the device must implement. Called when a read 1941165Sbinkertn@umich.edu * command is recieved by the port. */ 1951165Sbinkertn@umich.edu virtual Tick read(Packet &pkt) = 0; 1961165Sbinkertn@umich.edu 1971165Sbinkertn@umich.edu /** Pure virtual function that the device must implement. Called when a 1981165Sbinkertn@umich.edu * write command is recieved by the port. */ 1991049Sbinkertn@umich.edu virtual Tick write(Packet &pkt) = 0; 2001049Sbinkertn@umich.edu 2011049Sbinkertn@umich.edu public: 2021049Sbinkertn@umich.edu /** Params struct which is extended through each device based on the 2031049Sbinkertn@umich.edu * parameters it needs. Since we are re-writing everything, we might as well 2041049Sbinkertn@umich.edu * start from the bottom this time. */ 2051049Sbinkertn@umich.edu 2061049Sbinkertn@umich.edu struct Params 2071049Sbinkertn@umich.edu { 2081049Sbinkertn@umich.edu std::string name; 2091049Sbinkertn@umich.edu Platform *platform; 2101049Sbinkertn@umich.edu }; 2111049Sbinkertn@umich.edu 2121049Sbinkertn@umich.edu protected: 2131049Sbinkertn@umich.edu Params *_params; 2141049Sbinkertn@umich.edu 2151049Sbinkertn@umich.edu public: 2161049Sbinkertn@umich.edu const Params *params() const { return _params; } 2171049Sbinkertn@umich.edu 2181049Sbinkertn@umich.edu PioDevice(Params *p) 2191049Sbinkertn@umich.edu : SimObject(params()->name), platform(p->platform), _params(p) 2201049Sbinkertn@umich.edu {} 2211049Sbinkertn@umich.edu 2221049Sbinkertn@umich.edu virtual ~PioDevice(); 2231049Sbinkertn@umich.edu 2241049Sbinkertn@umich.edu virtual Port *getPort(const std::string &if_name) 2251049Sbinkertn@umich.edu { 2261049Sbinkertn@umich.edu if (if_name == "pio") { 2271049Sbinkertn@umich.edu if (pioPort != NULL) 2281049Sbinkertn@umich.edu panic("pio port already connected to."); 2291049Sbinkertn@umich.edu pioPort = new PioPort(this, params()->platform); 2301049Sbinkertn@umich.edu return pioPort; 2311049Sbinkertn@umich.edu } else 2321049Sbinkertn@umich.edu return NULL; 2331209Sbinkertn@umich.edu } 2341209Sbinkertn@umich.edu friend class PioPort; 2351049Sbinkertn@umich.edu 2361049Sbinkertn@umich.edu}; 2371049Sbinkertn@umich.edu 2381049Sbinkertn@umich.educlass BasicPioDevice : public PioDevice 2391049Sbinkertn@umich.edu{ 2401049Sbinkertn@umich.edu public: 2411049Sbinkertn@umich.edu struct Params : public PioDevice::Params 2421049Sbinkertn@umich.edu { 2431076Sbinkertn@umich.edu Addr pio_addr; 2441049Sbinkertn@umich.edu Tick pio_delay; 2451049Sbinkertn@umich.edu }; 2461049Sbinkertn@umich.edu 2471049Sbinkertn@umich.edu protected: 2481049Sbinkertn@umich.edu /** Address that the device listens to. */ 2491049Sbinkertn@umich.edu Addr pioAddr; 2501049Sbinkertn@umich.edu 2511076Sbinkertn@umich.edu /** Size that the device's address range. */ 2521049Sbinkertn@umich.edu Addr pioSize; 2531049Sbinkertn@umich.edu 2541049Sbinkertn@umich.edu /** Delay that the device experinces on an access. */ 2551049Sbinkertn@umich.edu Tick pioDelay; 2561049Sbinkertn@umich.edu 2571049Sbinkertn@umich.edu public: 2581049Sbinkertn@umich.edu BasicPioDevice(Params *p) 2591049Sbinkertn@umich.edu : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), pioDelay(p->pio_delay) 2601049Sbinkertn@umich.edu {} 2611049Sbinkertn@umich.edu 2621049Sbinkertn@umich.edu}; 2631049Sbinkertn@umich.edu 2641049Sbinkertn@umich.educlass DmaDevice : public PioDevice 2651049Sbinkertn@umich.edu{ 2661049Sbinkertn@umich.edu protected: 2671049Sbinkertn@umich.edu DmaPort *dmaPort; 2681049Sbinkertn@umich.edu 2691049Sbinkertn@umich.edu public: 2701049Sbinkertn@umich.edu DmaDevice(Params *p); 2711162Sbinkertn@umich.edu virtual ~DmaDevice(); 2721076Sbinkertn@umich.edu 2731049Sbinkertn@umich.edu virtual Port *getPort(const std::string &if_name) 2741049Sbinkertn@umich.edu { 2751049Sbinkertn@umich.edu if (if_name == "pio") 2761049Sbinkertn@umich.edu return pioPort; 2771049Sbinkertn@umich.edu else if (if_name == "dma") 2781049Sbinkertn@umich.edu return dmaPort; 2791162Sbinkertn@umich.edu else 2801049Sbinkertn@umich.edu return NULL; 2811049Sbinkertn@umich.edu } 2821049Sbinkertn@umich.edu 2831049Sbinkertn@umich.edu friend class DmaPort; 2841162Sbinkertn@umich.edu}; 2851076Sbinkertn@umich.edu 2861049Sbinkertn@umich.edu 2871049Sbinkertn@umich.edu#endif // __DEV_IO_DEVICE_HH__ 2881049Sbinkertn@umich.edu