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