io_device.cc revision 2542
16691Stjones1@inf.ed.ac.uk/*
26691Stjones1@inf.ed.ac.uk * Copyright (c) 2006 The Regents of The University of Michigan
36691Stjones1@inf.ed.ac.uk * All rights reserved.
46691Stjones1@inf.ed.ac.uk *
56691Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without
66691Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are
76691Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright
86691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer;
96691Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright
106691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the
116691Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution;
126691Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its
136691Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from
146691Stjones1@inf.ed.ac.uk * this software without specific prior written permission.
156691Stjones1@inf.ed.ac.uk *
166691Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176691Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186691Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196691Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206691Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216691Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226691Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236691Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246691Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256691Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266691Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276691Stjones1@inf.ed.ac.uk */
286691Stjones1@inf.ed.ac.uk
296691Stjones1@inf.ed.ac.uk#include "dev/io_device.hh"
306691Stjones1@inf.ed.ac.uk#include "sim/builder.hh"
316691Stjones1@inf.ed.ac.uk
326691Stjones1@inf.ed.ac.uk
336691Stjones1@inf.ed.ac.ukPioPort::PioPort(PioDevice *dev, Platform *p)
346691Stjones1@inf.ed.ac.uk        : device(dev), platform(p)
356691Stjones1@inf.ed.ac.uk{ }
366691Stjones1@inf.ed.ac.uk
376691Stjones1@inf.ed.ac.uk
386691Stjones1@inf.ed.ac.ukTick
396691Stjones1@inf.ed.ac.ukPioPort::recvAtomic(Packet &pkt)
406691Stjones1@inf.ed.ac.uk{
416691Stjones1@inf.ed.ac.uk    return device->recvAtomic(pkt);
426691Stjones1@inf.ed.ac.uk}
436691Stjones1@inf.ed.ac.uk
446691Stjones1@inf.ed.ac.ukvoid
456691Stjones1@inf.ed.ac.ukPioPort::recvFunctional(Packet &pkt)
466691Stjones1@inf.ed.ac.uk{
476691Stjones1@inf.ed.ac.uk    device->recvAtomic(pkt);
486691Stjones1@inf.ed.ac.uk}
496691Stjones1@inf.ed.ac.uk
506691Stjones1@inf.ed.ac.ukvoid
516691Stjones1@inf.ed.ac.ukPioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
526691Stjones1@inf.ed.ac.uk{
536691Stjones1@inf.ed.ac.uk    snoop.clear();
546691Stjones1@inf.ed.ac.uk    device->addressRanges(resp);
556691Stjones1@inf.ed.ac.uk}
566691Stjones1@inf.ed.ac.uk
576691Stjones1@inf.ed.ac.uk
586691Stjones1@inf.ed.ac.ukPacket *
596691Stjones1@inf.ed.ac.ukPioPort::recvRetry()
606691Stjones1@inf.ed.ac.uk{
616691Stjones1@inf.ed.ac.uk    Packet* pkt = transmitList.front();
626691Stjones1@inf.ed.ac.uk    transmitList.pop_front();
636691Stjones1@inf.ed.ac.uk    return pkt;
646691Stjones1@inf.ed.ac.uk}
656691Stjones1@inf.ed.ac.uk
666691Stjones1@inf.ed.ac.uk
676691Stjones1@inf.ed.ac.ukvoid
686691Stjones1@inf.ed.ac.ukPioPort::SendEvent::process()
696691Stjones1@inf.ed.ac.uk{
706691Stjones1@inf.ed.ac.uk    if (port->Port::sendTiming(packet) == Success)
716691Stjones1@inf.ed.ac.uk        return;
726691Stjones1@inf.ed.ac.uk
736691Stjones1@inf.ed.ac.uk    port->transmitList.push_back(&packet);
746691Stjones1@inf.ed.ac.uk}
756691Stjones1@inf.ed.ac.uk
766691Stjones1@inf.ed.ac.uk
776691Stjones1@inf.ed.ac.ukbool
786691Stjones1@inf.ed.ac.ukPioPort::recvTiming(Packet &pkt)
796691Stjones1@inf.ed.ac.uk{
806691Stjones1@inf.ed.ac.uk    device->recvAtomic(pkt);
816691Stjones1@inf.ed.ac.uk    sendTiming(pkt, pkt.time-pkt.req->getTime());
826691Stjones1@inf.ed.ac.uk    return Success;
836691Stjones1@inf.ed.ac.uk}
846691Stjones1@inf.ed.ac.uk
856691Stjones1@inf.ed.ac.ukPioDevice::~PioDevice()
866691Stjones1@inf.ed.ac.uk{
876691Stjones1@inf.ed.ac.uk    if (pioPort)
886691Stjones1@inf.ed.ac.uk        delete pioPort;
896691Stjones1@inf.ed.ac.uk}
906691Stjones1@inf.ed.ac.uk
916691Stjones1@inf.ed.ac.ukvoid
926691Stjones1@inf.ed.ac.ukPioDevice::init()
936691Stjones1@inf.ed.ac.uk{
946691Stjones1@inf.ed.ac.uk    if (!pioPort)
956691Stjones1@inf.ed.ac.uk        panic("Pio port not connected to anything!");
966691Stjones1@inf.ed.ac.uk    pioPort->sendStatusChange(Port::RangeChange);
976691Stjones1@inf.ed.ac.uk}
986691Stjones1@inf.ed.ac.uk
996691Stjones1@inf.ed.ac.ukvoid
1006691Stjones1@inf.ed.ac.ukBasicPioDevice::addressRanges(AddrRangeList &range_list)
1016691Stjones1@inf.ed.ac.uk{
1026691Stjones1@inf.ed.ac.uk    assert(pioSize != 0);
1036691Stjones1@inf.ed.ac.uk    range_list.clear();
1046691Stjones1@inf.ed.ac.uk    range_list.push_back(RangeSize(pioAddr, pioSize));
1056691Stjones1@inf.ed.ac.uk}
1066691Stjones1@inf.ed.ac.uk
1076691Stjones1@inf.ed.ac.uk
1086691Stjones1@inf.ed.ac.ukDmaPort::DmaPort(DmaDevice *dev)
1096691Stjones1@inf.ed.ac.uk        : device(dev)
1106691Stjones1@inf.ed.ac.uk{ }
1116691Stjones1@inf.ed.ac.uk
1126691Stjones1@inf.ed.ac.ukbool
1136691Stjones1@inf.ed.ac.ukDmaPort::recvTiming(Packet &pkt)
1146691Stjones1@inf.ed.ac.uk{
1156691Stjones1@inf.ed.ac.uk    completionEvent->schedule(curTick+1);
1166691Stjones1@inf.ed.ac.uk    completionEvent = NULL;
1176691Stjones1@inf.ed.ac.uk    return Success;
1186691Stjones1@inf.ed.ac.uk}
1196691Stjones1@inf.ed.ac.uk
1206691Stjones1@inf.ed.ac.ukDmaDevice::DmaDevice(Params *p)
1216691Stjones1@inf.ed.ac.uk    : PioDevice(p)
1226691Stjones1@inf.ed.ac.uk{
1236691Stjones1@inf.ed.ac.uk    dmaPort = new DmaPort(this);
1246691Stjones1@inf.ed.ac.uk}
1256691Stjones1@inf.ed.ac.uk
1266691Stjones1@inf.ed.ac.ukvoid
1276691Stjones1@inf.ed.ac.ukDmaPort::SendEvent::process()
1286691Stjones1@inf.ed.ac.uk{
1296691Stjones1@inf.ed.ac.uk    if (port->Port::sendTiming(packet) == Success)
1306691Stjones1@inf.ed.ac.uk        return;
1316691Stjones1@inf.ed.ac.uk
1326691Stjones1@inf.ed.ac.uk    port->transmitList.push_back(&packet);
1336691Stjones1@inf.ed.ac.uk}
1346691Stjones1@inf.ed.ac.uk
1356691Stjones1@inf.ed.ac.ukPacket *
1366691Stjones1@inf.ed.ac.ukDmaPort::recvRetry()
1376691Stjones1@inf.ed.ac.uk{
1386691Stjones1@inf.ed.ac.uk    Packet* pkt = transmitList.front();
1396691Stjones1@inf.ed.ac.uk    transmitList.pop_front();
1406691Stjones1@inf.ed.ac.uk    return pkt;
1416691Stjones1@inf.ed.ac.uk}
1426691Stjones1@inf.ed.ac.ukvoid
1436691Stjones1@inf.ed.ac.ukDmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
1446691Stjones1@inf.ed.ac.uk                     Event *event, uint8_t *data)
1456691Stjones1@inf.ed.ac.uk{
1466691Stjones1@inf.ed.ac.uk
1476691Stjones1@inf.ed.ac.uk    assert(event);
1486691Stjones1@inf.ed.ac.uk
1496691Stjones1@inf.ed.ac.uk    int prevSize = 0;
1506691Stjones1@inf.ed.ac.uk    Packet basePkt;
1516691Stjones1@inf.ed.ac.uk    Request baseReq(false);
1526691Stjones1@inf.ed.ac.uk
1536691Stjones1@inf.ed.ac.uk    basePkt.flags = 0;
1546691Stjones1@inf.ed.ac.uk    basePkt.coherence = NULL;
1556691Stjones1@inf.ed.ac.uk    basePkt.senderState = NULL;
1566691Stjones1@inf.ed.ac.uk    basePkt.src = 0;
1576691Stjones1@inf.ed.ac.uk    basePkt.dest = 0;
1586691Stjones1@inf.ed.ac.uk    basePkt.cmd = cmd;
1596691Stjones1@inf.ed.ac.uk    basePkt.result = Unknown;
1606691Stjones1@inf.ed.ac.uk    basePkt.req = NULL;
1616691Stjones1@inf.ed.ac.uk//    baseReq.nicReq = true;
1626691Stjones1@inf.ed.ac.uk    baseReq.setTime(curTick);
1636691Stjones1@inf.ed.ac.uk
1646691Stjones1@inf.ed.ac.uk    completionEvent = event;
1656691Stjones1@inf.ed.ac.uk
1666691Stjones1@inf.ed.ac.uk    for (ChunkGenerator gen(addr, size, peerBlockSize());
1676691Stjones1@inf.ed.ac.uk         !gen.done(); gen.next()) {
1686691Stjones1@inf.ed.ac.uk            Packet *pkt = new Packet(basePkt);
1696691Stjones1@inf.ed.ac.uk            Request *req = new Request(baseReq);
1706691Stjones1@inf.ed.ac.uk            pkt->addr = gen.addr();
1716691Stjones1@inf.ed.ac.uk            pkt->size = gen.size();
1726691Stjones1@inf.ed.ac.uk            pkt->req = req;
1736691Stjones1@inf.ed.ac.uk            pkt->req->setPaddr(pkt->addr);
1746691Stjones1@inf.ed.ac.uk            pkt->req->setSize(pkt->size);
1756691Stjones1@inf.ed.ac.uk            // Increment the data pointer on a write
1766691Stjones1@inf.ed.ac.uk            pkt->data = data ? data + prevSize : NULL ;
1776691Stjones1@inf.ed.ac.uk            prevSize += pkt->size;
1786691Stjones1@inf.ed.ac.uk
1796691Stjones1@inf.ed.ac.uk            sendDma(*pkt);
1806691Stjones1@inf.ed.ac.uk    }
1816691Stjones1@inf.ed.ac.uk}
1826691Stjones1@inf.ed.ac.uk
1836691Stjones1@inf.ed.ac.uk
1846691Stjones1@inf.ed.ac.ukvoid
1856691Stjones1@inf.ed.ac.ukDmaPort::sendDma(Packet &pkt)
1866691Stjones1@inf.ed.ac.uk{
1876691Stjones1@inf.ed.ac.uk   // some kind of selction between access methods
1886691Stjones1@inf.ed.ac.uk   // more work is going to have to be done to make
1896691Stjones1@inf.ed.ac.uk   // switching actually work
1906691Stjones1@inf.ed.ac.uk  /* MemState state = device->platform->system->memState;
1916691Stjones1@inf.ed.ac.uk
1926691Stjones1@inf.ed.ac.uk   if (state == Timing) {
1936691Stjones1@inf.ed.ac.uk       if (sendTiming(pkt) == Failure)
1946691Stjones1@inf.ed.ac.uk           transmitList.push_back(&packet);
1956691Stjones1@inf.ed.ac.uk   } else if (state == Atomic) {*/
1966691Stjones1@inf.ed.ac.uk       sendAtomic(pkt);
1976691Stjones1@inf.ed.ac.uk       completionEvent->schedule(pkt.time - pkt.req->getTime());
1986691Stjones1@inf.ed.ac.uk       completionEvent = NULL;
1996691Stjones1@inf.ed.ac.uk/*   } else if (state == Functional) {
2006691Stjones1@inf.ed.ac.uk       sendFunctional(pkt);
2016691Stjones1@inf.ed.ac.uk       // Is this correct???
2026691Stjones1@inf.ed.ac.uk       completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
2036691Stjones1@inf.ed.ac.uk       completionEvent == NULL;
2046691Stjones1@inf.ed.ac.uk   } else
2056691Stjones1@inf.ed.ac.uk       panic("Unknown memory command state.");
2066691Stjones1@inf.ed.ac.uk  */
2076691Stjones1@inf.ed.ac.uk}
2086691Stjones1@inf.ed.ac.uk
2096691Stjones1@inf.ed.ac.ukDmaDevice::~DmaDevice()
2106691Stjones1@inf.ed.ac.uk{
2116691Stjones1@inf.ed.ac.uk    if (dmaPort)
2126691Stjones1@inf.ed.ac.uk        delete dmaPort;
2136691Stjones1@inf.ed.ac.uk}
2146691Stjones1@inf.ed.ac.uk
2156691Stjones1@inf.ed.ac.uk
2166691Stjones1@inf.ed.ac.uk