io_device.cc revision 2626
14479Sbinkertn@umich.edu/*
24479Sbinkertn@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
34479Sbinkertn@umich.edu * All rights reserved.
44479Sbinkertn@umich.edu *
54479Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
64479Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are
74479Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright
84479Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer;
94479Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright
104479Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the
114479Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution;
124479Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its
134479Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from
144479Sbinkertn@umich.edu * this software without specific prior written permission.
154479Sbinkertn@umich.edu *
164479Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174479Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184479Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194479Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204479Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214479Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224479Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234479Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244479Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254479Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264479Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274479Sbinkertn@umich.edu */
284479Sbinkertn@umich.edu
294479Sbinkertn@umich.edu#include "dev/io_device.hh"
304479Sbinkertn@umich.edu#include "sim/builder.hh"
314479Sbinkertn@umich.edu
324479Sbinkertn@umich.edu
334479Sbinkertn@umich.eduPioPort::PioPort(PioDevice *dev, Platform *p)
344479Sbinkertn@umich.edu        : device(dev), platform(p)
354479Sbinkertn@umich.edu{ }
364479Sbinkertn@umich.edu
374479Sbinkertn@umich.edu
384479Sbinkertn@umich.eduTick
394479Sbinkertn@umich.eduPioPort::recvAtomic(Packet &pkt)
404479Sbinkertn@umich.edu{
414479Sbinkertn@umich.edu    return device->recvAtomic(pkt);
424479Sbinkertn@umich.edu}
434479Sbinkertn@umich.edu
444479Sbinkertn@umich.eduvoid
454479Sbinkertn@umich.eduPioPort::recvFunctional(Packet &pkt)
464479Sbinkertn@umich.edu{
474479Sbinkertn@umich.edu    device->recvAtomic(pkt);
484479Sbinkertn@umich.edu}
494479Sbinkertn@umich.edu
504479Sbinkertn@umich.eduvoid
514479Sbinkertn@umich.eduPioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
524479Sbinkertn@umich.edu{
534479Sbinkertn@umich.edu    snoop.clear();
544479Sbinkertn@umich.edu    device->addressRanges(resp);
554479Sbinkertn@umich.edu}
564479Sbinkertn@umich.edu
574479Sbinkertn@umich.edu
584479Sbinkertn@umich.eduPacket *
594479Sbinkertn@umich.eduPioPort::recvRetry()
604479Sbinkertn@umich.edu{
614479Sbinkertn@umich.edu    Packet* pkt = transmitList.front();
624479Sbinkertn@umich.edu    transmitList.pop_front();
634479Sbinkertn@umich.edu    return pkt;
644479Sbinkertn@umich.edu}
654479Sbinkertn@umich.edu
664479Sbinkertn@umich.edu
674479Sbinkertn@umich.eduvoid
684479Sbinkertn@umich.eduPioPort::SendEvent::process()
694479Sbinkertn@umich.edu{
704479Sbinkertn@umich.edu    if (port->Port::sendTiming(packet) == Success)
714479Sbinkertn@umich.edu        return;
724479Sbinkertn@umich.edu
734479Sbinkertn@umich.edu    port->transmitList.push_back(&packet);
744479Sbinkertn@umich.edu}
754479Sbinkertn@umich.edu
764479Sbinkertn@umich.edu
774479Sbinkertn@umich.edubool
784479Sbinkertn@umich.eduPioPort::recvTiming(Packet &pkt)
794479Sbinkertn@umich.edu{
804479Sbinkertn@umich.edu    device->recvAtomic(pkt);
814479Sbinkertn@umich.edu    sendTiming(pkt, pkt.time-pkt.req->getTime());
824479Sbinkertn@umich.edu    return Success;
834479Sbinkertn@umich.edu}
844479Sbinkertn@umich.edu
854479Sbinkertn@umich.eduPioDevice::~PioDevice()
864479Sbinkertn@umich.edu{
874479Sbinkertn@umich.edu    if (pioPort)
884479Sbinkertn@umich.edu        delete pioPort;
894479Sbinkertn@umich.edu}
904479Sbinkertn@umich.edu
914479Sbinkertn@umich.eduvoid
924479Sbinkertn@umich.eduPioDevice::init()
934479Sbinkertn@umich.edu{
944479Sbinkertn@umich.edu    if (!pioPort)
954479Sbinkertn@umich.edu        panic("Pio port not connected to anything!");
964479Sbinkertn@umich.edu    pioPort->sendStatusChange(Port::RangeChange);
974479Sbinkertn@umich.edu}
984479Sbinkertn@umich.edu
994479Sbinkertn@umich.eduvoid
1004479Sbinkertn@umich.eduBasicPioDevice::addressRanges(AddrRangeList &range_list)
1014479Sbinkertn@umich.edu{
1024479Sbinkertn@umich.edu    assert(pioSize != 0);
1034479Sbinkertn@umich.edu    range_list.clear();
1044479Sbinkertn@umich.edu    range_list.push_back(RangeSize(pioAddr, pioSize));
1054479Sbinkertn@umich.edu}
1064479Sbinkertn@umich.edu
1074479Sbinkertn@umich.edu
1084479Sbinkertn@umich.eduDmaPort::DmaPort(DmaDevice *dev, Platform *p)
1094479Sbinkertn@umich.edu        : device(dev), platform(p), pendingCount(0)
1104479Sbinkertn@umich.edu{ }
1114479Sbinkertn@umich.edu
1124479Sbinkertn@umich.edubool
1134479Sbinkertn@umich.eduDmaPort::recvTiming(Packet &pkt)
1144479Sbinkertn@umich.edu{
1154479Sbinkertn@umich.edu    if (pkt.senderState) {
1164479Sbinkertn@umich.edu        DmaReqState *state;
1174479Sbinkertn@umich.edu        state = (DmaReqState*)pkt.senderState;
1184479Sbinkertn@umich.edu        state->completionEvent->schedule(pkt.time - pkt.req->getTime());
1194479Sbinkertn@umich.edu        delete pkt.req;
1204479Sbinkertn@umich.edu        delete &pkt;
1214479Sbinkertn@umich.edu    }  else {
1224479Sbinkertn@umich.edu        delete pkt.req;
1234479Sbinkertn@umich.edu        delete &pkt;
1244479Sbinkertn@umich.edu    }
1254479Sbinkertn@umich.edu
1264479Sbinkertn@umich.edu    return Success;
1274479Sbinkertn@umich.edu}
1284479Sbinkertn@umich.edu
1294479Sbinkertn@umich.eduDmaDevice::DmaDevice(Params *p)
1304479Sbinkertn@umich.edu    : PioDevice(p), dmaPort(NULL)
1314479Sbinkertn@umich.edu{ }
1324479Sbinkertn@umich.edu
1334479Sbinkertn@umich.eduvoid
1344479Sbinkertn@umich.eduDmaPort::SendEvent::process()
1354479Sbinkertn@umich.edu{
1364479Sbinkertn@umich.edu    if (port->Port::sendTiming(packet) == Success)
1374479Sbinkertn@umich.edu        return;
1384479Sbinkertn@umich.edu
1394479Sbinkertn@umich.edu    port->transmitList.push_back(&packet);
1404479Sbinkertn@umich.edu}
1414479Sbinkertn@umich.edu
1424479Sbinkertn@umich.eduPacket *
1434479Sbinkertn@umich.eduDmaPort::recvRetry()
1444479Sbinkertn@umich.edu{
1454479Sbinkertn@umich.edu    Packet* pkt = transmitList.front();
1464479Sbinkertn@umich.edu    transmitList.pop_front();
1474479Sbinkertn@umich.edu    return pkt;
1484479Sbinkertn@umich.edu}
1494479Sbinkertn@umich.eduvoid
1504479Sbinkertn@umich.eduDmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
1514479Sbinkertn@umich.edu        uint8_t *data)
1524479Sbinkertn@umich.edu{
1534479Sbinkertn@umich.edu
1544479Sbinkertn@umich.edu    assert(event);
1554479Sbinkertn@umich.edu
1564479Sbinkertn@umich.edu    int prevSize = 0;
1574479Sbinkertn@umich.edu    Packet basePkt;
1584479Sbinkertn@umich.edu    Request baseReq(false);
1594479Sbinkertn@umich.edu
1604479Sbinkertn@umich.edu    basePkt.flags = 0;
1614479Sbinkertn@umich.edu    basePkt.coherence = NULL;
1624479Sbinkertn@umich.edu    basePkt.senderState = NULL;
1634479Sbinkertn@umich.edu    basePkt.dest = Packet::Broadcast;
1644479Sbinkertn@umich.edu    basePkt.cmd = cmd;
1654479Sbinkertn@umich.edu    basePkt.result = Unknown;
1664479Sbinkertn@umich.edu    basePkt.req = NULL;
1674479Sbinkertn@umich.edu//    baseReq.nicReq = true;
1684479Sbinkertn@umich.edu    baseReq.setTime(curTick);
1694479Sbinkertn@umich.edu
1704479Sbinkertn@umich.edu    for (ChunkGenerator gen(addr, size, peerBlockSize());
1714479Sbinkertn@umich.edu         !gen.done(); gen.next()) {
1724479Sbinkertn@umich.edu            Packet *pkt = new Packet(basePkt);
1734479Sbinkertn@umich.edu            Request *req = new Request(baseReq);
1744479Sbinkertn@umich.edu            pkt->addr = gen.addr();
1754479Sbinkertn@umich.edu            pkt->size = gen.size();
1764479Sbinkertn@umich.edu            pkt->req = req;
1774479Sbinkertn@umich.edu            pkt->req->setPaddr(pkt->addr);
1784479Sbinkertn@umich.edu            pkt->req->setSize(pkt->size);
1794479Sbinkertn@umich.edu            // Increment the data pointer on a write
1804479Sbinkertn@umich.edu            if (data)
1814479Sbinkertn@umich.edu                pkt->dataStatic(data + prevSize) ;
1824479Sbinkertn@umich.edu            prevSize += pkt->size;
1834479Sbinkertn@umich.edu            // Set the last bit of the dma as the final packet for this dma
1844479Sbinkertn@umich.edu            // and set it's completion event.
1854479Sbinkertn@umich.edu            if (prevSize == size) {
1864479Sbinkertn@umich.edu                DmaReqState *state = new DmaReqState(event, true);
1874479Sbinkertn@umich.edu
1884479Sbinkertn@umich.edu                pkt->senderState = (void*)state;
1894479Sbinkertn@umich.edu            }
1904479Sbinkertn@umich.edu            assert(pendingCount >= 0);
1914479Sbinkertn@umich.edu            pendingCount++;
1924479Sbinkertn@umich.edu            sendDma(pkt);
1934479Sbinkertn@umich.edu    }
1944479Sbinkertn@umich.edu    // since this isn't getting used and we want a check to make sure that all
1954479Sbinkertn@umich.edu    // packets had data in them at some point.
1964479Sbinkertn@umich.edu    basePkt.dataStatic((uint8_t*)NULL);
1974479Sbinkertn@umich.edu}
1984479Sbinkertn@umich.edu
1994479Sbinkertn@umich.edu
2004479Sbinkertn@umich.eduvoid
2014479Sbinkertn@umich.eduDmaPort::sendDma(Packet *pkt)
2024479Sbinkertn@umich.edu{
2034479Sbinkertn@umich.edu   // some kind of selction between access methods
2044479Sbinkertn@umich.edu   // more work is going to have to be done to make
2054479Sbinkertn@umich.edu   // switching actually work
2064479Sbinkertn@umich.edu  /* MemState state = device->platform->system->memState;
2074479Sbinkertn@umich.edu
2084479Sbinkertn@umich.edu   if (state == Timing) {
2094479Sbinkertn@umich.edu       if (sendTiming(pkt) == Failure)
2104479Sbinkertn@umich.edu           transmitList.push_back(&packet);
2114479Sbinkertn@umich.edu    } else if (state == Atomic) {*/
2124479Sbinkertn@umich.edu       sendAtomic(*pkt);
2134479Sbinkertn@umich.edu       if (pkt->senderState) {
2144479Sbinkertn@umich.edu           DmaReqState *state = (DmaReqState*)pkt->senderState;
2154479Sbinkertn@umich.edu           state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
2164479Sbinkertn@umich.edu       }
2174479Sbinkertn@umich.edu       pendingCount--;
2184479Sbinkertn@umich.edu       assert(pendingCount >= 0);
2194479Sbinkertn@umich.edu       delete pkt->req;
2204479Sbinkertn@umich.edu       delete pkt;
2214479Sbinkertn@umich.edu
2224479Sbinkertn@umich.edu/*   } else if (state == Functional) {
2234479Sbinkertn@umich.edu       sendFunctional(pkt);
2244479Sbinkertn@umich.edu       // Is this correct???
2254479Sbinkertn@umich.edu       completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
2264479Sbinkertn@umich.edu       completionEvent == NULL;
2274479Sbinkertn@umich.edu   } else
2284479Sbinkertn@umich.edu       panic("Unknown memory command state.");
2294479Sbinkertn@umich.edu  */
2304479Sbinkertn@umich.edu}
2314479Sbinkertn@umich.edu
2324479Sbinkertn@umich.eduDmaDevice::~DmaDevice()
2334479Sbinkertn@umich.edu{
2344479Sbinkertn@umich.edu    if (dmaPort)
2354479Sbinkertn@umich.edu        delete dmaPort;
2364479Sbinkertn@umich.edu}
2374479Sbinkertn@umich.edu
2384479Sbinkertn@umich.edu
2394479Sbinkertn@umich.edu