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