From: Andreas Hansson Date: Fri, 24 Feb 2012 16:46:39 +0000 (-0500) Subject: MEM: Move all read/write blob functions from Port to PortProxy X-Git-Tag: stable_2012_06_28~220 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=485d103255c0f64ebf697650c899fe7a80db1d6d;p=gem5.git MEM: Move all read/write blob functions from Port to PortProxy This patch moves the readBlob/writeBlob/memsetBlob from the Port class to the PortProxy class, thus making a clear separation of the basic port functionality (recv/send functional/atomic/timing), and the higher-level functional accessors available on the port proxies. There are only a few places in the code base where the blob functions were used on ports, and they are all for peeking into the memory system without making a normal memory access (in the memtest, and the malta and tsunami pchip). The memtest also exemplifies how easy it is to create a non-translating proxy if desired. The malta and tsunami pchip used a slave port to perform a functional read, and this is now changed to rely on the physProxy of the system (to which they already have a pointer). --- diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index 2d0131a92..dffaa71ed 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -125,6 +125,7 @@ MemTest::MemTest(const Params *p) tickEvent(this), cachePort("test", this), funcPort("functional", this), + funcProxy(funcPort), retryPkt(NULL), // mainMem(main_mem), // checkMem(check_mem), @@ -237,7 +238,7 @@ MemTest::completeRequest(PacketPtr pkt) exitSimLoop("maximum number of loads reached"); } else { assert(pkt->isWrite()); - funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize()); + funcProxy.writeBlob(req->getPaddr(), pkt_data, req->getSize()); numWrites++; numWritesStat++; } @@ -349,7 +350,7 @@ MemTest::tick() outstandingAddrs.insert(paddr); // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin - funcPort.readBlob(req->getPaddr(), result, req->getSize()); + funcProxy.readBlob(req->getPaddr(), result, req->getSize()); DPRINTF(MemTest, "id %d initiating %sread at addr %x (blk %x) expecting %x\n", diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 208b34caf..c56a37574 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -38,6 +38,7 @@ #include "base/statistics.hh" #include "mem/mem_object.hh" #include "mem/port.hh" +#include "mem/port_proxy.hh" #include "params/MemTest.hh" #include "sim/eventq.hh" #include "sim/sim_exit.hh" @@ -108,6 +109,7 @@ class MemTest : public MemObject CpuPort cachePort; CpuPort funcPort; + PortProxy funcProxy; class MemTestSenderState : public Packet::SenderState, public FastAlloc { diff --git a/src/dev/alpha/tsunami_pchip.cc b/src/dev/alpha/tsunami_pchip.cc index f49f1e6b6..fcd06c582 100644 --- a/src/dev/alpha/tsunami_pchip.cc +++ b/src/dev/alpha/tsunami_pchip.cc @@ -284,8 +284,8 @@ TsunamiPChip::translatePciToDma(Addr busAddr) baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); - pioPort.readBlob(pteAddr, (uint8_t*)&pteEntry, - sizeof(uint64_t)); + sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry, + sizeof(uint64_t)); dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); diff --git a/src/dev/mips/malta_pchip.cc b/src/dev/mips/malta_pchip.cc index fe00f98dd..076fdfe84 100755 --- a/src/dev/mips/malta_pchip.cc +++ b/src/dev/mips/malta_pchip.cc @@ -283,8 +283,8 @@ MaltaPChip::translatePciToDma(Addr busAddr) baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); - pioPort.readBlob(pteAddr, (uint8_t*)&pteEntry, - sizeof(uint64_t)); + sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry, + sizeof(uint64_t)); dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); diff --git a/src/mem/SConscript b/src/mem/SConscript index 09cc93c77..fe43f71be 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -41,6 +41,7 @@ Source('mport.cc') Source('packet.cc') Source('port.cc') Source('tport.cc') +Source('port_proxy.cc') Source('fs_translating_port_proxy.cc') Source('se_translating_port_proxy.cc') diff --git a/src/mem/port.cc b/src/mem/port.cc index e489b9d7a..8edca16f7 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -32,9 +32,6 @@ * @file * Port object definitions. */ -#include - -#include "base/chunk_generator.hh" #include "base/trace.hh" #include "debug/Config.hh" #include "mem/mem_object.hh" @@ -63,46 +60,6 @@ Port::setOwner(MemObject *_owner) owner = _owner; } -void -Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) -{ - Request req; - - for (ChunkGenerator gen(addr, size, peerBlockSize()); - !gen.done(); gen.next()) { - req.setPhys(gen.addr(), gen.size(), 0, Request::funcMasterId); - Packet pkt(&req, cmd, Packet::Broadcast); - pkt.dataStatic(p); - sendFunctional(&pkt); - p += gen.size(); - } -} - -void -Port::writeBlob(Addr addr, uint8_t *p, int size) -{ - blobHelper(addr, p, size, MemCmd::WriteReq); -} - -void -Port::readBlob(Addr addr, uint8_t *p, int size) -{ - blobHelper(addr, p, size, MemCmd::ReadReq); -} - -void -Port::memsetBlob(Addr addr, uint8_t val, int size) -{ - // quick and dirty... - uint8_t *buf = new uint8_t[size]; - - std::memset(buf, val, size); - blobHelper(addr, buf, size, MemCmd::WriteReq); - - delete [] buf; -} - - void Port::printAddr(Addr a) { diff --git a/src/mem/port.hh b/src/mem/port.hh index 98b3ad5f1..fef0c839d 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -38,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ron Dreslinski + * Andreas Hansson */ /** @@ -54,11 +55,8 @@ #include -#include "base/misc.hh" #include "base/range.hh" -#include "base/types.hh" #include "mem/packet.hh" -#include "mem/request.hh" /** This typedef is used to clean up getAddrRanges(). It's declared * outside the Port object since it's also used by some mem objects. @@ -227,37 +225,10 @@ class Port */ unsigned peerBlockSize() const { return peer->deviceBlockSize(); } - /** This function is a wrapper around sendFunctional() - that breaks a larger, arbitrarily aligned access into - appropriate chunks. The default implementation can use - getBlockSize() to determine the block size and go from there. - */ - virtual void readBlob(Addr addr, uint8_t *p, int size); - - /** This function is a wrapper around sendFunctional() - that breaks a larger, arbitrarily aligned access into - appropriate chunks. The default implementation can use - getBlockSize() to determine the block size and go from there. - */ - virtual void writeBlob(Addr addr, uint8_t *p, int size); - - /** Fill size bytes starting at addr with byte value val. This - should not need to be virtual, since it can be implemented in - terms of writeBlob(). However, it shouldn't be - performance-critical either, so it could be if we wanted to. - */ - virtual void memsetBlob(Addr addr, uint8_t val, int size); - /** Inject a PrintReq for the given address to print the state of * that address throughout the memory system. For debugging. */ void printAddr(Addr a); - - private: - - /** Internal helper function for read/writeBlob(). - */ - void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); }; #endif //__MEM_PORT_HH__ diff --git a/src/mem/port_proxy.cc b/src/mem/port_proxy.cc new file mode 100644 index 000000000..ac6ec2465 --- /dev/null +++ b/src/mem/port_proxy.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Hansson + */ + +#include "base/chunk_generator.hh" +#include "mem/port_proxy.hh" + +void +PortProxy::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) +{ + Request req; + + for (ChunkGenerator gen(addr, size, _port.peerBlockSize()); + !gen.done(); gen.next()) { + req.setPhys(gen.addr(), gen.size(), 0, Request::funcMasterId); + Packet pkt(&req, cmd, Packet::Broadcast); + pkt.dataStatic(p); + _port.sendFunctional(&pkt); + p += gen.size(); + } +} + +void +PortProxy::memsetBlob(Addr addr, uint8_t v, int size) +{ + // quick and dirty... + uint8_t *buf = new uint8_t[size]; + + std::memset(buf, v, size); + blobHelper(addr, buf, size, MemCmd::WriteReq); + + delete [] buf; +} diff --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh index 31ad4c1cd..d6ff4d68d 100644 --- a/src/mem/port_proxy.hh +++ b/src/mem/port_proxy.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -41,13 +41,17 @@ * @file * PortProxy Object Declaration. * - * Port proxies are used when non structural entities need access to - * the memory system. Proxy objects replace the previous - * FunctionalPort, TranslatingPort and VirtualPort objects, which - * provided the same functionality as the proxies, but were instances - * of ports not corresponding to real structural ports of the - * simulated system. Via the port proxies all the accesses go through - * an actual port and thus are transparent to a potentially + * Port proxies are used when non-structural entities need access to + * the memory system (or structural entities that want to peak into + * the memory system without making a real memory access). + * + * Proxy objects replace the previous FunctionalPort, TranslatingPort + * and VirtualPort objects, which provided the same functionality as + * the proxies, but were instances of ports not corresponding to real + * structural ports of the simulated system. Via the port proxies all + * the accesses go through an actual port (either the system port, + * e.g. for processes or initialisation, or a the data port of the + * CPU, e.g. for threads) and thus are transparent to a potentially * distributed memory and automatically adhere to the memory map of * the system. */ @@ -60,13 +64,12 @@ #include "arch/isa_traits.hh" #endif -#include "base/types.hh" #include "mem/port.hh" #include "sim/byteswap.hh" /** - * This object is a proxy for a structural port, - * to be used for debug accesses. + * This object is a proxy for a structural port, to be used for debug + * accesses. * * This proxy object is used when non structural entities * (e.g. thread contexts, object file loaders) need access to the @@ -80,31 +83,33 @@ */ class PortProxy { - protected: + private: + + /** The actual physical port used by this proxy. */ Port &_port; + void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); + public: PortProxy(Port &port) : _port(port) { } virtual ~PortProxy() { } - public: /** * Read size bytes memory at address and store in p. */ - virtual void readBlob(Addr address, uint8_t* p, int size) - { _port.readBlob(address, p, size); } + virtual void readBlob(Addr addr, uint8_t* p, int size) + { blobHelper(addr, p, size, MemCmd::ReadReq); } /** * Write size bytes from p to address. */ - virtual void writeBlob(Addr address, uint8_t* p, int size) - { _port.writeBlob(address, p, size); } + virtual void writeBlob(Addr addr, uint8_t* p, int size) + { blobHelper(addr, p, size, MemCmd::WriteReq); } /** * Fill size bytes starting at addr with byte value val. */ - virtual void memsetBlob(Addr address, uint8_t v, int size) - { _port.memsetBlob(address, v, size); } + virtual void memsetBlob(Addr addr, uint8_t v, int size); /** * Read sizeof(T) bytes from address and return as object T.