From 94d5cc17a29c7789c974a3f724b1c6a4c251cbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Thu, 8 Sep 2022 14:39:46 -0500 Subject: [PATCH] mem-ruby,mem-cache: ruby supports classic pfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds RubyPrefetcherProxy, which provides means to inject requests generated by the "classic" prefetchers into a SLICC prefetch queue. It defines defines notifyPf* functions to be used by protocols to notify a prefetcher. It also includes the probes required to interface with the classic implementation. AbstractController defines the accessor needed to snoop the caches. A followup patch will add support for RubyPrefetcherProxy in the CHI protocol. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Additional authors: Tuan Ta Change-Id: Ie908150b510f951cdd6fd0fd9c95d9760ff70fb0 Signed-off-by: Tiago Mück --- src/mem/ruby/SConscript | 3 +- src/mem/ruby/protocol/RubySlicc_Exports.sm | 4 +- src/mem/ruby/protocol/RubySlicc_Types.sm | 13 +- src/mem/ruby/protocol/RubySlicc_Util.sm | 3 +- .../slicc_interface/AbstractController.hh | 22 ++ .../ruby/slicc_interface/RubySlicc_Util.hh | 8 +- .../ruby/structures/RubyPrefetcherProxy.cc | 234 ++++++++++++++++++ .../ruby/structures/RubyPrefetcherProxy.hh | 178 +++++++++++++ src/mem/ruby/structures/SConscript | 3 +- src/mem/slicc/symbols/StateMachine.py | 1 + 10 files changed, 463 insertions(+), 6 deletions(-) create mode 100644 src/mem/ruby/structures/RubyPrefetcherProxy.cc create mode 100644 src/mem/ruby/structures/RubyPrefetcherProxy.hh diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 1e386f922d..5e4057fe0a 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2021 Arm Limited +# Copyright (c) 2021,2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -111,6 +111,7 @@ MakeInclude('structures/DirectoryMemory.hh') MakeInclude('structures/PerfectCacheMemory.hh') MakeInclude('structures/PersistentTable.hh') MakeInclude('structures/RubyPrefetcher.hh') +MakeInclude('structures/RubyPrefetcherProxy.hh') MakeInclude('structures/TBEStorage.hh') if env['PROTOCOL'] == 'CHI': MakeInclude('structures/MN_TBEStorage.hh') diff --git a/src/mem/ruby/protocol/RubySlicc_Exports.sm b/src/mem/ruby/protocol/RubySlicc_Exports.sm index 2e496a8221..93d374d731 100644 --- a/src/mem/ruby/protocol/RubySlicc_Exports.sm +++ b/src/mem/ruby/protocol/RubySlicc_Exports.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -51,6 +51,8 @@ external_type(Addr, primitive="yes"); external_type(Cycles, primitive="yes", default="Cycles(0)"); external_type(Tick, primitive="yes", default="0"); external_type(RequestPtr, primitive="yes", default="nullptr"); +external_type(RequestorID, primitive="yes"); +external_type(prefetch::Base, primitive="yes"); structure(WriteMask, external="yes", desc="...") { void clear(); diff --git a/src/mem/ruby/protocol/RubySlicc_Types.sm b/src/mem/ruby/protocol/RubySlicc_Types.sm index 293c731c37..2206effa29 100644 --- a/src/mem/ruby/protocol/RubySlicc_Types.sm +++ b/src/mem/ruby/protocol/RubySlicc_Types.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -259,3 +259,14 @@ structure (RubyPrefetcher, external = "yes") { void observePfHit(Addr); void observePfMiss(Addr); } + +structure(RubyPrefetcherProxy, external = "yes") { + void notifyPfHit(RequestPtr, bool, DataBlock); + void notifyPfMiss(RequestPtr, bool, DataBlock); + void notifyPfFill(RequestPtr, DataBlock, bool); + void notifyPfEvict(Addr, bool, RequestorID); + void completePrefetch(Addr); + // SLICC controller must define its own regProbePoints and call + // this for every RubyPrefetcherProxy object present + void regProbePoints(); +} diff --git a/src/mem/ruby/protocol/RubySlicc_Util.sm b/src/mem/ruby/protocol/RubySlicc_Util.sm index 3079f20f23..104c7c034c 100644 --- a/src/mem/ruby/protocol/RubySlicc_Util.sm +++ b/src/mem/ruby/protocol/RubySlicc_Util.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 ARM Limited + * Copyright (c) 2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -60,3 +60,4 @@ Addr makeNextStrideAddress(Addr addr, int stride); structure(BoolVec, external="yes") { } int countBoolVec(BoolVec bVec); +RequestorID getRequestorID(RequestPtr req); diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 72b679d6cf..ce6a6972af 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -367,6 +367,28 @@ class AbstractController : public ClockedObject, public Consumer void wakeUpAllBuffers(); bool serviceMemoryQueue(); + /** + * Functions needed by CacheAccessor. These are implemented in SLICC, + * thus the const& for all args to match the generated code. + */ + virtual bool inCache(const Addr &addr, const bool &is_secure) + { fatal("inCache: prefetching not supported"); return false; } + + virtual bool hasBeenPrefetched(const Addr &addr, const bool &is_secure) + { fatal("hasBeenPrefetched: prefetching not supported"); return false; } + + virtual bool hasBeenPrefetched(const Addr &addr, const bool &is_secure, + const RequestorID &requestor) + { fatal("hasBeenPrefetched: prefetching not supported"); return false; } + + virtual bool inMissQueue(const Addr &addr, const bool &is_secure) + { fatal("inMissQueue: prefetching not supported"); return false; } + + virtual bool coalesce() + { fatal("coalesce: prefetching not supported"); return false; } + + friend class RubyPrefetcherProxy; + protected: const NodeID m_version; MachineID m_machineID; diff --git a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh index edfbe4eea5..8df56c7013 100644 --- a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh +++ b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -316,6 +316,12 @@ countBoolVec(BoolVec bVec) return count; } +inline RequestorID +getRequestorID(RequestPtr req) +{ + return req->requestorId(); +} + } // namespace ruby } // namespace gem5 diff --git a/src/mem/ruby/structures/RubyPrefetcherProxy.cc b/src/mem/ruby/structures/RubyPrefetcherProxy.cc new file mode 100644 index 0000000000..2a29fbc88e --- /dev/null +++ b/src/mem/ruby/structures/RubyPrefetcherProxy.cc @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "mem/ruby/structures/RubyPrefetcherProxy.hh" + +#include "debug/HWPrefetch.hh" +#include "mem/ruby/system/RubySystem.hh" + +namespace gem5 +{ + +namespace ruby +{ + +RubyPrefetcherProxy::RubyPrefetcherProxy(AbstractController* _parent, + prefetch::Base* _prefetcher, + MessageBuffer *_pf_queue) + :Named(_parent->name()), + prefetcher(_prefetcher), + cacheCntrl(_parent), + pfQueue(_pf_queue), + pfEvent([this]{ issuePrefetch(); }, name()), + ppHit(nullptr), ppMiss(nullptr), + ppFill(nullptr), ppDataUpdate(nullptr) +{ + fatal_if(!cacheCntrl, + "initializing a RubyPrefetcherProxy without a parent"); + if (prefetcher) { + fatal_if(!pfQueue, + "%s initializing a RubyPrefetcherProxy without a prefetch queue", + name()); + prefetcher->setParentInfo( + cacheCntrl->params().system, + cacheCntrl->getProbeManager(), + RubySystem::getBlockSizeBytes()); + } +} + +void +RubyPrefetcherProxy::scheduleNextPrefetch() +{ + if (pfEvent.scheduled()) + return; + + Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(), + cacheCntrl->clockEdge(Cycles(1))); + if (next_pf_time != MaxTick) { + DPRINTF(HWPrefetch, "Next prefetch ready at %d\n", next_pf_time); + cacheCntrl->schedule(&pfEvent, next_pf_time); + } +} + +void +RubyPrefetcherProxy::deschedulePrefetch() +{ + if (pfEvent.scheduled()) + cacheCntrl->deschedule(&pfEvent); +} + +void +RubyPrefetcherProxy::completePrefetch(Addr addr) +{ + assert(makeLineAddress(addr) == addr); + assert(issuedPfPkts.count(addr) == 1); + DPRINTF(HWPrefetch, "Prefetch request for addr %#x completed\n", addr); + delete issuedPfPkts[addr]; + issuedPfPkts.erase(addr); +} + +void +RubyPrefetcherProxy::issuePrefetch() +{ + assert(prefetcher); + assert(pfQueue); + + if (pfQueue->areNSlotsAvailable(1, curTick())) { + PacketPtr pkt = prefetcher->getPacket(); + + if (pkt) { + DPRINTF(HWPrefetch, "Next prefetch ready %s\n", pkt->print()); + unsigned blk_size = RubySystem::getBlockSizeBytes(); + Addr line_addr = pkt->getBlockAddr(blk_size); + + if (issuedPfPkts.count(line_addr) == 0) { + DPRINTF(HWPrefetch, "Issued PF request for paddr=%#x, " + "line_addr=%#x, is_write=%d\n", + pkt->getAddr(), line_addr, + pkt->needsWritable()); + + RubyRequestType req_type = pkt->needsWritable() ? + RubyRequestType_ST : RubyRequestType_LD; + + std::shared_ptr msg = + std::make_shared(cacheCntrl->clockEdge(), + pkt->getAddr(), + blk_size, + 0, // pc + req_type, + RubyAccessMode_Supervisor, + pkt, + PrefetchBit_Yes); + + // enqueue request into prefetch queue to the cache + pfQueue->enqueue(msg, cacheCntrl->clockEdge(), + cacheCntrl->cyclesToTicks(Cycles(1))); + + // track all pending PF requests + issuedPfPkts[line_addr] = pkt; + } else { + DPRINTF(HWPrefetch, "Aborted PF request for address being " + "prefetched\n"); + delete pkt; + } + } + } else { + DPRINTF(HWPrefetch, "No prefetch slots are available\n"); + } + + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfHit(const RequestPtr& req, bool is_read, + const DataBlock& data_blk) +{ + assert(ppHit); + assert(req); + Packet pkt(req, is_read ? Packet::makeReadCmd(req) : + Packet::makeWriteCmd(req)); + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify hit: %s\n", pkt.print()); + ppHit->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfMiss(const RequestPtr& req, bool is_read, + const DataBlock& data_blk) +{ + assert(ppMiss); + assert(req); + Packet pkt(req, is_read ? Packet::makeReadCmd(req) : + Packet::makeWriteCmd(req)); + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify miss: %s\n", pkt.print()); + ppMiss->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfFill(const RequestPtr& req, + const DataBlock& data_blk, + bool from_pf) +{ + assert(ppFill); + assert(req); + Packet pkt(req, Packet::makeReadCmd(req)); + if (from_pf) + pkt.cmd = Packet::Command::HardPFReq; + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify fill: %s\n", pkt.print()); + ppFill->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfEvict(Addr blkAddr, bool hwPrefetched, + RequestorID requestorID) +{ + DPRINTF(HWPrefetch, "notify evict: %#x hw_pf=%d\n", blkAddr, hwPrefetched); + CacheDataUpdateProbeArg data_update( + blkAddr, false, requestorID, *this); + data_update.hwPrefetched = hwPrefetched; + ppDataUpdate->notify(data_update); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::regProbePoints() +{ + assert(cacheCntrl); + ppHit = new ProbePointArg( + cacheCntrl->getProbeManager(), "Hit"); + ppMiss = new ProbePointArg( + cacheCntrl->getProbeManager(), "Miss"); + ppFill = new ProbePointArg( + cacheCntrl->getProbeManager(), "Fill"); + ppDataUpdate = + new ProbePointArg( + cacheCntrl->getProbeManager(), "Data Update"); +} + +} // namespace ruby +} // namespace gem5 diff --git a/src/mem/ruby/structures/RubyPrefetcherProxy.hh b/src/mem/ruby/structures/RubyPrefetcherProxy.hh new file mode 100644 index 0000000000..34c40154b6 --- /dev/null +++ b/src/mem/ruby/structures/RubyPrefetcherProxy.hh @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ +#define __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ + +#include + +#include "mem/cache/cache_probe_arg.hh" +#include "mem/cache/prefetch/base.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/ruby/slicc_interface/RubyRequest.hh" + +namespace gem5 +{ + +namespace ruby +{ + +/** + * This is a proxy for prefetcher class in classic memory. This wrapper + * enables a SLICC machine to interact with classic prefetchers. + * + * The expected use case for this class is to instantiate it in the SLICC + * state machine definition and provide a pointer to the prefetcher object + * (typically defined in SLICC as one of the SM's configuration parameters) + * and the prefetch queue where prefetch requests will be inserted. + * + * The SLICC SM can them use the notifyPF* functions to notify the prefetcher. + * + * Notes: + * + * This object's regProbePoints() must be called explicitly. The SLICC SM may + * defined it's own regProbePoints() to call it. + * + * completePrefetch(Addr) must be called when a request injected into the + * prefetch queue is completed. + * + * A nullptr prefetcher can be provided, in which case the notifyPf* are + * no-ops. + * + */ +class RubyPrefetcherProxy : public CacheAccessor, public Named +{ + public: + + RubyPrefetcherProxy(AbstractController* parent, + prefetch::Base* prefetcher, + MessageBuffer *pf_queue); + + /** Deschedled the ready prefetch event */ + void deschedulePrefetch(); + + /** Notifies a completed prefetch request */ + void completePrefetch(Addr addr); + + /** + * Notify PF probes hit/miss/fill + */ + void notifyPfHit(const RequestPtr& req, bool is_read, + const DataBlock& data_blk); + void notifyPfMiss(const RequestPtr& req, bool is_read, + const DataBlock& data_blk); + void notifyPfFill(const RequestPtr& req, const DataBlock& data_blk, + bool from_pf); + void notifyPfEvict(Addr blkAddr, bool hwPrefetched, + RequestorID requestorID); + + /** Registers probes. */ + void regProbePoints(); + + private: + + /** Schedule the next ready prefetch */ + void scheduleNextPrefetch(); + + /** Issue prefetch to the contoller prefetch queue */ + void issuePrefetch(); + + /** Prefetcher from classic memory */ + prefetch::Base* prefetcher; + + /** Ruby cache controller */ + AbstractController* cacheCntrl; + + /** Prefetch queue to the cache controller */ + MessageBuffer* pfQueue; + + /** List of issued prefetch request packets */ + std::unordered_map issuedPfPkts; + + /** Prefetch event */ + EventFunctionWrapper pfEvent; + + /** To probe when a cache hit occurs */ + ProbePointArg *ppHit; + + /** To probe when a cache miss occurs */ + ProbePointArg *ppMiss; + + /** To probe when a cache fill occurs */ + ProbePointArg *ppFill; + + /** + * To probe when the contents of a block are updated. Content updates + * include data fills, overwrites, and invalidations, which means that + * this probe partially overlaps with other probes. + */ + ProbePointArg *ppDataUpdate; + + public: + + /** Accessor functions */ + + bool inCache(Addr addr, bool is_secure) const override + { + return cacheCntrl->inCache(addr, is_secure); + } + + bool hasBeenPrefetched(Addr addr, bool is_secure) const override + { + return cacheCntrl->hasBeenPrefetched(addr, is_secure); + } + + bool hasBeenPrefetched(Addr addr, bool is_secure, + RequestorID requestor) const override + { + return cacheCntrl->hasBeenPrefetched(addr, is_secure, requestor); + } + + bool inMissQueue(Addr addr, bool is_secure) const override + { + return cacheCntrl->inMissQueue(addr, is_secure); + } + + bool coalesce() const override + { return cacheCntrl->coalesce(); } + +}; + +} // namespace ruby +} // namespace gem5 + +#endif // __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript index cae03909c7..3a321b05f5 100644 --- a/src/mem/ruby/structures/SConscript +++ b/src/mem/ruby/structures/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2021 ARM Limited +# Copyright (c) 2021,2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -53,6 +53,7 @@ Source('CacheMemory.cc') Source('WireBuffer.cc') Source('PersistentTable.cc') Source('RubyPrefetcher.cc') +Source('RubyPrefetcherProxy.cc') Source('TimerTable.cc') Source('BankedArray.cc') Source('TBEStorage.cc') diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 68a1a6a8af..4910c55ce6 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -63,6 +63,7 @@ python_class_map = { "MessageBuffer": "MessageBuffer", "DMASequencer": "DMASequencer", "RubyPrefetcher": "RubyPrefetcher", + "prefetch::Base": "BasePrefetcher", "Cycles": "Cycles", "Addr": "Addr", }