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