/*
+ * Copyright (c) 2020 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.
+ *
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved.
*
struct MachineID
{
- MachineID() : type(MachineType_NULL), num(0) { }
+ MachineID() : type(MachineType_NUM), num(0) { }
MachineID(MachineType mach_type, NodeID node_id)
: type(mach_type), num(node_id) { }
MachineType getType() const { return type; }
NodeID getNum() const { return num; }
+
+ bool isValid() const { return type != MachineType_NUM; }
};
inline std::string
/*
- * Copyright (c) 2017,2019 ARM Limited
+ * Copyright (c) 2017,2019,2020 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
if (getMemReqQueue()) {
getMemReqQueue()->setConsumer(this);
}
+
+ // Initialize the addr->downstream machine mappings. Multiple machines
+ // in downstream_destinations can have the same address range if they have
+ // different types. If this is the case, mapAddressToDownstreamMachine
+ // needs to specify the machine type
+ downstreamDestinations.resize();
+ for (auto abs_cntrl : params()->downstream_destinations) {
+ MachineID mid = abs_cntrl->getMachineID();
+ const AddrRangeList &ranges = abs_cntrl->getAddrRanges();
+ for (const auto addr_range : ranges) {
+ auto i = downstreamAddrMap.intersects(addr_range);
+ if (i == downstreamAddrMap.end()) {
+ i = downstreamAddrMap.insert(addr_range, AddrMapEntry());
+ }
+ AddrMapEntry &entry = i->second;
+ fatal_if(entry.count(mid.getType()) > 0,
+ "%s: %s mapped to multiple machines of the same type\n",
+ name(), addr_range.to_string());
+ entry[mid.getType()] = mid;
+ }
+ downstreamDestinations.add(mid);
+ }
+
}
void
return mach;
}
+MachineID
+AbstractController::mapAddressToDownstreamMachine(Addr addr, MachineType mtype)
+const
+{
+ const auto i = downstreamAddrMap.contains(addr);
+ fatal_if(i == downstreamAddrMap.end(),
+ "%s: couldn't find mapping for address %x\n", name(), addr);
+
+ const AddrMapEntry &entry = i->second;
+ assert(!entry.empty());
+
+ if (mtype == MachineType_NUM) {
+ fatal_if(entry.size() > 1,
+ "%s: address %x mapped to multiple machine types.\n", name(), addr);
+ return entry.begin()->second;
+ } else {
+ auto j = entry.find(mtype);
+ fatal_if(j == entry.end(),
+ "%s: couldn't find mapping for address %x\n", name(), addr);
+ return j->second;
+ }
+}
+
+
bool
AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt)
{
/*
- * Copyright (c) 2017,2019 ARM Limited
+ * Copyright (c) 2017,2019,2020 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include <exception>
#include <iostream>
#include <string>
+#include <unordered_map>
#include "base/addr_range.hh"
+#include "base/addr_range_map.hh"
#include "base/callback.hh"
#include "mem/packet.hh"
#include "mem/qport.hh"
*/
MachineID mapAddressToMachine(Addr addr, MachineType mtype) const;
+ /**
+ * Maps an address to the correct dowstream MachineID (i.e. the component
+ * in the next level of the cache hierarchy towards memory)
+ *
+ * This function uses the local list of possible destinations instead of
+ * querying the network.
+ *
+ * @param the destination address
+ * @param the type of the destination (optional)
+ * @return the MachineID of the destination
+ */
+ MachineID mapAddressToDownstreamMachine(Addr addr,
+ MachineType mtype = MachineType_NUM) const;
+
+ const NetDest& allDownstreamDest() const { return downstreamDestinations; }
+
protected:
//! Profiles original cache requests including PUTs
void profileRequest(const std::string &request);
private:
/** The address range to which the controller responds on the CPU side. */
const AddrRangeList addrRanges;
+
+ typedef std::unordered_map<MachineType, MachineID> AddrMapEntry;
+
+ AddrRangeMap<AddrMapEntry, 3> downstreamAddrMap;
+
+ NetDest downstreamDestinations;
+
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
-# Copyright (c) 2017,2019 ARM Limited
+# Copyright (c) 2017,2019,2020 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
"memory output to the main memory is now called `memory_out_port`")
system = Param.System(Parent.any, "system object parameter")
+
+ # These can be used by a protocol to enable reuse of the same machine
+ # types to model different levels of the cache hierarchy
+ downstream_destinations = VectorParam.RubyController([],
+ "Possible destinations for requests sent towards memory")