port_proxy.hh revision 14196
18706Sandreas.hansson@arm.com/*
212522Sandreas.sandberg@arm.com * Copyright (c) 2011-2013, 2018 ARM Limited
38706Sandreas.hansson@arm.com * All rights reserved
48706Sandreas.hansson@arm.com *
58706Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68706Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78706Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88706Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98706Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108706Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118706Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128706Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138706Sandreas.hansson@arm.com *
148706Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
158706Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
168706Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
178706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
188706Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
198706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
208706Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
218706Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
228706Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
238706Sandreas.hansson@arm.com * this software without specific prior written permission.
248706Sandreas.hansson@arm.com *
258706Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
268706Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
278706Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
288706Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
298706Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
308706Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
318706Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
328706Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
338706Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
348706Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
358706Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368706Sandreas.hansson@arm.com *
378706Sandreas.hansson@arm.com * Authors: Andreas Hansson
388706Sandreas.hansson@arm.com */
398706Sandreas.hansson@arm.com
408706Sandreas.hansson@arm.com/**
418706Sandreas.hansson@arm.com * @file
428706Sandreas.hansson@arm.com * PortProxy Object Declaration.
438706Sandreas.hansson@arm.com *
448853Sandreas.hansson@arm.com * Port proxies are used when non-structural entities need access to
458853Sandreas.hansson@arm.com * the memory system (or structural entities that want to peak into
468853Sandreas.hansson@arm.com * the memory system without making a real memory access).
478853Sandreas.hansson@arm.com *
488853Sandreas.hansson@arm.com * Proxy objects replace the previous FunctionalPort, TranslatingPort
498853Sandreas.hansson@arm.com * and VirtualPort objects, which provided the same functionality as
508853Sandreas.hansson@arm.com * the proxies, but were instances of ports not corresponding to real
518853Sandreas.hansson@arm.com * structural ports of the simulated system. Via the port proxies all
528853Sandreas.hansson@arm.com * the accesses go through an actual port (either the system port,
538853Sandreas.hansson@arm.com * e.g. for processes or initialisation, or a the data port of the
548853Sandreas.hansson@arm.com * CPU, e.g. for threads) and thus are transparent to a potentially
558706Sandreas.hansson@arm.com * distributed memory and automatically adhere to the memory map of
568706Sandreas.hansson@arm.com * the system.
578706Sandreas.hansson@arm.com */
588706Sandreas.hansson@arm.com
598706Sandreas.hansson@arm.com#ifndef __MEM_PORT_PROXY_HH__
608706Sandreas.hansson@arm.com#define __MEM_PORT_PROXY_HH__
618706Sandreas.hansson@arm.com
6214196Sgabeblack@google.com#include <functional>
6314012Sgabeblack@google.com#include <limits>
6414012Sgabeblack@google.com
658706Sandreas.hansson@arm.com#include "mem/port.hh"
668706Sandreas.hansson@arm.com#include "sim/byteswap.hh"
678706Sandreas.hansson@arm.com
688706Sandreas.hansson@arm.com/**
6914196Sgabeblack@google.com * This object is a proxy for a port or other object which implements the
7014196Sgabeblack@google.com * functional response protocol, to be used for debug accesses.
718706Sandreas.hansson@arm.com *
728706Sandreas.hansson@arm.com * This proxy object is used when non structural entities
738706Sandreas.hansson@arm.com * (e.g. thread contexts, object file loaders) need access to the
748706Sandreas.hansson@arm.com * memory system. It calls the corresponding functions on the underlying
7514196Sgabeblack@google.com * protocol, and provides templatized convenience access functions.
768706Sandreas.hansson@arm.com *
778706Sandreas.hansson@arm.com * The addresses are interpreted as physical addresses.
788706Sandreas.hansson@arm.com *
798706Sandreas.hansson@arm.com * @sa SETranslatingProxy
808706Sandreas.hansson@arm.com * @sa FSTranslatingProxy
818706Sandreas.hansson@arm.com */
8214196Sgabeblack@google.comclass PortProxy : FunctionalRequestProtocol
838706Sandreas.hansson@arm.com{
8414196Sgabeblack@google.com  public:
8514196Sgabeblack@google.com    typedef std::function<void(PacketPtr pkt)> SendFunctionalFunc;
8614196Sgabeblack@google.com
878853Sandreas.hansson@arm.com  private:
8814196Sgabeblack@google.com    SendFunctionalFunc sendFunctional;
898706Sandreas.hansson@arm.com
909814Sandreas.hansson@arm.com    /** Granularity of any transactions issued through this proxy. */
919814Sandreas.hansson@arm.com    const unsigned int _cacheLineSize;
929814Sandreas.hansson@arm.com
9314196Sgabeblack@google.com    void
9414196Sgabeblack@google.com    recvFunctionalSnoop(PacketPtr pkt) override
9514196Sgabeblack@google.com    {
9614196Sgabeblack@google.com        // Since port proxies aren't anyone else's peer, they should never
9714196Sgabeblack@google.com        // receive snoops.
9814196Sgabeblack@google.com        panic("Port proxies should never receive snoops.");
9914196Sgabeblack@google.com    }
10014196Sgabeblack@google.com
1018706Sandreas.hansson@arm.com  public:
10214196Sgabeblack@google.com    PortProxy(SendFunctionalFunc func, unsigned int cacheLineSize) :
10314196Sgabeblack@google.com        sendFunctional(func), _cacheLineSize(cacheLineSize)
10414196Sgabeblack@google.com    {}
10514196Sgabeblack@google.com    PortProxy(const MasterPort &port, unsigned int cacheLineSize) :
10614196Sgabeblack@google.com        sendFunctional([&port](PacketPtr pkt)->void {
10714196Sgabeblack@google.com                port.sendFunctional(pkt);
10814196Sgabeblack@google.com            }), _cacheLineSize(cacheLineSize)
10913893Sgabeblack@google.com    {}
1108706Sandreas.hansson@arm.com    virtual ~PortProxy() { }
1118706Sandreas.hansson@arm.com
1128706Sandreas.hansson@arm.com
1138706Sandreas.hansson@arm.com
11414008Sgabeblack@google.com    /** Fixed functionality for use in base classes. */
11512532Sandreas.sandberg@arm.com
11612532Sandreas.sandberg@arm.com    /**
11712532Sandreas.sandberg@arm.com     * Read size bytes memory at physical address and store in p.
11812532Sandreas.sandberg@arm.com     */
11912532Sandreas.sandberg@arm.com    void readBlobPhys(Addr addr, Request::Flags flags,
12014009Sgabeblack@google.com                      void *p, int size) const;
12112532Sandreas.sandberg@arm.com
12212532Sandreas.sandberg@arm.com    /**
12312532Sandreas.sandberg@arm.com     * Write size bytes from p to physical address.
12412532Sandreas.sandberg@arm.com     */
12512532Sandreas.sandberg@arm.com    void writeBlobPhys(Addr addr, Request::Flags flags,
12614009Sgabeblack@google.com                       const void *p, int size) const;
12712532Sandreas.sandberg@arm.com
12812532Sandreas.sandberg@arm.com    /**
12912532Sandreas.sandberg@arm.com     * Fill size bytes starting at physical addr with byte value val.
13012532Sandreas.sandberg@arm.com     */
13112532Sandreas.sandberg@arm.com    void memsetBlobPhys(Addr addr, Request::Flags flags,
13212532Sandreas.sandberg@arm.com                        uint8_t v, int size) const;
1338706Sandreas.hansson@arm.com
13414008Sgabeblack@google.com
13514008Sgabeblack@google.com
13614008Sgabeblack@google.com    /** Methods to override in base classes */
13714008Sgabeblack@google.com
13814008Sgabeblack@google.com    /**
13914008Sgabeblack@google.com     * Read size bytes memory at address and store in p.
14014008Sgabeblack@google.com     * Returns true on success and false on failure.
14114008Sgabeblack@google.com     */
14214008Sgabeblack@google.com    virtual bool
14314009Sgabeblack@google.com    tryReadBlob(Addr addr, void *p, int size) const
14414008Sgabeblack@google.com    {
14514008Sgabeblack@google.com        readBlobPhys(addr, 0, p, size);
14614008Sgabeblack@google.com        return true;
14714008Sgabeblack@google.com    }
14814008Sgabeblack@google.com
14914008Sgabeblack@google.com    /**
15014008Sgabeblack@google.com     * Write size bytes from p to address.
15114008Sgabeblack@google.com     * Returns true on success and false on failure.
15214008Sgabeblack@google.com     */
15314008Sgabeblack@google.com    virtual bool
15414009Sgabeblack@google.com    tryWriteBlob(Addr addr, const void *p, int size) const
15514008Sgabeblack@google.com    {
15614008Sgabeblack@google.com        writeBlobPhys(addr, 0, p, size);
15714008Sgabeblack@google.com        return true;
15814008Sgabeblack@google.com    }
15914008Sgabeblack@google.com
16014008Sgabeblack@google.com    /**
16114008Sgabeblack@google.com     * Fill size bytes starting at addr with byte value val.
16214008Sgabeblack@google.com     * Returns true on success and false on failure.
16314008Sgabeblack@google.com     */
16414008Sgabeblack@google.com    virtual bool
16514008Sgabeblack@google.com    tryMemsetBlob(Addr addr, uint8_t val, int size) const
16614008Sgabeblack@google.com    {
16714008Sgabeblack@google.com        memsetBlobPhys(addr, 0, val, size);
16814008Sgabeblack@google.com        return true;
16914008Sgabeblack@google.com    }
17014008Sgabeblack@google.com
17114008Sgabeblack@google.com
17214008Sgabeblack@google.com
17314008Sgabeblack@google.com    /** Higher level interfaces based on the above. */
17414008Sgabeblack@google.com
17514008Sgabeblack@google.com    /**
17614008Sgabeblack@google.com     * Same as tryReadBlob, but insists on success.
17714008Sgabeblack@google.com     */
17814008Sgabeblack@google.com    void
17914009Sgabeblack@google.com    readBlob(Addr addr, void *p, int size) const
18014008Sgabeblack@google.com    {
18114008Sgabeblack@google.com        if (!tryReadBlob(addr, p, size))
18214008Sgabeblack@google.com            fatal("readBlob(%#x, ...) failed", addr);
18314008Sgabeblack@google.com    }
18414008Sgabeblack@google.com
18514008Sgabeblack@google.com    /**
18614008Sgabeblack@google.com     * Same as tryWriteBlob, but insists on success.
18714008Sgabeblack@google.com     */
18814008Sgabeblack@google.com    void
18914009Sgabeblack@google.com    writeBlob(Addr addr, const void *p, int size) const
19014008Sgabeblack@google.com    {
19114008Sgabeblack@google.com        if (!tryWriteBlob(addr, p, size))
19214008Sgabeblack@google.com            fatal("writeBlob(%#x, ...) failed", addr);
19314008Sgabeblack@google.com    }
19414008Sgabeblack@google.com
19514008Sgabeblack@google.com    /**
19614008Sgabeblack@google.com     * Same as tryMemsetBlob, but insists on success.
19714008Sgabeblack@google.com     */
19814008Sgabeblack@google.com    void
19914008Sgabeblack@google.com    memsetBlob(Addr addr, uint8_t v, int size) const
20014008Sgabeblack@google.com    {
20114008Sgabeblack@google.com        if (!tryMemsetBlob(addr, v, size))
20214008Sgabeblack@google.com            fatal("memsetBlob(%#x, ...) failed", addr);
20314008Sgabeblack@google.com    }
20414008Sgabeblack@google.com
2058706Sandreas.hansson@arm.com    /**
2068706Sandreas.hansson@arm.com     * Read sizeof(T) bytes from address and return as object T.
2078706Sandreas.hansson@arm.com     */
2088706Sandreas.hansson@arm.com    template <typename T>
2098861Sandreas.hansson@arm.com    T read(Addr address) const;
2108706Sandreas.hansson@arm.com
2118706Sandreas.hansson@arm.com    /**
2128706Sandreas.hansson@arm.com     * Write object T to address. Writes sizeof(T) bytes.
2138706Sandreas.hansson@arm.com     */
2148706Sandreas.hansson@arm.com    template <typename T>
21514011Sgabeblack@google.com    void write(Addr address, const T &data) const;
2168706Sandreas.hansson@arm.com
21712522Sandreas.sandberg@arm.com    /**
21812522Sandreas.sandberg@arm.com     * Read sizeof(T) bytes from address and return as object T.
21913893Sgabeblack@google.com     * Performs endianness conversion from the selected guest to host order.
22012522Sandreas.sandberg@arm.com     */
22112522Sandreas.sandberg@arm.com    template <typename T>
22213893Sgabeblack@google.com    T read(Addr address, ByteOrder guest_byte_order) const;
22312522Sandreas.sandberg@arm.com
22412522Sandreas.sandberg@arm.com    /**
22512522Sandreas.sandberg@arm.com     * Write object T to address. Writes sizeof(T) bytes.
22613893Sgabeblack@google.com     * Performs endianness conversion from host to the selected guest order.
22712522Sandreas.sandberg@arm.com     */
22812522Sandreas.sandberg@arm.com    template <typename T>
22913893Sgabeblack@google.com    void write(Addr address, T data, ByteOrder guest_byte_order) const;
23014008Sgabeblack@google.com
23114008Sgabeblack@google.com    /**
23214008Sgabeblack@google.com     * Write the string str into guest memory at address addr.
23314008Sgabeblack@google.com     * Returns true on success and false on failure.
23414008Sgabeblack@google.com     */
23514008Sgabeblack@google.com    bool tryWriteString(Addr addr, const char *str) const;
23614008Sgabeblack@google.com
23714008Sgabeblack@google.com    /**
23814008Sgabeblack@google.com     * Same as tryWriteString, but insists on success.
23914008Sgabeblack@google.com     */
24014008Sgabeblack@google.com    void
24114008Sgabeblack@google.com    writeString(Addr addr, const char *str) const
24214008Sgabeblack@google.com    {
24314008Sgabeblack@google.com        if (!tryWriteString(addr, str))
24414008Sgabeblack@google.com            fatal("writeString(%#x, ...) failed", addr);
24514008Sgabeblack@google.com    }
24614008Sgabeblack@google.com
24714008Sgabeblack@google.com    /**
24814008Sgabeblack@google.com     * Reads the string at guest address addr into the std::string str.
24914008Sgabeblack@google.com     * Returns true on success and false on failure.
25014008Sgabeblack@google.com     */
25114008Sgabeblack@google.com    bool tryReadString(std::string &str, Addr addr) const;
25214008Sgabeblack@google.com
25314008Sgabeblack@google.com    /**
25414008Sgabeblack@google.com     * Same as tryReadString, but insists on success.
25514008Sgabeblack@google.com     */
25614008Sgabeblack@google.com    void
25714008Sgabeblack@google.com    readString(std::string &str, Addr addr) const
25814008Sgabeblack@google.com    {
25914008Sgabeblack@google.com        if (!tryReadString(str, addr))
26014008Sgabeblack@google.com            fatal("readString(%#x, ...) failed", addr);
26114008Sgabeblack@google.com    }
26214012Sgabeblack@google.com
26314012Sgabeblack@google.com    /**
26414012Sgabeblack@google.com     * Reads the string at guest address addr into the char * str, reading up
26514012Sgabeblack@google.com     * to maxlen characters. The last character read is always a nul
26614012Sgabeblack@google.com     * terminator. Returns true on success and false on failure.
26714012Sgabeblack@google.com     */
26814012Sgabeblack@google.com    bool tryReadString(char *str, Addr addr, size_t maxlen) const;
26914012Sgabeblack@google.com
27014012Sgabeblack@google.com    /**
27114012Sgabeblack@google.com     * Same as tryReadString, but insists on success.
27214012Sgabeblack@google.com     */
27314012Sgabeblack@google.com    void
27414012Sgabeblack@google.com    readString(char *str, Addr addr, size_t maxlen) const
27514012Sgabeblack@google.com    {
27614012Sgabeblack@google.com        if (!tryReadString(str, addr, maxlen))
27714012Sgabeblack@google.com            fatal("readString(%#x, ...) failed", addr);
27814012Sgabeblack@google.com    }
2798706Sandreas.hansson@arm.com};
2808706Sandreas.hansson@arm.com
2818706Sandreas.hansson@arm.com
2828706Sandreas.hansson@arm.comtemplate <typename T>
2838706Sandreas.hansson@arm.comT
2848861Sandreas.hansson@arm.comPortProxy::read(Addr address) const
2858706Sandreas.hansson@arm.com{
2868706Sandreas.hansson@arm.com    T data;
28714009Sgabeblack@google.com    readBlob(address, &data, sizeof(T));
2888706Sandreas.hansson@arm.com    return data;
2898706Sandreas.hansson@arm.com}
2908706Sandreas.hansson@arm.com
2918706Sandreas.hansson@arm.comtemplate <typename T>
2928706Sandreas.hansson@arm.comvoid
29314011Sgabeblack@google.comPortProxy::write(Addr address, const T &data) const
2948706Sandreas.hansson@arm.com{
29514009Sgabeblack@google.com    writeBlob(address, &data, sizeof(T));
2968706Sandreas.hansson@arm.com}
2978706Sandreas.hansson@arm.com
29812522Sandreas.sandberg@arm.comtemplate <typename T>
29912522Sandreas.sandberg@arm.comT
30013893Sgabeblack@google.comPortProxy::read(Addr address, ByteOrder byte_order) const
30112522Sandreas.sandberg@arm.com{
30212522Sandreas.sandberg@arm.com    T data;
30314009Sgabeblack@google.com    readBlob(address, &data, sizeof(T));
30412522Sandreas.sandberg@arm.com    return gtoh(data, byte_order);
30512522Sandreas.sandberg@arm.com}
30612522Sandreas.sandberg@arm.com
30712522Sandreas.sandberg@arm.comtemplate <typename T>
30812522Sandreas.sandberg@arm.comvoid
30913893Sgabeblack@google.comPortProxy::write(Addr address, T data, ByteOrder byte_order) const
31012522Sandreas.sandberg@arm.com{
31112522Sandreas.sandberg@arm.com    data = htog(data, byte_order);
31214009Sgabeblack@google.com    writeBlob(address, &data, sizeof(T));
31312522Sandreas.sandberg@arm.com}
31412522Sandreas.sandberg@arm.com
3158706Sandreas.hansson@arm.com#endif // __MEM_PORT_PROXY_HH__
316