port_proxy.hh revision 14196
1955SN/A/*
2955SN/A * Copyright (c) 2011-2013, 2018 ARM Limited
311408Sandreas.sandberg@arm.com * All rights reserved
49812Sandreas.hansson@arm.com *
59812Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69812Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79812Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89812Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99812Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109812Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119812Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129812Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139812Sandreas.hansson@arm.com *
149812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
157816Ssteve.reinhardt@amd.com * modification, are permitted provided that the following conditions are
165871Snate@binkert.org * met: redistributions of source code must retain the above copyright
171762SN/A * notice, this list of conditions and the following disclaimer;
18955SN/A * redistributions in binary form must reproduce the above copyright
19955SN/A * notice, this list of conditions and the following disclaimer in the
20955SN/A * documentation and/or other materials provided with the distribution;
21955SN/A * neither the name of the copyright holders nor the names of its
22955SN/A * contributors may be used to endorse or promote products derived from
23955SN/A * this software without specific prior written permission.
24955SN/A *
25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36955SN/A *
37955SN/A * Authors: Andreas Hansson
38955SN/A */
39955SN/A
40955SN/A/**
41955SN/A * @file
422665Ssaidi@eecs.umich.edu * PortProxy Object Declaration.
432665Ssaidi@eecs.umich.edu *
445863Snate@binkert.org * Port proxies are used when non-structural entities need access to
45955SN/A * the memory system (or structural entities that want to peak into
46955SN/A * the memory system without making a real memory access).
47955SN/A *
48955SN/A * Proxy objects replace the previous FunctionalPort, TranslatingPort
49955SN/A * and VirtualPort objects, which provided the same functionality as
508878Ssteve.reinhardt@amd.com * the proxies, but were instances of ports not corresponding to real
512632Sstever@eecs.umich.edu * structural ports of the simulated system. Via the port proxies all
528878Ssteve.reinhardt@amd.com * the accesses go through an actual port (either the system port,
532632Sstever@eecs.umich.edu * e.g. for processes or initialisation, or a the data port of the
54955SN/A * CPU, e.g. for threads) and thus are transparent to a potentially
558878Ssteve.reinhardt@amd.com * distributed memory and automatically adhere to the memory map of
562632Sstever@eecs.umich.edu * the system.
572761Sstever@eecs.umich.edu */
582632Sstever@eecs.umich.edu
592632Sstever@eecs.umich.edu#ifndef __MEM_PORT_PROXY_HH__
602632Sstever@eecs.umich.edu#define __MEM_PORT_PROXY_HH__
612761Sstever@eecs.umich.edu
622761Sstever@eecs.umich.edu#include <functional>
632761Sstever@eecs.umich.edu#include <limits>
648878Ssteve.reinhardt@amd.com
658878Ssteve.reinhardt@amd.com#include "mem/port.hh"
662761Sstever@eecs.umich.edu#include "sim/byteswap.hh"
672761Sstever@eecs.umich.edu
682761Sstever@eecs.umich.edu/**
692761Sstever@eecs.umich.edu * This object is a proxy for a port or other object which implements the
702761Sstever@eecs.umich.edu * functional response protocol, to be used for debug accesses.
718878Ssteve.reinhardt@amd.com *
728878Ssteve.reinhardt@amd.com * This proxy object is used when non structural entities
732632Sstever@eecs.umich.edu * (e.g. thread contexts, object file loaders) need access to the
742632Sstever@eecs.umich.edu * memory system. It calls the corresponding functions on the underlying
758878Ssteve.reinhardt@amd.com * protocol, and provides templatized convenience access functions.
768878Ssteve.reinhardt@amd.com *
772632Sstever@eecs.umich.edu * The addresses are interpreted as physical addresses.
78955SN/A *
79955SN/A * @sa SETranslatingProxy
80955SN/A * @sa FSTranslatingProxy
815863Snate@binkert.org */
825863Snate@binkert.orgclass PortProxy : FunctionalRequestProtocol
835863Snate@binkert.org{
845863Snate@binkert.org  public:
855863Snate@binkert.org    typedef std::function<void(PacketPtr pkt)> SendFunctionalFunc;
865863Snate@binkert.org
875863Snate@binkert.org  private:
885863Snate@binkert.org    SendFunctionalFunc sendFunctional;
895863Snate@binkert.org
905863Snate@binkert.org    /** Granularity of any transactions issued through this proxy. */
915863Snate@binkert.org    const unsigned int _cacheLineSize;
928878Ssteve.reinhardt@amd.com
935863Snate@binkert.org    void
945863Snate@binkert.org    recvFunctionalSnoop(PacketPtr pkt) override
955863Snate@binkert.org    {
969812Sandreas.hansson@arm.com        // Since port proxies aren't anyone else's peer, they should never
979812Sandreas.hansson@arm.com        // receive snoops.
985863Snate@binkert.org        panic("Port proxies should never receive snoops.");
999812Sandreas.hansson@arm.com    }
1005863Snate@binkert.org
1015863Snate@binkert.org  public:
1025863Snate@binkert.org    PortProxy(SendFunctionalFunc func, unsigned int cacheLineSize) :
1039812Sandreas.hansson@arm.com        sendFunctional(func), _cacheLineSize(cacheLineSize)
1049812Sandreas.hansson@arm.com    {}
1055863Snate@binkert.org    PortProxy(const MasterPort &port, unsigned int cacheLineSize) :
1065863Snate@binkert.org        sendFunctional([&port](PacketPtr pkt)->void {
1078878Ssteve.reinhardt@amd.com                port.sendFunctional(pkt);
1085863Snate@binkert.org            }), _cacheLineSize(cacheLineSize)
1095863Snate@binkert.org    {}
1105863Snate@binkert.org    virtual ~PortProxy() { }
1116654Snate@binkert.org
11210196SCurtis.Dunham@arm.com
113955SN/A
1145396Ssaidi@eecs.umich.edu    /** Fixed functionality for use in base classes. */
11511401Sandreas.sandberg@arm.com
1165863Snate@binkert.org    /**
1175863Snate@binkert.org     * Read size bytes memory at physical address and store in p.
1184202Sbinkertn@umich.edu     */
1195863Snate@binkert.org    void readBlobPhys(Addr addr, Request::Flags flags,
1205863Snate@binkert.org                      void *p, int size) const;
1215863Snate@binkert.org
1225863Snate@binkert.org    /**
123955SN/A     * Write size bytes from p to physical address.
1246654Snate@binkert.org     */
1255273Sstever@gmail.com    void writeBlobPhys(Addr addr, Request::Flags flags,
1265871Snate@binkert.org                       const void *p, int size) const;
1275273Sstever@gmail.com
1286655Snate@binkert.org    /**
1298878Ssteve.reinhardt@amd.com     * Fill size bytes starting at physical addr with byte value val.
1306655Snate@binkert.org     */
1316655Snate@binkert.org    void memsetBlobPhys(Addr addr, Request::Flags flags,
1329219Spower.jg@gmail.com                        uint8_t v, int size) const;
1336655Snate@binkert.org
1345871Snate@binkert.org
1356654Snate@binkert.org
1368947Sandreas.hansson@arm.com    /** Methods to override in base classes */
1375396Ssaidi@eecs.umich.edu
1388120Sgblack@eecs.umich.edu    /**
1398120Sgblack@eecs.umich.edu     * Read size bytes memory at address and store in p.
1408120Sgblack@eecs.umich.edu     * Returns true on success and false on failure.
1418120Sgblack@eecs.umich.edu     */
1428120Sgblack@eecs.umich.edu    virtual bool
1438120Sgblack@eecs.umich.edu    tryReadBlob(Addr addr, void *p, int size) const
1448120Sgblack@eecs.umich.edu    {
1458120Sgblack@eecs.umich.edu        readBlobPhys(addr, 0, p, size);
1468879Ssteve.reinhardt@amd.com        return true;
1478879Ssteve.reinhardt@amd.com    }
1488879Ssteve.reinhardt@amd.com
1498879Ssteve.reinhardt@amd.com    /**
1508879Ssteve.reinhardt@amd.com     * Write size bytes from p to address.
1518879Ssteve.reinhardt@amd.com     * Returns true on success and false on failure.
1528879Ssteve.reinhardt@amd.com     */
1538879Ssteve.reinhardt@amd.com    virtual bool
1548879Ssteve.reinhardt@amd.com    tryWriteBlob(Addr addr, const void *p, int size) const
1558879Ssteve.reinhardt@amd.com    {
1568879Ssteve.reinhardt@amd.com        writeBlobPhys(addr, 0, p, size);
1578879Ssteve.reinhardt@amd.com        return true;
1588879Ssteve.reinhardt@amd.com    }
1598120Sgblack@eecs.umich.edu
1608120Sgblack@eecs.umich.edu    /**
1618120Sgblack@eecs.umich.edu     * Fill size bytes starting at addr with byte value val.
1628120Sgblack@eecs.umich.edu     * Returns true on success and false on failure.
1638120Sgblack@eecs.umich.edu     */
1648120Sgblack@eecs.umich.edu    virtual bool
1658120Sgblack@eecs.umich.edu    tryMemsetBlob(Addr addr, uint8_t val, int size) const
1668120Sgblack@eecs.umich.edu    {
1678120Sgblack@eecs.umich.edu        memsetBlobPhys(addr, 0, val, size);
1688120Sgblack@eecs.umich.edu        return true;
1698120Sgblack@eecs.umich.edu    }
1708120Sgblack@eecs.umich.edu
1718120Sgblack@eecs.umich.edu
1728120Sgblack@eecs.umich.edu
1738879Ssteve.reinhardt@amd.com    /** Higher level interfaces based on the above. */
1748879Ssteve.reinhardt@amd.com
1758879Ssteve.reinhardt@amd.com    /**
1768879Ssteve.reinhardt@amd.com     * Same as tryReadBlob, but insists on success.
17710458Sandreas.hansson@arm.com     */
17810458Sandreas.hansson@arm.com    void
17910458Sandreas.hansson@arm.com    readBlob(Addr addr, void *p, int size) const
1808879Ssteve.reinhardt@amd.com    {
1818879Ssteve.reinhardt@amd.com        if (!tryReadBlob(addr, p, size))
1828879Ssteve.reinhardt@amd.com            fatal("readBlob(%#x, ...) failed", addr);
1838879Ssteve.reinhardt@amd.com    }
1849227Sandreas.hansson@arm.com
1859227Sandreas.hansson@arm.com    /**
1868879Ssteve.reinhardt@amd.com     * Same as tryWriteBlob, but insists on success.
1878879Ssteve.reinhardt@amd.com     */
1888879Ssteve.reinhardt@amd.com    void
1898879Ssteve.reinhardt@amd.com    writeBlob(Addr addr, const void *p, int size) const
19010453SAndrew.Bardsley@arm.com    {
19110453SAndrew.Bardsley@arm.com        if (!tryWriteBlob(addr, p, size))
19210453SAndrew.Bardsley@arm.com            fatal("writeBlob(%#x, ...) failed", addr);
19310456SCurtis.Dunham@arm.com    }
19410456SCurtis.Dunham@arm.com
19510456SCurtis.Dunham@arm.com    /**
19610457Sandreas.hansson@arm.com     * Same as tryMemsetBlob, but insists on success.
19710457Sandreas.hansson@arm.com     */
19811342Sandreas.hansson@arm.com    void
19911342Sandreas.hansson@arm.com    memsetBlob(Addr addr, uint8_t v, int size) const
2008120Sgblack@eecs.umich.edu    {
2018947Sandreas.hansson@arm.com        if (!tryMemsetBlob(addr, v, size))
2027816Ssteve.reinhardt@amd.com            fatal("memsetBlob(%#x, ...) failed", addr);
2035871Snate@binkert.org    }
2045871Snate@binkert.org
2056121Snate@binkert.org    /**
2065871Snate@binkert.org     * Read sizeof(T) bytes from address and return as object T.
2075871Snate@binkert.org     */
2089926Sstan.czerniawski@arm.com    template <typename T>
2099926Sstan.czerniawski@arm.com    T read(Addr address) const;
2109119Sandreas.hansson@arm.com
21110068Sandreas.hansson@arm.com    /**
21211989Sandreas.sandberg@arm.com     * Write object T to address. Writes sizeof(T) bytes.
213955SN/A     */
2149416SAndreas.Sandberg@ARM.com    template <typename T>
21511342Sandreas.hansson@arm.com    void write(Addr address, const T &data) const;
21611212Sjoseph.gross@amd.com
21711212Sjoseph.gross@amd.com    /**
21811212Sjoseph.gross@amd.com     * Read sizeof(T) bytes from address and return as object T.
21911212Sjoseph.gross@amd.com     * Performs endianness conversion from the selected guest to host order.
22011212Sjoseph.gross@amd.com     */
2219416SAndreas.Sandberg@ARM.com    template <typename T>
2229416SAndreas.Sandberg@ARM.com    T read(Addr address, ByteOrder guest_byte_order) const;
2235871Snate@binkert.org
22410584Sandreas.hansson@arm.com    /**
2259416SAndreas.Sandberg@ARM.com     * Write object T to address. Writes sizeof(T) bytes.
2269416SAndreas.Sandberg@ARM.com     * Performs endianness conversion from host to the selected guest order.
2275871Snate@binkert.org     */
228955SN/A    template <typename T>
22910671Sandreas.hansson@arm.com    void write(Addr address, T data, ByteOrder guest_byte_order) const;
23010671Sandreas.hansson@arm.com
23110671Sandreas.hansson@arm.com    /**
23210671Sandreas.hansson@arm.com     * Write the string str into guest memory at address addr.
2338881Smarc.orr@gmail.com     * Returns true on success and false on failure.
2346121Snate@binkert.org     */
2356121Snate@binkert.org    bool tryWriteString(Addr addr, const char *str) const;
2361533SN/A
2379239Sandreas.hansson@arm.com    /**
2389239Sandreas.hansson@arm.com     * Same as tryWriteString, but insists on success.
2399239Sandreas.hansson@arm.com     */
2409239Sandreas.hansson@arm.com    void
2419239Sandreas.hansson@arm.com    writeString(Addr addr, const char *str) const
2429239Sandreas.hansson@arm.com    {
2439239Sandreas.hansson@arm.com        if (!tryWriteString(addr, str))
2446655Snate@binkert.org            fatal("writeString(%#x, ...) failed", addr);
2456655Snate@binkert.org    }
2466655Snate@binkert.org
2476655Snate@binkert.org    /**
2485871Snate@binkert.org     * Reads the string at guest address addr into the std::string str.
2495871Snate@binkert.org     * Returns true on success and false on failure.
2505863Snate@binkert.org     */
2515871Snate@binkert.org    bool tryReadString(std::string &str, Addr addr) const;
2528878Ssteve.reinhardt@amd.com
2535871Snate@binkert.org    /**
2545871Snate@binkert.org     * Same as tryReadString, but insists on success.
2555871Snate@binkert.org     */
2565863Snate@binkert.org    void
2576121Snate@binkert.org    readString(std::string &str, Addr addr) const
2585863Snate@binkert.org    {
25911408Sandreas.sandberg@arm.com        if (!tryReadString(str, addr))
26011408Sandreas.sandberg@arm.com            fatal("readString(%#x, ...) failed", addr);
2618336Ssteve.reinhardt@amd.com    }
26211469SCurtis.Dunham@arm.com
26311469SCurtis.Dunham@arm.com    /**
2648336Ssteve.reinhardt@amd.com     * Reads the string at guest address addr into the char * str, reading up
2654678Snate@binkert.org     * to maxlen characters. The last character read is always a nul
26611887Sandreas.sandberg@arm.com     * terminator. Returns true on success and false on failure.
26711887Sandreas.sandberg@arm.com     */
26811887Sandreas.sandberg@arm.com    bool tryReadString(char *str, Addr addr, size_t maxlen) const;
26911887Sandreas.sandberg@arm.com
27011887Sandreas.sandberg@arm.com    /**
27111887Sandreas.sandberg@arm.com     * Same as tryReadString, but insists on success.
27211887Sandreas.sandberg@arm.com     */
27311887Sandreas.sandberg@arm.com    void
27411887Sandreas.sandberg@arm.com    readString(char *str, Addr addr, size_t maxlen) const
27511887Sandreas.sandberg@arm.com    {
27611887Sandreas.sandberg@arm.com        if (!tryReadString(str, addr, maxlen))
27711408Sandreas.sandberg@arm.com            fatal("readString(%#x, ...) failed", addr);
27811401Sandreas.sandberg@arm.com    }
27911401Sandreas.sandberg@arm.com};
28011401Sandreas.sandberg@arm.com
28111401Sandreas.sandberg@arm.com
28211401Sandreas.sandberg@arm.comtemplate <typename T>
28311401Sandreas.sandberg@arm.comT
2848336Ssteve.reinhardt@amd.comPortProxy::read(Addr address) const
2858336Ssteve.reinhardt@amd.com{
2868336Ssteve.reinhardt@amd.com    T data;
2874678Snate@binkert.org    readBlob(address, &data, sizeof(T));
28811401Sandreas.sandberg@arm.com    return data;
2894678Snate@binkert.org}
2904678Snate@binkert.org
29111401Sandreas.sandberg@arm.comtemplate <typename T>
29211401Sandreas.sandberg@arm.comvoid
2938336Ssteve.reinhardt@amd.comPortProxy::write(Addr address, const T &data) const
2944678Snate@binkert.org{
2958336Ssteve.reinhardt@amd.com    writeBlob(address, &data, sizeof(T));
2968336Ssteve.reinhardt@amd.com}
2978336Ssteve.reinhardt@amd.com
2988336Ssteve.reinhardt@amd.comtemplate <typename T>
2998336Ssteve.reinhardt@amd.comT
3008336Ssteve.reinhardt@amd.comPortProxy::read(Addr address, ByteOrder byte_order) const
3015871Snate@binkert.org{
3025871Snate@binkert.org    T data;
3038336Ssteve.reinhardt@amd.com    readBlob(address, &data, sizeof(T));
30411408Sandreas.sandberg@arm.com    return gtoh(data, byte_order);
30511408Sandreas.sandberg@arm.com}
30611408Sandreas.sandberg@arm.com
30711408Sandreas.sandberg@arm.comtemplate <typename T>
30811408Sandreas.sandberg@arm.comvoid
30911408Sandreas.sandberg@arm.comPortProxy::write(Addr address, T data, ByteOrder byte_order) const
31011408Sandreas.sandberg@arm.com{
3118336Ssteve.reinhardt@amd.com    data = htog(data, byte_order);
31211401Sandreas.sandberg@arm.com    writeBlob(address, &data, sizeof(T));
31311401Sandreas.sandberg@arm.com}
31411401Sandreas.sandberg@arm.com
3155871Snate@binkert.org#endif // __MEM_PORT_PROXY_HH__
3168336Ssteve.reinhardt@amd.com