self.probeToL3 = probe_to_l3
self.respToL3 = resp_to_l3
-class DirMem(RubyDirectoryMemory, CntrlBase):
- def create(self, options, ruby_system, system):
- self.version = self.versionCount()
-
- phys_mem_size = AddrRange(options.mem_size).size()
- mem_module_size = phys_mem_size / options.num_dirs
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
- self.size = dir_size
-
class DirCntrl(Directory_Controller, CntrlBase):
- def create(self, options, ruby_system, system):
+ def create(self, options, dir_ranges, ruby_system, system):
self.version = self.versionCount()
self.response_latency = 30
- self.directory = DirMem()
- self.directory.create(options, ruby_system, system)
+ self.addr_ranges = dir_ranges
+ self.directory = RubyDirectoryMemory()
self.L3CacheMemory = L3Cache()
self.L3CacheMemory.create(options, ruby_system, system)
# This is the base crossbar that connects the L3s, Dirs, and cpu/gpu
# Clusters
mainCluster = Cluster(extBW = 512, intBW = 512) # 1 TB/s
+
+ if options.numa_high_bit:
+ numa_bit = options.numa_high_bit
+ else:
+ # if the numa_bit is not specified, set the directory bits as the
+ # lowest bits above the block offset bits, and the numa_bit as the
+ # highest of those directory bits
+ dir_bits = int(math.log(options.num_dirs, 2))
+ block_size_bits = int(math.log(options.cacheline_size, 2))
+ numa_bit = block_size_bits + dir_bits - 1
+
for i in xrange(options.num_dirs):
+ dir_ranges = []
+ for r in system.mem_ranges:
+ addr_range = m5.objects.AddrRange(r.start, size = r.size(),
+ intlvHighBit = numa_bit,
+ intlvBits = dir_bits,
+ intlvMatch = i)
+ dir_ranges.append(addr_range)
dir_cntrl = DirCntrl(TCC_select_num_bits = TCC_bits)
- dir_cntrl.create(options, ruby_system, system)
+ dir_cntrl.create(options, dir_ranges, ruby_system, system)
dir_cntrl.number_of_TBEs = 2560 * options.num_compute_units
#Enough TBEs for all TCP TBEs
from m5.objects import *
from m5.defines import buildEnv
from m5.util import addToPath
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
#
# Declare caches used by the protocol
# Therefore the l1 controller nodes must be listed before
# the directory nodes and directory nodes before dma nodes, etc.
l1_cntrl_nodes = []
- dir_cntrl_nodes = []
#
# Must create the individual controllers before the network to ensure the
l1_cntrl.forwardFromCache = MessageBuffer()
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
- dir_cntrl = Directory_Controller(version = i,
- directory = \
- RubyDirectoryMemory(version = i,
- size = dir_size),
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer()
dir_cntrl.forwardToDir = MessageBuffer()
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
l0_cntrl_nodes = []
l1_cntrl_nodes = []
l2_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
assert (options.num_cpus % options.num_clusters == 0)
l2_cntrl.responseToL2Cache = MessageBuffer()
l2_cntrl.responseToL2Cache.slave = ruby_system.network.master
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
# Run each of the ruby memory controllers at a ratio of the frequency of
# the ruby system
# clk_divider value is a fix to pass regression.
ruby_system.memctrl_clk_domain = DerivedClockDomain(
clk_domain = ruby_system.clk_domain, clk_divider = 3)
- for i in xrange(options.num_dirs):
- #
- # Create the Ruby objects associated with the directory controller
- #
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(version = i, size = dir_size),
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer()
dir_cntrl.requestToDir.slave = ruby_system.network.master
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
#
l1_cntrl_nodes = []
l2_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
#
l2_cntrl.responseToL2Cache.slave = ruby_system.network.master
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
-
# Run each of the ruby memory controllers at a ratio of the frequency of
# the ruby system
# clk_divider value is a fix to pass regression.
clk_domain = ruby_system.clk_domain,
clk_divider = 3)
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(version = i, size = dir_size),
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer()
dir_cntrl.requestToDir.slave = ruby_system.network.master
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
# listed before the directory nodes and directory nodes before dma nodes, etc.
#
l1_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
#
clk_domain=ruby_system.clk_domain,
clk_divider=3)
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(
- version = i, size = dir_size),
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer(ordered = True)
dir_cntrl.requestToDir.slave = ruby_system.network.master
self.probeToL3 = probe_to_l3
self.respToL3 = resp_to_l3
-class DirMem(RubyDirectoryMemory, CntrlBase):
- def create(self, options, ruby_system, system):
- self.version = self.versionCount()
-
- phys_mem_size = AddrRange(options.mem_size).size()
- mem_module_size = phys_mem_size / options.num_dirs
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
- self.size = dir_size
-
class DirCntrl(Directory_Controller, CntrlBase):
- def create(self, options, ruby_system, system):
+ def create(self, options, dir_ranges, ruby_system, system):
self.version = self.versionCount()
self.response_latency = 30
- self.directory = DirMem()
- self.directory.create(options, ruby_system, system)
+ self.addr_ranges = dir_ranges
+ self.directory = RubyDirectoryMemory()
self.L3CacheMemory = L3Cache()
self.L3CacheMemory.create(options, ruby_system, system)
# This is the base crossbar that connects the L3s, Dirs, and cpu
# Cluster
mainCluster = Cluster(extBW = 512, intBW = 512) # 1 TB/s
+
+ if options.numa_high_bit:
+ numa_bit = options.numa_high_bit
+ else:
+ # if the numa_bit is not specified, set the directory bits as the
+ # lowest bits above the block offset bits, and the numa_bit as the
+ # highest of those directory bits
+ dir_bits = int(math.log(options.num_dirs, 2))
+ block_size_bits = int(math.log(options.cacheline_size, 2))
+ numa_bit = block_size_bits + dir_bits - 1
+
for i in xrange(options.num_dirs):
+ dir_ranges = []
+ for r in system.mem_ranges:
+ addr_range = m5.objects.AddrRange(r.start, size = r.size(),
+ intlvHighBit = numa_bit,
+ intlvBits = dir_bits,
+ intlvMatch = i)
+ dir_ranges.append(addr_range)
+
dir_cntrl = DirCntrl(TCC_select_num_bits = 0)
- dir_cntrl.create(options, ruby_system, system)
+ dir_cntrl.create(options, dir_ranges, ruby_system, system)
# Connect the Directory controller to the ruby network
dir_cntrl.requestFromCores = MessageBuffer(ordered = True)
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
#
l1_cntrl_nodes = []
l2_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
#
l2_cntrl.responseToL2Cache.slave = ruby_system.network.master
l2_cntrl.triggerQueue = MessageBuffer(ordered = True)
-
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
-
# Run each of the ruby memory controllers at a ratio of the frequency of
# the ruby system.
# clk_divider value is a fix to pass regression.
clk_domain=ruby_system.clk_domain,
clk_divider=3)
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(
- version = i, size = dir_size),
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer()
dir_cntrl.requestToDir.slave = ruby_system.network.master
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
#
l1_cntrl_nodes = []
l2_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
#
l2_cntrl.persistentToL2Cache.slave = ruby_system.network.master
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
# Run each of the ruby memory controllers at a ratio of the frequency of
# the ruby system
# clk_divider value is a fix to pass regression.
clk_domain=ruby_system.clk_domain,
clk_divider=3)
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(
- version = i, size = dir_size),
- l2_select_num_bits = l2_bits,
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
-
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
+ dir_cntrl.l2_select_num_bits = l2_bits
# Connect the directory controllers and the network
dir_cntrl.requestToDir = MessageBuffer()
dir_cntrl.requestToDir.slave = ruby_system.network.master
import m5
from m5.objects import *
from m5.defines import buildEnv
-from Ruby import create_topology
+from Ruby import create_topology, create_directories
from Ruby import send_evicts
#
# listed before the directory nodes and directory nodes before dma nodes, etc.
#
l1_cntrl_nodes = []
- dir_cntrl_nodes = []
dma_cntrl_nodes = []
#
l1_cntrl.responseToCache.slave = ruby_system.network.master
- phys_mem_size = sum(map(lambda r: r.size(), system.mem_ranges))
- assert(phys_mem_size % options.num_dirs == 0)
- mem_module_size = phys_mem_size / options.num_dirs
-
#
# determine size and index bits for probe filter
# By default, the probe filter size is configured to be twice the
clk_domain=ruby_system.clk_domain,
clk_divider=3)
- for i in xrange(options.num_dirs):
- dir_size = MemorySize('0B')
- dir_size.value = mem_module_size
-
+ dir_cntrl_nodes = create_directories(options, system.mem_ranges,
+ ruby_system)
+ for dir_cntrl in dir_cntrl_nodes:
pf = ProbeFilter(size = pf_size, assoc = 4,
start_index_bit = pf_start_bit)
- dir_cntrl = Directory_Controller(version = i,
- directory = RubyDirectoryMemory(
- version = i, size = dir_size),
- probeFilter = pf,
- probe_filter_enabled = options.pf_on,
- full_bit_dir_enabled = options.dir_on,
- transitions_per_cycle = options.ports,
- ruby_system = ruby_system)
+ dir_cntrl.probeFilter = pf
+ dir_cntrl.probe_filter_enabled = options.pf_on
+ dir_cntrl.full_bit_dir_enabled = options.dir_on
if options.recycle_latency:
dir_cntrl.recycle_latency = options.recycle_latency
- exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
- dir_cntrl_nodes.append(dir_cntrl)
-
# Connect the directory controller to the network
dir_cntrl.forwardFromDir = MessageBuffer()
dir_cntrl.forwardFromDir.master = ruby_system.network.slave
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012, 2017 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
def setup_memory_controllers(system, ruby, dir_cntrls, options):
ruby.block_size_bytes = options.cacheline_size
ruby.memory_size_bits = 48
- block_size_bits = int(math.log(options.cacheline_size, 2))
-
- if options.numa_high_bit:
- numa_bit = options.numa_high_bit
- else:
- # if the numa_bit is not specified, set the directory bits as the
- # lowest bits above the block offset bits, and the numa_bit as the
- # highest of those directory bits
- dir_bits = int(math.log(options.num_dirs, 2))
- numa_bit = block_size_bits + dir_bits - 1
index = 0
mem_ctrls = []
# for each address range as the abstract memory can handle only one
# contiguous address range as of now.
for dir_cntrl in dir_cntrls:
- dir_cntrl.directory.numa_high_bit = numa_bit
-
crossbar = None
if len(system.mem_ranges) > 1:
crossbar = IOXBar()
ruby.phys_mem = SimpleMemory(range=system.mem_ranges[0],
in_addr_map=False)
+def create_directories(options, mem_ranges, ruby_system):
+ dir_cntrl_nodes = []
+ if options.numa_high_bit:
+ numa_bit = options.numa_high_bit
+ else:
+ # if the numa_bit is not specified, set the directory bits as the
+ # lowest bits above the block offset bits, and the numa_bit as the
+ # highest of those directory bits
+ dir_bits = int(math.log(options.num_dirs, 2))
+ block_size_bits = int(math.log(options.cacheline_size, 2))
+ numa_bit = block_size_bits + dir_bits - 1
+
+ for i in xrange(options.num_dirs):
+ dir_ranges = []
+ for r in mem_ranges:
+ addr_range = m5.objects.AddrRange(r.start, size = r.size(),
+ intlvHighBit = numa_bit,
+ intlvBits = dir_bits,
+ intlvMatch = i)
+ dir_ranges.append(addr_range)
+
+ dir_cntrl = Directory_Controller()
+ dir_cntrl.version = i
+ dir_cntrl.directory = RubyDirectoryMemory()
+ dir_cntrl.ruby_system = ruby_system
+ dir_cntrl.addr_ranges = dir_ranges
+
+ exec("ruby_system.dir_cntrl%d = dir_cntrl" % i)
+ dir_cntrl_nodes.append(dir_cntrl)
+ return dir_cntrl_nodes
+
def send_evicts(options):
# currently, 2 scenarios warrant forwarding evictions to the CPU:
# 1. The O3 model must keep the LSQ coherent with the caches
/*
- * Copyright (c) 2012, 2014 ARM Limited
+ * Copyright (c) 2012, 2014, 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
return false;
}
+ /**
+ * Remove the interleaving bits from an input address.
+ *
+ * This function returns a new address that doesn't have the bits
+ * that are use to determine which of the interleaved ranges it
+ * belongs to.
+ *
+ * e.g., if the input address is:
+ * -------------------------------
+ * | prefix | intlvBits | suffix |
+ * -------------------------------
+ * this function will return:
+ * -------------------------------
+ * | 0 | prefix | suffix |
+ * -------------------------------
+ *
+ * @param the input address
+ * @return the address without the interleaved bits
+ */
+ inline Addr removeIntlvBits(const Addr &a) const
+ {
+ const auto intlv_low_bit = intlvHighBit - intlvBits + 1;
+ return insertBits(a >> intlvBits, intlv_low_bit - 1, 0, a);
+ }
+
+ /**
+ * Determine the offset of an address within the range.
+ *
+ * This function returns the offset of the given address from the
+ * starting address discarding any bits that are used for
+ * interleaving. This way we can convert the input address to a
+ * new unique address in a continuous range that starts from 0.
+ *
+ * @param the input address
+ * @return the flat offset in the address range
+ */
+ Addr getOffset(const Addr& a) const
+ {
+ bool in_range = a >= _start && a <= _end;
+ if (!in_range) {
+ return MaxAddr;
+ }
+ if (interleaved()) {
+ return removeIntlvBits(a) - removeIntlvBits(_start);
+ } else {
+ return a - _start;
+ }
+ }
+
/**
* Less-than operator used to turn an STL map into a binary search
* tree of non-overlapping address ranges.
void unset_cache_entry();
void set_tbe(TBE b);
void unset_tbe();
-
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
bool presentOrAvail(Addr addr) {
return directory.isTagPresent(addr) || directory.cacheAvail(addr);
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlk;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlkS;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlkM;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
out_msg.addr := address;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.Type := CoherenceRequestType:VicDirty;
if (cache_entry.CacheState == State:O) {
enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
out_msg.addr := address;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.Type := CoherenceRequestType:VicClean;
if (cache_entry.CacheState == State:S) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and TCC respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Ntsl := true;
out_msg.Hit := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and TCC respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false; // only true if sending back data i think
out_msg.Hit := false;
out_msg.Ntsl := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := getDataBlock(address);
if (is_valid(tbe)) {
out_msg.Dirty := tbe.Dirty;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := getDataBlock(address);
if (is_valid(tbe)) {
out_msg.Dirty := tbe.Dirty;
enqueue(requestToNB_out, CPURequestMsg, issue_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:WrCancel;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Requestor := machineID;
out_msg.MessageSize := MessageSizeType:Request_Control;
}
action(uu_sendUnblock, "uu", desc="state changed, unblock") {
enqueue(unblockToNB_out, UnblockMsg, issue_latency) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
enqueue(responseToNB_out, ResponseMsg, issue_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:StaleNotif;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Response_Control;
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUData;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
if (tbe.Shared) {
}
enqueue(unblockToNB_out, UnblockMsg, 1) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Shared := false; // unneeded for this request
out_msg.MessageSize := in_msg.MessageSize;
DPRINTF(RubySlicc, "%s\n", out_msg);
out_msg.addr := address;
out_msg.Requestor := machineID;
out_msg.WTRequestor := in_msg.Requestor;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Data;
out_msg.Type := CoherenceRequestType:WriteThrough;
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Requestor := machineID;
out_msg.WTRequestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Data;
out_msg.Type := CoherenceRequestType:WriteThrough;
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Requestor := machineID;
out_msg.WTRequestor := in_msg.Requestor;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Data;
out_msg.Type := CoherenceRequestType:Atomic;
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
}
enqueue(unblockToNB_out, UnblockMsg, 1) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // TCC, L3 respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
// FUNCTIONS
Tick clockEdge();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
// cpu/testers/networktest/networktest.cc generates packets of the type
// ReadReq, INST_FETCH, and WriteReq.
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
// To send broadcasts in vnet0 (to emulate broadcast-based protocols),
// replace the above line by the following:
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:MSG;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Data;
}
}
void unset_tbe();
void wakeUpBuffers(Addr a);
void profileMsgDelay(int virtualNetworkType, Cycles c);
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
// inclusive cache, returns L2 entries only
Entry getCacheEntry(Addr addr), return_by_pointer="yes" {
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:MEMORY_DATA;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
out_msg.Dirty := cache_entry.Dirty;
out_msg.MessageSize := MessageSizeType:Response_Data;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:MEMORY_DATA;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
out_msg.MessageSize := MessageSizeType:Response_Data;
TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
Tick clockEdge();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
State getState(TBE tbe, Addr addr) {
if (is_valid(tbe)) {
out_msg.Type := CoherenceRequestType:DMA_READ;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Type := CoherenceRequestType:DMA_WRITE;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
void set_tbe(TBE b);
void unset_tbe();
void profileMsgDelay(int virtualNetworkType, Cycles b);
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getCacheEntry(Addr address), return_by_pointer="yes" {
return static_cast(Entry, "pointer", cacheMemory.lookup(address));
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
out_msg.MessageSize := MessageSizeType:Data;
}
TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
Tick clockEdge();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
State getState(TBE tbe, Addr addr) {
if (is_valid(tbe)) {
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
// END STRUCTURE DEFINITIONS
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlk;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
DPRINTF(RubySlicc,"%s\n",out_msg.Destination);
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlkM;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:RdBlkS;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
}
assert(is_valid(cache_entry));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.Type := CoherenceRequestType:VicDirty;
out_msg.InitialRequestTime := curCycle();
enqueue(requestNetwork_out, CPURequestMsg, issue_latency) {
out_msg.addr := address;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.Type := CoherenceRequestType:VicClean;
out_msg.InitialRequestTime := curCycle();
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:StaleNotif;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Response_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUData;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
if (tbe.Shared) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Ntsl := true;
out_msg.Hit := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
assert(addressInCore(address) || is_valid(tbe));
out_msg.Dirty := false; // only true if sending back data i think
out_msg.Hit := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
if (addressInCore(address)) {
out_msg.Hit := true;
} else {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
assert(tbe.Dirty);
out_msg.Dirty := true;
action(uu_sendUnblock, "uu", desc="state changed, unblock") {
enqueue(unblockNetwork_out, UnblockMsg, issue_latency) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
void unset_tbe();
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
-
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
// FUNCTION DEFINITIONS
Tick clockEdge();
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Shared := false; // unneeded for this request
out_msg.MessageSize := in_msg.MessageSize;
DPRINTF(RubySlicc, "%s\n", out_msg);
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:VicDirty;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := true;
out_msg.Ntsl := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
assert(tbe.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:WrCancel;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUData;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
if (tbe.Shared) {
action(uu_sendUnblock, "uu", desc="state changed, unblock") {
enqueue(unblockNetwork_out, UnblockMsg, l3_request_latency) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
// END STRUCTURE DEFINITIONS
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:StaleNotif;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Response_Control;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUData;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
if (tbe.Shared) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Hit := false;
out_msg.Ntsl := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false;
out_msg.Ntsl := true;
out_msg.Hit := false;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
assert(addressInCore(address) || is_valid(tbe));
out_msg.Dirty := false; // only true if sending back data i think
out_msg.Hit := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
if (addressInCore(address)) {
out_msg.Hit := true;
} else {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := cache_entry.DataBlk;
assert(cache_entry.Dirty);
out_msg.Dirty := true;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
assert(tbe.Dirty);
out_msg.Dirty := true;
enqueue(responseNetwork_out, ResponseMsg, issue_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:CPUCancelWB;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Response_Control;
}
action(uu_sendUnblock, "uu", desc="state changed, unblock") {
enqueue(unblockNetwork_out, UnblockMsg, issue_latency) {
out_msg.addr := address;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
out_msg.wasValid := isValid(address);
DPRINTF(RubySlicc, "%s\n", out_msg);
enqueue(responseNetwork_out, ResponseMsg, response_latency_regionDir) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:DirReadyAck;
- out_msg.Destination.add(map_Address_to_RegionDir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.Sender := machineID;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Requestor := in_msg.Requestor;
- out_msg.Destination.add(map_Address_to_RegionDir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
- DPRINTF(RubySlicc, "out dest: %s\n", map_Address_to_RegionDir(address));
+ DPRINTF(RubySlicc, "out dest: %s\n", mapAddressToMachine(address, MachineType:RegionDir));
}
}
}
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
int blockBits, default="RubySystem::getBlockSizeBits()";
int blockBytes, default="RubySystem::getBlockSizeBytes()";
out_msg.Dirty := in_msg.Dirty;
out_msg.Requestor := in_msg.Requestor;
out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Destination.add(map_Address_to_Directory(in_msg.addr));
+ out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Private := true;
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.InitialRequestTime := curCycle();
// will this always be ok? probably not for multisocket
- out_msg.Destination.add(map_Address_to_RegionDir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Request_Control;
DPRINTF(RubySlicc, "Private request %s\n", out_msg);
}
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.InitialRequestTime := curCycle();
// will this always be ok? probably not for multisocket
- out_msg.Destination.add(map_Address_to_RegionDir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
cache_entry.ProbeRequestTime := curCycle();
out_msg.addr := getRegionBase(address); // use the actual address so the demand request can be fulfilled
out_msg.Type := CoherenceRequestType:CleanWbRequest;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.Dirty := tbe.dirty;
APPEND_TRANSITION_COMMENT(getRegionBase(address));
out_msg.WTRequestor := in_msg.WTRequestor;
out_msg.InitialRequestTime := curCycle();
// will this always be ok? probably not for multisocket
- out_msg.Destination.add(map_Address_to_RegionDir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
cache_entry.ProbeRequestTime := curCycle();
out_msg.addr := getRegionBase(address);
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.addr := tbe.DemandAddress;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := getPeer(machineID,address);
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false; // only true if sending back data i think
out_msg.Hit := false;
out_msg.Ntsl := false;
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
out_msg.NotCached := true;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
out_msg.Dirty := tbe.dirty;
}
out_msg.addr := getRegionBase(address);
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.Type := CoherenceResponseType:CPUPrbResp;
out_msg.Sender := machineID;
out_msg.NotCached := true;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.addr := getRegionBase(address);
out_msg.Type := CoherenceResponseType:PrivateAck;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.addr := getRegionBase(address);
out_msg.Type := CoherenceResponseType:RegionWbAck;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_RegionDir(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:RegionDir));
out_msg.MessageSize := MessageSizeType:Response_Control;
}
}
out_msg.addr := in_msg.DemandAddress;
out_msg.Type := CoherenceResponseType:CPUPrbResp; // L3 and CPUs respond in same way to probes
out_msg.Sender := getPeer(machineID,address);
- out_msg.Destination.add(map_Address_to_Directory(address)); // will this always be ok? probably not for multisocket
+ // will this always be ok? probably not for multisocket
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := false; // only true if sending back data i think
out_msg.Hit := false;
out_msg.Ntsl := false;
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
int blockBits, default="RubySystem::getBlockSizeBits()";
int blockBytes, default="RubySystem::getBlockSizeBytes()";
out_msg.Dirty := in_msg.Dirty;
out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Destination.add(map_Address_to_Directory(in_msg.addr));
+ out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Private := in_msg.Private;
out_msg.Dirty := in_msg.Dirty;
out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Destination.add(map_Address_to_Directory(in_msg.addr));
+ out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Private := in_msg.Private;
out_msg.Dirty := in_msg.Dirty;
out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Destination.add(map_Address_to_Directory(in_msg.addr));
+ out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Private := in_msg.Private;
out_msg.Dirty := in_msg.Dirty;
out_msg.Requestor := getCoreMachine(in_msg.Requestor,address);
out_msg.WTRequestor := in_msg.WTRequestor;
- out_msg.Destination.add(map_Address_to_Directory(in_msg.addr));
+ out_msg.Destination.add(mapAddressToMachine(in_msg.addr, MachineType:Directory));
out_msg.Shared := in_msg.Shared;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.Private := in_msg.Private;
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
Entry dir_entry := static_cast(Entry, "pointer", directory.lookup(addr));
out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
TCC_select_low_bit, TCC_select_num_bits));
} else {
- out_msg.Destination.add(map_Address_to_TCCdir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:TCCdir));
}
}
out_msg.Destination.remove(in_msg.Requestor);
if (noTCCdir) {
//Don't need to notify TCC about reads
} else {
- out_msg.Destination.add(map_Address_to_TCCdir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:TCCdir));
tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
}
if (noTCCdir && CAB_TCC) {
if (noTCCdir) {
//Don't need to notify TCC about reads
} else {
- out_msg.Destination.add(map_Address_to_TCCdir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:TCCdir));
tbe.NumPendingAcks := tbe.NumPendingAcks + 1;
}
if (noTCCdir && CAB_TCC) {
out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC,
TCC_select_low_bit, TCC_select_num_bits));
} else {
- out_msg.Destination.add(map_Address_to_TCCdir(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:TCCdir));
}
}
out_msg.Destination.remove(in_msg.Requestor);
void unset_cache_entry();
void set_tbe(TBE b);
void unset_tbe();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getCacheEntry(Addr address), return_by_pointer="yes" {
return static_cast(Entry, "pointer", L2cache[address]);
out_msg.Type := CoherenceRequestType:GETS;
out_msg.RequestorMachine := MachineType:L2Cache;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.Type := CoherenceRequestType:GETX;
out_msg.RequestorMachine := MachineType:L2Cache;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
}
}
out_msg.Type := CoherenceRequestType:PUTX;
out_msg.RequestorMachine := MachineType:L2Cache;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Type := CoherenceRequestType:PUTO;
out_msg.Requestor := machineID;
out_msg.RequestorMachine := MachineType:L2Cache;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Type := CoherenceRequestType:PUTO_SHARERS;
out_msg.Requestor := machineID;
out_msg.RequestorMachine := MachineType:L2Cache;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCK;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L2Cache;
out_msg.MessageSize := MessageSizeType:Unblock_Control;
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L2Cache;
out_msg.MessageSize := MessageSizeType:Unblock_Control;
out_msg.addr := address;
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L2Cache;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := tbe.Dirty;
if (tbe.Dirty) {
out_msg.Type := CoherenceResponseType:WRITEBACK_DIRTY_DATA;
enqueue(responseNetwork_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:DMA_ACK;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:L2Cache;
out_msg.MessageSize := MessageSizeType:Unblock_Control;
void set_tbe(TBE b);
void unset_tbe();
void wakeUpAllBuffers();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
State getState(TBE tbe, Addr addr) {
return cur_state;
out_msg.Type := CoherenceRequestType:DMA_READ;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Requestor := machineID;
out_msg.RequestorMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
out_msg.Type := CoherenceRequestType:DMA_WRITE;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Requestor := machineID;
out_msg.RequestorMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
enqueue(respToDirectory_out, ResponseMsg, response_latency) {
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCK_EXCLUSIVE;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Sender := machineID;
out_msg.SenderMachine := MachineType:DMA;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
TBETable L1_TBEs, template="<L1Cache_TBE>", constructor="m_number_of_TBEs";
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
out_msg.Prefetch := tbe.Prefetch;
out_msg.AccessMode := tbe.AccessMode;
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
out_msg.Prefetch := tbe.Prefetch;
out_msg.AccessMode := tbe.AccessMode;
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Tokens := in_msg.Tokens;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := in_msg.DataBlk;
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
}
starving := false;
Tick clockEdge();
void set_cache_entry(AbstractCacheEntry b);
void unset_cache_entry();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getCacheEntry(Addr address), return_by_pointer="yes" {
Entry cache_entry := static_cast(Entry, "pointer", L2cache.lookup(address));
//out_msg.Destination.addNetDest(getAllPertinentL2Banks(address));
//out_msg.Destination.remove(map_L1CacheMachId_to_L2Cache(address, in_msg.Requestor));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.AccessMode := in_msg.AccessMode;
out_msg.Prefetch := in_msg.Prefetch;
out_msg.addr := address;
out_msg.Type := in_msg.Type;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Tokens := in_msg.Tokens;
out_msg.MessageSize := in_msg.MessageSize;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:ACK;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Tokens := cache_entry.Tokens;
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
enqueue(responseNetwork_out, ResponseMsg, l2_response_latency) {
out_msg.addr := address;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Tokens := cache_entry.Tokens;
out_msg.DataBlk := cache_entry.DataBlk;
out_msg.Dirty := cache_entry.Dirty;
Tick cyclesToTicks(Cycles c);
void set_tbe(TBE b);
void unset_tbe();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" {
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
out_msg.Prefetch := PrefetchBit:No;
out_msg.AccessMode := RubyAccessMode:Supervisor;
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
out_msg.Prefetch := PrefetchBit:No;
out_msg.AccessMode := RubyAccessMode:Supervisor;
MachineType:L2Cache, l2_select_low_bit,
l2_select_num_bits, intToID(0)));
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Persistent_Control;
}
starving := false;
TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
Tick clockEdge();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
State getState(TBE tbe, Addr addr) {
if (is_valid(tbe)) {
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
void wakeUpAllBuffers();
void wakeUpBuffers(Addr a);
Cycles curCycle();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
Entry getCacheEntry(Addr address), return_by_pointer="yes" {
Entry L2cache_entry := static_cast(Entry, "pointer", L2cache.lookup(address));
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETS;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETX;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:GETF;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Request_Control;
out_msg.InitialRequestTime := curCycle();
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:PUT;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceRequestType:PUTF;
out_msg.Requestor := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCK;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
}
}
out_msg.addr := address;
out_msg.Type := CoherenceResponseType:UNBLOCKM;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
}
}
out_msg.Type := CoherenceResponseType:UNBLOCKS;
out_msg.Sender := machineID;
out_msg.CurOwner := tbe.CurOwner;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Unblock_Control;
}
}
assert(is_valid(tbe));
out_msg.addr := address;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.Dirty := tbe.Dirty;
if (tbe.Dirty) {
out_msg.Type := CoherenceResponseType:WB_DIRTY;
assert(is_valid(tbe));
out_msg.addr := address;
out_msg.Sender := machineID;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.DataBlk := tbe.DataBlk;
out_msg.Dirty := tbe.Dirty;
if (tbe.Dirty) {
TBETable TBEs, template="<DMA_TBE>", constructor="m_number_of_TBEs";
Tick clockEdge();
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype);
State getState(TBE tbe, Addr addr) {
if (is_valid(tbe)) {
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
out_msg.Requestor := machineID;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.Len := in_msg.Len;
- out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory));
out_msg.MessageSize := MessageSizeType:Writeback_Control;
}
}
int low, int high, NodeID n);
NetDest broadcast(MachineType type);
MachineID map_Address_to_DMA(Addr addr);
-MachineID map_Address_to_Directory(Addr addr);
-MachineID map_Address_to_RegionDir(Addr addr);
-NodeID map_Address_to_DirectoryNode(Addr addr);
-MachineID map_Address_to_TCCdir(Addr addr);
-NodeID map_Address_to_TCCdirNode(Addr addr);
NodeID machineIDToNodeID(MachineID machID);
NodeID machineIDToVersion(MachineID machID);
MachineType machineIDToMachineType(MachineID machID);
/*
+ * Copyright (c) 2017 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.
*
#include "mem/ruby/network/Network.hh"
#include "base/misc.hh"
+#include "mem/ruby/common/MachineID.hh"
#include "mem/ruby/network/BasicLink.hh"
#include "mem/ruby/system/RubySystem.hh"
BasicExtLink *ext_link = (*i);
AbstractController *abs_cntrl = ext_link->params()->ext_node;
abs_cntrl->initNetworkPtr(this);
+ const AddrRangeList &ranges = abs_cntrl->getAddrRanges();
+ if (!ranges.empty()) {
+ MachineID mid = abs_cntrl->getMachineID();
+ AddrMapNode addr_map_node = {
+ .id = mid.getNum(),
+ .ranges = ranges
+ };
+ addrMap.emplace(mid.getType(), addr_map_node);
+ }
}
// Register a callback function for combining the statistics
}
m_fromNetQueues[id][network_num] = b;
}
+
+NodeID
+Network::addressToNodeID(Addr addr, MachineType mtype)
+{
+ // Look through the address maps for entries with matching machine
+ // type to get the responsible node for this address.
+ const auto &matching_ranges = addrMap.equal_range(mtype);
+ for (auto it = matching_ranges.first; it != matching_ranges.second; it++) {
+ AddrMapNode &node = it->second;
+ auto &ranges = node.ranges;
+ for (AddrRange &range: ranges) {
+ if (range.contains(addr)) {
+ return node.id;
+ }
+ }
+ }
+ return MachineType_base_count(mtype);
+}
/*
+ * Copyright (c) 2017 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.
*
#include <iostream>
#include <string>
+#include <unordered_map>
#include <vector>
+#include "base/addr_range.hh"
+#include "base/types.hh"
+#include "mem/packet.hh"
#include "mem/protocol/LinkDirection.hh"
#include "mem/protocol/MessageSizeType.hh"
+#include "mem/ruby/common/MachineID.hh"
#include "mem/ruby/common/TypeDefines.hh"
#include "mem/ruby/network/Topology.hh"
-#include "mem/packet.hh"
#include "params/RubyNetwork.hh"
#include "sim/clocked_object.hh"
virtual uint32_t functionalWrite(Packet *pkt)
{ fatal("Functional write not implemented.\n"); }
+ /**
+ * Map an address to the correct NodeID
+ *
+ * This function traverses the global address map to find the
+ * NodeID that corresponds to the given address and the type of
+ * the destination. For example for a request to a directory this
+ * function will return the NodeID of the right directory.
+ *
+ * @param the destination address
+ * @param the type of the destination
+ * @return the NodeID of the destination
+ */
+ NodeID addressToNodeID(Addr addr, MachineType mtype);
+
protected:
// Private copy constructor and assignment operator
Network(const Network& obj);
void process() {ctr->collateStats();}
};
+
+ // Global address map
+ struct AddrMapNode {
+ NodeID id;
+ AddrRangeList ranges;
+ };
+ std::unordered_multimap<MachineType, AddrMapNode> addrMap;
};
inline std::ostream&
/*
+ * Copyright (c) 2017 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) 2011-2014 Mark D. Hill and David A. Wood
* All rights reserved.
*
m_number_of_TBEs(p->number_of_TBEs),
m_transitions_per_cycle(p->transitions_per_cycle),
m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency),
- memoryPort(csprintf("%s.memory", name()), this, "")
+ memoryPort(csprintf("%s.memory", name()), this, ""),
+ addrRanges(p->addr_ranges.begin(), p->addr_ranges.end())
{
if (m_version == 0) {
// Combine the statistics from all controllers
delete pkt;
}
+MachineID
+AbstractController::mapAddressToMachine(Addr addr, MachineType mtype) const
+{
+ NodeID node = m_net_ptr->addressToNodeID(addr, mtype);
+ MachineID mach = {mtype, node};
+ return mach;
+}
+
bool
AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt)
{
/*
+ * Copyright (c) 2017 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) 2009-2014 Mark D. Hill and David A. Wood
* All rights reserved.
*
#include <iostream>
#include <string>
+#include "base/addr_range.hh"
#include "base/callback.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
#include "mem/protocol/AccessPermission.hh"
+#include "mem/qport.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/DataBlock.hh"
#include "mem/ruby/common/MachineID.hh"
#include "mem/ruby/network/MessageBuffer.hh"
#include "mem/ruby/system/CacheRecorder.hh"
-#include "mem/packet.hh"
-#include "mem/qport.hh"
#include "params/RubyController.hh"
-#include "mem/mem_object.hh"
class Network;
class GPUCoalescer;
const DataBlock &block, int size);
void recvTimingResp(PacketPtr pkt);
+ const AddrRangeList &getAddrRanges() const { return addrRanges; }
+
public:
MachineID getMachineID() const { return m_machineID; }
Stats::Histogram& getDelayVCHist(uint32_t index)
{ return *(m_delayVCHistogram[index]); }
+ /**
+ * Map an address to the correct MachineID
+ *
+ * This function querries the network for the NodeID of the
+ * destination for a given request using its address and the type
+ * of the destination. For example for a request with a given
+ * address to a directory it will return the MachineID of the
+ * authorative directory.
+ *
+ * @param the destination address
+ * @param the type of the destination
+ * @return the MachineID of the destination
+ */
+ MachineID mapAddressToMachine(Addr addr, MachineType mtype) const;
+
protected:
//! Profiles original cache requests including PUTs
void profileRequest(const std::string &request);
SenderState(MachineID _id) : id(_id)
{}
};
+
+ private:
+ /** The address range to which the controller responds on the CPU side. */
+ const AddrRangeList addrRanges;
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
+# Copyright (c) 2017 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) 2009 Advanced Micro Devices, Inc.
# All rights reserved.
#
cxx_header = "mem/ruby/slicc_interface/AbstractController.hh"
abstract = True
version = Param.Int("")
+ addr_ranges = VectorParam.AddrRange([AllMemory], "Address range this "
+ "controller responds to")
cluster_id = Param.UInt32(0, "Id of this controller's cluster")
transitions_per_cycle = \
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/structures/DirectoryMemory.hh"
-// used to determine the home directory
-// returns a value between 0 and total_directories_within_the_system
-inline NodeID
-map_Address_to_DirectoryNode(Addr addr)
-{
- return DirectoryMemory::mapAddressToDirectoryVersion(addr);
-}
-
-inline NodeID
-map_Address_to_TCCdirNode(Addr addr)
-{
- return DirectoryMemory::mapAddressToDirectoryVersion(addr);
-}
-
-// used to determine the home directory
-// returns a value between 0 and total_directories_within_the_system
-inline MachineID
-map_Address_to_Directory(Addr addr)
-{
- MachineID mach =
- {MachineType_Directory, map_Address_to_DirectoryNode(addr)};
- return mach;
-}
-
-inline MachineID
-map_Address_to_RegionDir(Addr addr)
-{
- MachineID mach = {MachineType_RegionDir,
- map_Address_to_DirectoryNode(addr)};
- return mach;
-}
-
-inline MachineID
-map_Address_to_TCCdir(Addr addr)
-{
- MachineID mach =
- {MachineType_TCCdir, map_Address_to_TCCdirNode(addr)};
- return mach;
-}
-
inline NetDest
broadcast(MachineType type)
{
/*
+ * Copyright (c) 2017 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
* Copyright (c) 2017 Google Inc.
* All rights reserved.
#include "mem/ruby/structures/DirectoryMemory.hh"
+#include "base/addr_range.hh"
#include "base/intmath.hh"
#include "debug/RubyCache.hh"
#include "debug/RubyStats.hh"
using namespace std;
-int DirectoryMemory::m_num_directories = 0;
-int DirectoryMemory::m_num_directories_bits = 0;
-int DirectoryMemory::m_numa_high_bit = 0;
-
DirectoryMemory::DirectoryMemory(const Params *p)
- : SimObject(p)
+ : SimObject(p), addrRanges(p->addr_ranges.begin(), p->addr_ranges.end())
{
- m_version = p->version;
- // In X86, there is an IO gap in the 3-4GB range.
- if (p->system->getArch() == Arch::X86ISA && p->size > 0xc0000000){
- // We need to add 1GB to the size for the gap
- m_size_bytes = p->size + 0x40000000;
- }
- else {
- m_size_bytes = p->size;
+ m_size_bytes = 0;
+ for (const auto &r: addrRanges) {
+ m_size_bytes += r.size();
}
m_size_bits = floorLog2(m_size_bytes);
m_num_entries = 0;
- m_numa_high_bit = p->numa_high_bit;
}
void
m_entries = new AbstractEntry*[m_num_entries];
for (int i = 0; i < m_num_entries; i++)
m_entries[i] = NULL;
-
- m_num_directories++;
- m_num_directories_bits = ceilLog2(m_num_directories);
-
- if (m_numa_high_bit == 0) {
- m_numa_high_bit = RubySystem::getMemorySizeBits() - 1;
- }
- assert(m_numa_high_bit != 0);
}
DirectoryMemory::~DirectoryMemory()
delete [] m_entries;
}
-uint64_t
-DirectoryMemory::mapAddressToDirectoryVersion(Addr address)
-{
- if (m_num_directories_bits == 0)
- return 0;
-
- uint64_t ret = bitSelect(address,
- m_numa_high_bit - m_num_directories_bits + 1,
- m_numa_high_bit);
- return ret;
-}
-
bool
DirectoryMemory::isPresent(Addr address)
{
- bool ret = (mapAddressToDirectoryVersion(address) == m_version);
- return ret;
+ for (const auto& r: addrRanges) {
+ if (r.contains(address)) {
+ return true;
+ }
+ }
+ return false;
}
uint64_t
DirectoryMemory::mapAddressToLocalIdx(Addr address)
{
- uint64_t ret;
- if (m_num_directories_bits > 0) {
- ret = bitRemove(address, m_numa_high_bit - m_num_directories_bits + 1,
- m_numa_high_bit);
- } else {
- ret = address;
+ uint64_t ret = 0;
+ for (const auto& r: addrRanges) {
+ if (r.contains(address)) {
+ ret += r.getOffset(address);
+ break;
+ }
+ ret += r.size();
}
-
- return ret >> (RubySystem::getBlockSizeBits());
+ return ret >> RubySystem::getBlockSizeBits();
}
AbstractEntry*
/*
+ * Copyright (c) 2017 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.
*
#include <iostream>
#include <string>
+#include "base/addr_range.hh"
#include "mem/protocol/DirectoryRequestType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/slicc_interface/AbstractEntry.hh"
void init();
+ /**
+ * Return the index in the directory based on an address
+ *
+ * This function transforms an address which belongs to a not
+ * necessarily continuous vector of address ranges into a flat
+ * address that we use to index in the directory
+ *
+ * @param an input address
+ * @return the corresponding index in the directory
+ *
+ */
uint64_t mapAddressToLocalIdx(Addr address);
- static uint64_t mapAddressToDirectoryVersion(Addr address);
uint64_t getSize() { return m_size_bytes; }
uint64_t m_size_bytes;
uint64_t m_size_bits;
uint64_t m_num_entries;
- int m_version;
- static int m_num_directories;
- static int m_num_directories_bits;
- static int m_numa_high_bit;
+ /**
+ * The address range for which the directory responds. Normally
+ * this is all possible memory addresses.
+ */
+ const AddrRangeList addrRanges;
};
inline std::ostream&
+# Copyright (c) 2017 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) 2009 Advanced Micro Devices, Inc.
# All rights reserved.
#
type = 'RubyDirectoryMemory'
cxx_class = 'DirectoryMemory'
cxx_header = "mem/ruby/structures/DirectoryMemory.hh"
- version = Param.Int(0, "")
- size = Param.MemorySize("1GB", "capacity in bytes")
- # the default value of the numa high bit is specified in the command line
- # option and must be passed into the directory memory sim object
- numa_high_bit = Param.Int("numa high bit")
- system = Param.System(Parent.any, "system object")
+ addr_ranges = VectorParam.AddrRange(
+ Parent.addr_ranges, "Address range this directory responds to")
code('#include "mem/protocol/AccessPermission.hh"')
if self.isMachineType:
+ code('#include <functional>')
code('#include "base/misc.hh"')
code('#include "mem/ruby/common/Address.hh"')
code('#include "mem/ruby/common/TypeDefines.hh"')
${{self.c_ident}} &operator++(${{self.c_ident}} &e);
''')
+ if self.isMachineType:
+ code('''
+
+// define a hash function for the MachineType class
+namespace std {
+template<>
+struct hash<MachineType> {
+ std::size_t operator()(const MachineType &mtype) const {
+ return hash<size_t>()(static_cast<size_t>(mtype));
+ }
+};
+}
+
+''')
# MachineType hack used to set the base component id for each Machine
if self.isMachineType:
code('''