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).
This commit is contained in:
Andreas Hansson 2012-02-24 11:46:39 -05:00
parent 9e3c8de30b
commit 485d103255
9 changed files with 104 additions and 99 deletions

View file

@ -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",

View file

@ -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
{

View file

@ -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));

View file

@ -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));

View file

@ -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')

View file

@ -32,9 +32,6 @@
* @file
* Port object definitions.
*/
#include <cstring>
#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)
{

View file

@ -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 <list>
#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__

68
src/mem/port_proxy.cc Normal file
View file

@ -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;
}

View file

@ -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.