io_device.cc revision 2914:2c524dc023d2
17405SAli.Saidi@ARM.com/* 211573SDylan.Johnson@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147405SAli.Saidi@ARM.com * this software without specific prior written permission. 157405SAli.Saidi@ARM.com * 167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277405SAli.Saidi@ARM.com * 287405SAli.Saidi@ARM.com * Authors: Ali Saidi 297405SAli.Saidi@ARM.com * Nathan Binkert 307405SAli.Saidi@ARM.com */ 317405SAli.Saidi@ARM.com 327405SAli.Saidi@ARM.com#include "base/trace.hh" 337405SAli.Saidi@ARM.com#include "dev/io_device.hh" 347405SAli.Saidi@ARM.com#include "sim/builder.hh" 357405SAli.Saidi@ARM.com#include "sim/system.hh" 367405SAli.Saidi@ARM.com 377405SAli.Saidi@ARM.com 387405SAli.Saidi@ARM.comPioPort::PioPort(PioDevice *dev, System *s, std::string pname) 397405SAli.Saidi@ARM.com : SimpleTimingPort(dev->name() + pname), device(dev), sys(s) 407405SAli.Saidi@ARM.com{ } 417405SAli.Saidi@ARM.com 4210461SAndreas.Sandberg@ARM.com 439050Schander.sudanthi@arm.comTick 4412406Sgabeblack@google.comPioPort::recvAtomic(Packet *pkt) 4511793Sbrandon.potter@amd.com{ 468887Sgeoffrey.blake@arm.com return device->recvAtomic(pkt); 478232Snate@binkert.org} 488232Snate@binkert.org 4910844Sandreas.sandberg@arm.comvoid 509384SAndreas.Sandberg@arm.comPioPort::recvFunctional(Packet *pkt) 517678Sgblack@eecs.umich.edu{ 528059SAli.Saidi@ARM.com device->recvAtomic(pkt); 538284SAli.Saidi@ARM.com} 547405SAli.Saidi@ARM.com 557405SAli.Saidi@ARM.comvoid 567405SAli.Saidi@ARM.comPioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 577405SAli.Saidi@ARM.com{ 589384SAndreas.Sandberg@arm.com snoop.clear(); 5910461SAndreas.Sandberg@ARM.com device->addressRanges(resp); 6010461SAndreas.Sandberg@ARM.com} 6111165SRekai.GonzalezAlberquilla@arm.com 6212109SRekai.GonzalezAlberquilla@arm.com 6312479SCurtis.Dunham@arm.combool 649384SAndreas.Sandberg@arm.comPioPort::recvTiming(Packet *pkt) 6511770SCurtis.Dunham@arm.com{ 6610037SARM gem5 Developers if (pkt->result == Packet::Nacked) { 6710461SAndreas.Sandberg@ARM.com resendNacked(pkt); 6810461SAndreas.Sandberg@ARM.com } else { 6910461SAndreas.Sandberg@ARM.com Tick latency = device->recvAtomic(pkt); 7010461SAndreas.Sandberg@ARM.com // turn packet around to go back to requester 7110461SAndreas.Sandberg@ARM.com pkt->makeTimingResponse(); 7210461SAndreas.Sandberg@ARM.com sendTiming(pkt, latency); 7310609Sandreas.sandberg@arm.com } 7410609Sandreas.sandberg@arm.com return true; 7510609Sandreas.sandberg@arm.com} 7610037SARM gem5 Developers 7710037SARM gem5 DevelopersPioDevice::~PioDevice() 7810037SARM gem5 Developers{ 7910037SARM gem5 Developers if (pioPort) 8011771SCurtis.Dunham@arm.com delete pioPort; 8110037SARM gem5 Developers} 8210037SARM gem5 Developers 8310037SARM gem5 Developersvoid 8410037SARM gem5 DevelopersPioDevice::init() 8510037SARM gem5 Developers{ 8610037SARM gem5 Developers if (!pioPort) 8711771SCurtis.Dunham@arm.com panic("Pio port not connected to anything!"); 8810037SARM gem5 Developers pioPort->sendStatusChange(Port::RangeChange); 8910037SARM gem5 Developers} 9010037SARM gem5 Developers 9110037SARM gem5 Developers 9210037SARM gem5 Developersunsigned int 9312477SCurtis.Dunham@arm.comPioDevice::drain(Event *de) 9410037SARM gem5 Developers{ 9510037SARM gem5 Developers unsigned int count; 969384SAndreas.Sandberg@arm.com count = pioPort->drain(de); 979384SAndreas.Sandberg@arm.com if (count) 989384SAndreas.Sandberg@arm.com changeState(Draining); 9912479SCurtis.Dunham@arm.com else 10012479SCurtis.Dunham@arm.com changeState(Drained); 1019384SAndreas.Sandberg@arm.com return count; 1029384SAndreas.Sandberg@arm.com} 1039384SAndreas.Sandberg@arm.com 1049384SAndreas.Sandberg@arm.comvoid 1059384SAndreas.Sandberg@arm.comBasicPioDevice::addressRanges(AddrRangeList &range_list) 1069384SAndreas.Sandberg@arm.com{ 1077427Sgblack@eecs.umich.edu assert(pioSize != 0); 1087427Sgblack@eecs.umich.edu range_list.clear(); 1097427Sgblack@eecs.umich.edu range_list.push_back(RangeSize(pioAddr, pioSize)); 1109385SAndreas.Sandberg@arm.com} 1119385SAndreas.Sandberg@arm.com 1127427Sgblack@eecs.umich.edu 1137427Sgblack@eecs.umich.eduDmaPort::DmaPort(DmaDevice *dev, System *s) 11410037SARM gem5 Developers : Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0), 11510037SARM gem5 Developers actionInProgress(0), drainEvent(NULL) 11610037SARM gem5 Developers{ } 11710037SARM gem5 Developers 11810037SARM gem5 Developersbool 11910037SARM gem5 DevelopersDmaPort::recvTiming(Packet *pkt) 12010037SARM gem5 Developers{ 12110037SARM gem5 Developers 12210037SARM gem5 Developers 12310037SARM gem5 Developers if (pkt->result == Packet::Nacked) { 12410037SARM gem5 Developers DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n", 12510037SARM gem5 Developers pkt, pkt->senderState, pkt->getAddr()); 12610037SARM gem5 Developers pkt->reinitNacked(); 12710037SARM gem5 Developers sendDma(pkt, true); 1287427Sgblack@eecs.umich.edu } else if (pkt->senderState) { 1297427Sgblack@eecs.umich.edu DmaReqState *state; 1307427Sgblack@eecs.umich.edu DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x\n", 1317427Sgblack@eecs.umich.edu pkt, pkt->senderState, pkt->getAddr()); 1327427Sgblack@eecs.umich.edu state = dynamic_cast<DmaReqState*>(pkt->senderState); 1337427Sgblack@eecs.umich.edu pendingCount--; 13410037SARM gem5 Developers 13510037SARM gem5 Developers assert(pendingCount >= 0); 13610037SARM gem5 Developers assert(state); 13710037SARM gem5 Developers 1387427Sgblack@eecs.umich.edu state->numBytes += pkt->req->getSize(); 1397427Sgblack@eecs.umich.edu if (state->totBytes == state->numBytes) { 1407427Sgblack@eecs.umich.edu state->completionEvent->process(); 14110037SARM gem5 Developers delete state; 14210204SAli.Saidi@ARM.com } 14310204SAli.Saidi@ARM.com delete pkt->req; 14410037SARM gem5 Developers delete pkt; 1457427Sgblack@eecs.umich.edu 14610037SARM gem5 Developers if (pendingCount == 0 && drainEvent) { 1477427Sgblack@eecs.umich.edu drainEvent->process(); 14810037SARM gem5 Developers drainEvent = NULL; 1497427Sgblack@eecs.umich.edu } 1507427Sgblack@eecs.umich.edu } else { 15110037SARM gem5 Developers panic("Got packet without sender state... huh?\n"); 1527427Sgblack@eecs.umich.edu } 1537427Sgblack@eecs.umich.edu 1547427Sgblack@eecs.umich.edu return true; 1557427Sgblack@eecs.umich.edu} 1567427Sgblack@eecs.umich.edu 1577427Sgblack@eecs.umich.eduDmaDevice::DmaDevice(Params *p) 1587427Sgblack@eecs.umich.edu : PioDevice(p), dmaPort(NULL) 1597427Sgblack@eecs.umich.edu{ } 1607427Sgblack@eecs.umich.edu 1617427Sgblack@eecs.umich.edu 1627427Sgblack@eecs.umich.eduunsigned int 1637427Sgblack@eecs.umich.eduDmaDevice::drain(Event *de) 1647427Sgblack@eecs.umich.edu{ 1657427Sgblack@eecs.umich.edu unsigned int count; 1667427Sgblack@eecs.umich.edu count = pioPort->drain(de) + dmaPort->drain(de); 1677427Sgblack@eecs.umich.edu if (count) 1687427Sgblack@eecs.umich.edu changeState(Draining); 1697427Sgblack@eecs.umich.edu else 1707427Sgblack@eecs.umich.edu changeState(Drained); 1717427Sgblack@eecs.umich.edu return count; 1727427Sgblack@eecs.umich.edu} 1737427Sgblack@eecs.umich.edu 1747427Sgblack@eecs.umich.eduunsigned int 1757436Sdam.sunwoo@arm.comDmaPort::drain(Event *de) 1767436Sdam.sunwoo@arm.com{ 17710037SARM gem5 Developers if (pendingCount == 0) 17810037SARM gem5 Developers return 0; 1797436Sdam.sunwoo@arm.com drainEvent = de; 1807436Sdam.sunwoo@arm.com return 1; 1817436Sdam.sunwoo@arm.com} 1827436Sdam.sunwoo@arm.com 1837436Sdam.sunwoo@arm.com 1847436Sdam.sunwoo@arm.comvoid 1857436Sdam.sunwoo@arm.comDmaPort::recvRetry() 1867436Sdam.sunwoo@arm.com{ 1877436Sdam.sunwoo@arm.com Packet* pkt = transmitList.front(); 1887436Sdam.sunwoo@arm.com bool result = true; 1897436Sdam.sunwoo@arm.com while (result && transmitList.size()) { 1907436Sdam.sunwoo@arm.com DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n", 19110037SARM gem5 Developers pkt, pkt->senderState); 1927436Sdam.sunwoo@arm.com result = sendTiming(pkt); 1937436Sdam.sunwoo@arm.com if (result) { 1947436Sdam.sunwoo@arm.com DPRINTF(DMA, "-- Done\n"); 1957436Sdam.sunwoo@arm.com transmitList.pop_front(); 1967436Sdam.sunwoo@arm.com } else { 1977436Sdam.sunwoo@arm.com DPRINTF(DMA, "-- Failed, queued\n"); 1987436Sdam.sunwoo@arm.com } 1997436Sdam.sunwoo@arm.com } 2007436Sdam.sunwoo@arm.com} 2017436Sdam.sunwoo@arm.com 2027436Sdam.sunwoo@arm.com 2037436Sdam.sunwoo@arm.comvoid 2047436Sdam.sunwoo@arm.comDmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 2057436Sdam.sunwoo@arm.com uint8_t *data) 2067436Sdam.sunwoo@arm.com{ 2077436Sdam.sunwoo@arm.com assert(event); 2087644Sali.saidi@arm.com 2098147SAli.Saidi@ARM.com assert(device->getState() == SimObject::Running); 2109385SAndreas.Sandberg@arm.com 2119385SAndreas.Sandberg@arm.com DmaReqState *reqState = new DmaReqState(event, this, size); 2129385SAndreas.Sandberg@arm.com 2139385SAndreas.Sandberg@arm.com for (ChunkGenerator gen(addr, size, peerBlockSize()); 2149385SAndreas.Sandberg@arm.com !gen.done(); gen.next()) { 2159385SAndreas.Sandberg@arm.com Request *req = new Request(gen.addr(), gen.size(), 0); 2169385SAndreas.Sandberg@arm.com Packet *pkt = new Packet(req, cmd, Packet::Broadcast); 2179385SAndreas.Sandberg@arm.com 2189385SAndreas.Sandberg@arm.com // Increment the data pointer on a write 2199385SAndreas.Sandberg@arm.com if (data) 2209385SAndreas.Sandberg@arm.com pkt->dataStatic(data + gen.complete()); 2219385SAndreas.Sandberg@arm.com 2229385SAndreas.Sandberg@arm.com pkt->senderState = reqState; 2239385SAndreas.Sandberg@arm.com 22410037SARM gem5 Developers assert(pendingCount >= 0); 22510037SARM gem5 Developers pendingCount++; 22610037SARM gem5 Developers sendDma(pkt); 22710037SARM gem5 Developers } 22810037SARM gem5 Developers 22910037SARM gem5 Developers} 23010037SARM gem5 Developers 23110037SARM gem5 Developers 23210037SARM gem5 Developersvoid 23310037SARM gem5 DevelopersDmaPort::sendDma(Packet *pkt, bool front) 23410037SARM gem5 Developers{ 23510037SARM gem5 Developers // some kind of selction between access methods 23610037SARM gem5 Developers // more work is going to have to be done to make 23710037SARM gem5 Developers // switching actually work 23810037SARM gem5 Developers 23910037SARM gem5 Developers System::MemoryMode state = sys->getMemoryMode(); 2408147SAli.Saidi@ARM.com if (state == System::Timing) { 2417427Sgblack@eecs.umich.edu DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n", 2427427Sgblack@eecs.umich.edu pkt, pkt->getAddr()); 2437427Sgblack@eecs.umich.edu if (transmitList.size() || !sendTiming(pkt)) { 24410037SARM gem5 Developers if (front) 24510037SARM gem5 Developers transmitList.push_front(pkt); 24610037SARM gem5 Developers else 24710037SARM gem5 Developers transmitList.push_back(pkt); 24810037SARM gem5 Developers DPRINTF(DMA, "-- Failed: queued\n"); 24910037SARM gem5 Developers } else { 25010037SARM gem5 Developers DPRINTF(DMA, "-- Done\n"); 25110037SARM gem5 Developers } 25210037SARM gem5 Developers } else if (state == System::Atomic) { 25310037SARM gem5 Developers Tick lat; 25410037SARM gem5 Developers lat = sendAtomic(pkt); 25510037SARM gem5 Developers assert(pkt->senderState); 25610037SARM gem5 Developers DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); 25710037SARM gem5 Developers assert(state); 25810037SARM gem5 Developers 25910037SARM gem5 Developers state->numBytes += pkt->req->getSize(); 26010037SARM gem5 Developers if (state->totBytes == state->numBytes) { 26110037SARM gem5 Developers state->completionEvent->schedule(curTick + lat); 26210037SARM gem5 Developers delete state; 26310037SARM gem5 Developers delete pkt->req; 26410037SARM gem5 Developers } 26510037SARM gem5 Developers pendingCount--; 26610037SARM gem5 Developers assert(pendingCount >= 0); 26710037SARM gem5 Developers delete pkt; 26810037SARM gem5 Developers 26910037SARM gem5 Developers if (pendingCount == 0 && drainEvent) { 27010037SARM gem5 Developers drainEvent->process(); 27110037SARM gem5 Developers drainEvent = NULL; 27210037SARM gem5 Developers } 27310037SARM gem5 Developers 27410037SARM gem5 Developers } else 27510037SARM gem5 Developers panic("Unknown memory command state."); 27610037SARM gem5 Developers} 27710037SARM gem5 Developers 27810037SARM gem5 DevelopersDmaDevice::~DmaDevice() 27910037SARM gem5 Developers{ 28011770SCurtis.Dunham@arm.com if (dmaPort) 28110037SARM gem5 Developers delete dmaPort; 28211574SCurtis.Dunham@arm.com} 28311770SCurtis.Dunham@arm.com 28411770SCurtis.Dunham@arm.com 28510037SARM gem5 Developers