/*
- * Copyright (c) 2011-2012 ARM Limited
+ * Copyright (c) 2011-2013, 2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* 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
*/
/**
#ifndef __MEM_PORT_PROXY_HH__
#define __MEM_PORT_PROXY_HH__
-#include "config/the_isa.hh"
-#if THE_ISA != NO_ISA
- #include "arch/isa_traits.hh"
-#endif
+#include <functional>
+#include <limits>
#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 port or other object which implements the
+ * functional response protocol, 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
* memory system. It calls the corresponding functions on the underlying
- * structural port, and provides templatized convenience access functions.
+ * protocol, and provides templatized convenience access functions.
*
* The addresses are interpreted as physical addresses.
*
* @sa SETranslatingProxy
* @sa FSTranslatingProxy
*/
-class PortProxy
+class PortProxy : FunctionalRequestProtocol
{
+ public:
+ typedef std::function<void(PacketPtr pkt)> SendFunctionalFunc;
+
private:
+ SendFunctionalFunc sendFunctional;
- /** The actual physical port used by this proxy. */
- MasterPort &_port;
+ /** Granularity of any transactions issued through this proxy. */
+ const unsigned int _cacheLineSize;
- void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) const;
+ void
+ recvFunctionalSnoop(PacketPtr pkt) override
+ {
+ // Since port proxies aren't anyone else's peer, they should never
+ // receive snoops.
+ panic("Port proxies should never receive snoops.");
+ }
public:
- PortProxy(MasterPort &port) : _port(port) { }
+ PortProxy(SendFunctionalFunc func, unsigned int cacheLineSize) :
+ sendFunctional(func), _cacheLineSize(cacheLineSize)
+ {}
+ PortProxy(const RequestPort &port, unsigned int cacheLineSize) :
+ sendFunctional([&port](PacketPtr pkt)->void {
+ port.sendFunctional(pkt);
+ }), _cacheLineSize(cacheLineSize)
+ {}
virtual ~PortProxy() { }
+
+
+ /** Fixed functionality for use in base classes. */
+
+ /**
+ * Read size bytes memory at physical address and store in p.
+ */
+ void readBlobPhys(Addr addr, Request::Flags flags,
+ void *p, int size) const;
+
+ /**
+ * Write size bytes from p to physical address.
+ */
+ void writeBlobPhys(Addr addr, Request::Flags flags,
+ const void *p, int size) const;
+
+ /**
+ * Fill size bytes starting at physical addr with byte value val.
+ */
+ void memsetBlobPhys(Addr addr, Request::Flags flags,
+ uint8_t v, int size) const;
+
+
+
+ /** Methods to override in base classes */
+
/**
* Read size bytes memory at address and store in p.
+ * Returns true on success and false on failure.
*/
- virtual void readBlob(Addr addr, uint8_t* p, int size) const
- { blobHelper(addr, p, size, MemCmd::ReadReq); }
+ virtual bool
+ tryReadBlob(Addr addr, void *p, int size) const
+ {
+ readBlobPhys(addr, 0, p, size);
+ return true;
+ }
/**
* Write size bytes from p to address.
+ * Returns true on success and false on failure.
*/
- virtual void writeBlob(Addr addr, uint8_t* p, int size) const
- { blobHelper(addr, p, size, MemCmd::WriteReq); }
+ virtual bool
+ tryWriteBlob(Addr addr, const void *p, int size) const
+ {
+ writeBlobPhys(addr, 0, p, size);
+ return true;
+ }
/**
* Fill size bytes starting at addr with byte value val.
+ * Returns true on success and false on failure.
+ */
+ virtual bool
+ tryMemsetBlob(Addr addr, uint8_t val, int size) const
+ {
+ memsetBlobPhys(addr, 0, val, size);
+ return true;
+ }
+
+
+
+ /** Higher level interfaces based on the above. */
+
+ /**
+ * Same as tryReadBlob, but insists on success.
*/
- virtual void memsetBlob(Addr addr, uint8_t v, int size) const;
+ void
+ readBlob(Addr addr, void *p, int size) const
+ {
+ if (!tryReadBlob(addr, p, size))
+ fatal("readBlob(%#x, ...) failed", addr);
+ }
+
+ /**
+ * Same as tryWriteBlob, but insists on success.
+ */
+ void
+ writeBlob(Addr addr, const void *p, int size) const
+ {
+ if (!tryWriteBlob(addr, p, size))
+ fatal("writeBlob(%#x, ...) failed", addr);
+ }
+
+ /**
+ * Same as tryMemsetBlob, but insists on success.
+ */
+ void
+ memsetBlob(Addr addr, uint8_t v, int size) const
+ {
+ if (!tryMemsetBlob(addr, v, size))
+ fatal("memsetBlob(%#x, ...) failed", addr);
+ }
/**
* Read sizeof(T) bytes from address and return as object T.
* Write object T to address. Writes sizeof(T) bytes.
*/
template <typename T>
- void write(Addr address, T data) const;
+ void write(Addr address, const T &data) const;
-#if THE_ISA != NO_ISA
/**
* Read sizeof(T) bytes from address and return as object T.
- * Performs Guest to Host endianness transform.
+ * Performs endianness conversion from the selected guest to host order.
*/
template <typename T>
- T readGtoH(Addr address) const;
+ T read(Addr address, ByteOrder guest_byte_order) const;
/**
* Write object T to address. Writes sizeof(T) bytes.
- * Performs Host to Guest endianness transform.
+ * Performs endianness conversion from host to the selected guest order.
*/
template <typename T>
- void writeHtoG(Addr address, T data) const;
-#endif
+ void write(Addr address, T data, ByteOrder guest_byte_order) const;
+
+ /**
+ * Write the string str into guest memory at address addr.
+ * Returns true on success and false on failure.
+ */
+ bool tryWriteString(Addr addr, const char *str) const;
+
+ /**
+ * Same as tryWriteString, but insists on success.
+ */
+ void
+ writeString(Addr addr, const char *str) const
+ {
+ if (!tryWriteString(addr, str))
+ fatal("writeString(%#x, ...) failed", addr);
+ }
+
+ /**
+ * Reads the string at guest address addr into the std::string str.
+ * Returns true on success and false on failure.
+ */
+ bool tryReadString(std::string &str, Addr addr) const;
+
+ /**
+ * Same as tryReadString, but insists on success.
+ */
+ void
+ readString(std::string &str, Addr addr) const
+ {
+ if (!tryReadString(str, addr))
+ fatal("readString(%#x, ...) failed", addr);
+ }
+
+ /**
+ * Reads the string at guest address addr into the char * str, reading up
+ * to maxlen characters. The last character read is always a nul
+ * terminator. Returns true on success and false on failure.
+ */
+ bool tryReadString(char *str, Addr addr, size_t maxlen) const;
+
+ /**
+ * Same as tryReadString, but insists on success.
+ */
+ void
+ readString(char *str, Addr addr, size_t maxlen) const
+ {
+ if (!tryReadString(str, addr, maxlen))
+ fatal("readString(%#x, ...) failed", addr);
+ }
};
PortProxy::read(Addr address) const
{
T data;
- readBlob(address, (uint8_t*)&data, sizeof(T));
+ readBlob(address, &data, sizeof(T));
return data;
}
template <typename T>
void
-PortProxy::write(Addr address, T data) const
+PortProxy::write(Addr address, const T &data) const
{
- writeBlob(address, (uint8_t*)&data, sizeof(T));
+ writeBlob(address, &data, sizeof(T));
}
-#if THE_ISA != NO_ISA
template <typename T>
T
-PortProxy::readGtoH(Addr address) const
+PortProxy::read(Addr address, ByteOrder byte_order) const
{
T data;
- readBlob(address, (uint8_t*)&data, sizeof(T));
- return TheISA::gtoh(data);
+ readBlob(address, &data, sizeof(T));
+ return gtoh(data, byte_order);
}
template <typename T>
void
-PortProxy::writeHtoG(Addr address, T data) const
+PortProxy::write(Addr address, T data, ByteOrder byte_order) const
{
- data = TheISA::htog(data);
- writeBlob(address, (uint8_t*)&data, sizeof(T));
+ data = htog(data, byte_order);
+ writeBlob(address, &data, sizeof(T));
}
-#endif
#endif // __MEM_PORT_PROXY_HH__