website: Merge branch 'stable' into develop
This is done periodically to keep develop up-to-date with improvements
on stable.
Change-Id: I828efa321561e0ed0e1c28fdbf395c6325bef9bb
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
index 71fa9ac..e03e811
--- a/README.md
+++ b/README.md
@@ -288,6 +288,29 @@
`aarch64/semihost_exit` only builds for baremetal, as semihosting is not
available on userland.
+The `simple` directory is also able to generate squashfs images containing
+only a single userland executable at `/sbin/init` for any of the userland
+executables. This can be done with a command of type:
+
+ make ISA=aarch64 out/aarch64/squashfs/m5_exit.squashfs
+
+Squashfs is a filesystem type that the Linux kernel understands natively,
+exactly like ext4, except that it is a bit more convenient to create, and
+write-only.
+
+You can therefore give those squashfs images to gem5 exactly as you
+would give a normal ext4 raw image, by pointing to it for example with
+`fs.py --disk-image=m5_exit.squashfs` as shown at:
+https://www.gem5.org/documentation/general_docs/fullsystem/building_arm_kernel
+Linux will then run the given userland executable after Linux boots as the
+init program.
+
+The initial motivation for this was to generate simple test images for
+Linux boot.
+
+Since this is a less common use case, squashfs images are not currently
+generated by any single phony target all at once.
+
## Pre-build binaries
<http://dist.gem5.org/dist/v20-1/test-progs/pthreads/x86/test_pthread_create_seq>
diff --git a/src/boot-exit/README.md b/src/boot-exit/README.md
old mode 100755
new mode 100644
index 7053e46..0510952
--- a/src/boot-exit/README.md
+++ b/src/boot-exit/README.md
@@ -137,4 +137,4 @@
## Working Status
-Working status of these tests for gem5-20 can be found [here](https://www.gem5.org/documentation/benchmark_status/).
+Working status of these tests for gem5-20 can be found [here](https://www.gem5.org/documentation/benchmark_status/gem5-20).
diff --git a/src/boot-exit/configs/system/MESI_Two_Level.py b/src/boot-exit/configs/system/MESI_Two_Level.py
index 4feef12..ec19ce2 100755
--- a/src/boot-exit/configs/system/MESI_Two_Level.py
+++ b/src/boot-exit/configs/system/MESI_Two_Level.py
@@ -91,7 +91,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
@@ -124,7 +124,8 @@
if isa == 'x86':
cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
- cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_responder = \
+ self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
cpu.itb.walker.port = self.sequencers[i].in_ports
cpu.dtb.walker.port = self.sequencers[i].in_ports
diff --git a/src/boot-exit/configs/system/MI_example_caches.py b/src/boot-exit/configs/system/MI_example_caches.py
index 8aa08ea..d104ebc 100755
--- a/src/boot-exit/configs/system/MI_example_caches.py
+++ b/src/boot-exit/configs/system/MI_example_caches.py
@@ -92,7 +92,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
@@ -124,7 +124,8 @@
if isa == 'x86':
cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
- cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_responder = \
+ self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
cpu.itb.walker.port = self.sequencers[i].in_ports
cpu.dtb.walker.port = self.sequencers[i].in_ports
diff --git a/src/boot-exit/configs/system/MOESI_CMP_directory.py b/src/boot-exit/configs/system/MOESI_CMP_directory.py
index 5aa49ba..c30f72c 100755
--- a/src/boot-exit/configs/system/MOESI_CMP_directory.py
+++ b/src/boot-exit/configs/system/MOESI_CMP_directory.py
@@ -92,7 +92,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
diff --git a/src/gapbs/README.md b/src/gapbs/README.md
index c34b4f5..90b1c2e 100644
--- a/src/gapbs/README.md
+++ b/src/gapbs/README.md
@@ -1,5 +1,5 @@
# GAP Benchmark Suite (GAPBS) tests
-This document provides instructions to create a GAP Benchmarks Suite (GAPBS) disk image, which, along with provided configuration scripts, may be used to run GAPBS within gem5 simulations.
+This document provides instructions to create a GAP Benchmark Suite (GAPBS) disk image, which, along with provided configuration scripts, may be used to run GAPBS within gem5 simulations.
A pre-build disk image, for X86, can be found, gzipped, here: <http://dist.gem5.org/dist/v20-1/images/x86/ubuntu-18-04/gapbs.img.gz>.
@@ -41,9 +41,9 @@
**--benchmark** : The graph workload (`cc`, `bc`, `bfs`, `tc`, `pr`, `sssp`).
-**--synthetic** : Type of graph (if synthetic graph 1, if real world graph 0)
+**--synthetic** : Type of graph (if synthetic graph 1, if real world graph 0).
-**--graph** : Size of graph (if synthetic then number of nodes, else name of the graph )
+**--graph** : Size of graph (if synthetic then number of nodes, else name of the graph).
Example usage:
diff --git a/src/gapbs/configs/run_gapbs.py b/src/gapbs/configs/run_gapbs.py
index 4e27261..bb15d9e 100644
--- a/src/gapbs/configs/run_gapbs.py
+++ b/src/gapbs/configs/run_gapbs.py
@@ -86,21 +86,15 @@
cpu_type = args.cpu_type
num_cpus = int(args.num_cpus)
mem_sys = args.mem_sys
- benchmark_name =args.benchmark
+ benchmark_name = args.benchmark
benchmark_size = args.graph
synthetic = args.synthetic
-
-
if (mem_sys == "classic"):
system = MySystem(kernel, disk, cpu_type, num_cpus)
elif (mem_sys == "MI_example" or "MESI_Two_Level"):
system = MyRubySystem(kernel, disk, cpu_type, mem_sys, num_cpus)
-
-
- output_dir = os.path.join(m5.options.outdir, "speclogs")
-
# For workitems to work correctly
# This will cause the simulator to exit simulation when the first work
# item is reached and when the first work item is finished.
diff --git a/src/gapbs/configs/system/MESI_Two_Level.py b/src/gapbs/configs/system/MESI_Two_Level.py
index 102ec57..ca542cb 100644
--- a/src/gapbs/configs/system/MESI_Two_Level.py
+++ b/src/gapbs/configs/system/MESI_Two_Level.py
@@ -83,12 +83,12 @@
icache = self.controllers[i].L1Icache,
dcache = self.controllers[i].L1Dcache,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
@@ -110,21 +110,22 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_port
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_port
+ cpu.dcache_port = self.sequencers[i].in_port
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_port
+ cpu.interrupts[0].int_responder = \
+ self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_port
+ cpu.dtb.walker.port = self.sequencers[i].in_port
class L1Cache(L1Cache_Controller):
@@ -190,18 +191,18 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
- self.requestFromL1Cache.master = ruby_system.network.slave
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
self.responseFromL1Cache = MessageBuffer()
- self.responseFromL1Cache.master = ruby_system.network.slave
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
self.unblockFromL1Cache = MessageBuffer()
- self.unblockFromL1Cache.master = ruby_system.network.slave
+ self.unblockFromL1Cache.out_port = ruby_system.network.in_port
self.optionalQueue = MessageBuffer()
self.requestToL1Cache = MessageBuffer()
- self.requestToL1Cache.slave = ruby_system.network.master
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
self.responseToL1Cache = MessageBuffer()
- self.responseToL1Cache.slave = ruby_system.network.master
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
class L2Cache(L2Cache_Controller):
@@ -235,17 +236,17 @@
"""Connect all of the queues for this controller.
"""
self.DirRequestFromL2Cache = MessageBuffer()
- self.DirRequestFromL2Cache.master = ruby_system.network.slave
+ self.DirRequestFromL2Cache.out_port = ruby_system.network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
- self.L1RequestFromL2Cache.master = ruby_system.network.slave
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
self.responseFromL2Cache = MessageBuffer()
- self.responseFromL2Cache.master = ruby_system.network.slave
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
self.unblockToL2Cache = MessageBuffer()
- self.unblockToL2Cache.slave = ruby_system.network.master
+ self.unblockToL2Cache.in_port = ruby_system.network.out_port
self.L1RequestToL2Cache = MessageBuffer()
- self.L1RequestToL2Cache.slave = ruby_system.network.master
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
self.responseToL2Cache = MessageBuffer()
- self.responseToL2Cache.slave = ruby_system.network.master
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
@@ -273,11 +274,11 @@
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer()
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.responseToDir = MessageBuffer()
- self.responseToDir.slave = ruby_system.network.master
+ self.responseToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -298,9 +299,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
class MyNetwork(SimpleNetwork):
diff --git a/src/gapbs/configs/system/MI_example_caches.py b/src/gapbs/configs/system/MI_example_caches.py
index c588e0d..4ea5938 100644
--- a/src/gapbs/configs/system/MI_example_caches.py
+++ b/src/gapbs/configs/system/MI_example_caches.py
@@ -87,12 +87,12 @@
icache = self.controllers[i].cacheMemory,
dcache = self.controllers[i].cacheMemory,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
@@ -113,21 +113,22 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_port
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_port
+ cpu.dcache_port = self.sequencers[i].in_port
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_port
+ cpu.interrupts[0].int_responder = \
+ self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_port
+ cpu.dtb.walker.port = self.sequencers[i].in_port
class L1Cache(L1Cache_Controller):
@@ -177,13 +178,13 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromCache = MessageBuffer(ordered = True)
- self.requestFromCache.master = ruby_system.network.slave
+ self.requestFromCache.out_port = ruby_system.network.in_port
self.responseFromCache = MessageBuffer(ordered = True)
- self.responseFromCache.master = ruby_system.network.slave
+ self.responseFromCache.out_port = ruby_system.network.in_port
self.forwardToCache = MessageBuffer(ordered = True)
- self.forwardToCache.slave = ruby_system.network.master
+ self.forwardToCache.in_port = ruby_system.network.out_port
self.responseToCache = MessageBuffer(ordered = True)
- self.responseToCache.slave = ruby_system.network.master
+ self.responseToCache.in_port = ruby_system.network.out_port
class DirController(Directory_Controller):
@@ -209,16 +210,16 @@
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer(ordered = True)
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.dmaRequestToDir = MessageBuffer(ordered = True)
- self.dmaRequestToDir.slave = ruby_system.network.master
+ self.dmaRequestToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.dmaResponseFromDir = MessageBuffer(ordered = True)
- self.dmaResponseFromDir.master = ruby_system.network.slave
+ self.dmaResponseFromDir.out_port = ruby_system.network.in_port
self.forwardFromDir = MessageBuffer()
- self.forwardFromDir.master = ruby_system.network.slave
+ self.forwardFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -239,9 +240,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
class MyNetwork(SimpleNetwork):
diff --git a/src/gapbs/configs/system/caches.py b/src/gapbs/configs/system/caches.py
index 1bb9056..ddc578d 100755
--- a/src/gapbs/configs/system/caches.py
+++ b/src/gapbs/configs/system/caches.py
@@ -69,7 +69,7 @@
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -129,13 +129,13 @@
Note: This creates a new crossbar
"""
self.mmubus = L2XBar()
- self.cpu_side = self.mmubus.master
+ self.cpu_side = self.mmubus.mem_side_ports
cpu.mmu.connectWalkerPorts(
self.mmubus.cpu_side_ports, self.mmubus.cpu_side_ports)
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -158,10 +158,10 @@
self.size = opts.l2_size
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L3Cache(Cache):
"""Simple L3 Cache bank with default values
@@ -185,7 +185,7 @@
self.size = ('4MB')
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/gapbs/configs/system/fs_tools.py b/src/gapbs/configs/system/fs_tools.py
index 22a43d2..5e5e2df 100755
--- a/src/gapbs/configs/system/fs_tools.py
+++ b/src/gapbs/configs/system/fs_tools.py
@@ -33,7 +33,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/gapbs/configs/system/ruby_system.py b/src/gapbs/configs/system/ruby_system.py
index b642d97..d0afeae 100755
--- a/src/gapbs/configs/system/ruby_system.py
+++ b/src/gapbs/configs/system/ruby_system.py
@@ -78,7 +78,8 @@
self.caches = MESITwoLevelCache()
self.caches.setup(self, self.cpu, self.mem_cntrls,
- [self.pc.south_bridge.ide.dma, self.iobus.master],
+ [self.pc.south_bridge.ide.dma,
+ self.iobus.mem_side_ports],
self.iobus)
if self._host_parallel:
diff --git a/src/gapbs/configs/system/system.py b/src/gapbs/configs/system/system.py
index ba87399..1e82b12 100755
--- a/src/gapbs/configs/system/system.py
+++ b/src/gapbs/configs/system/system.py
@@ -59,7 +59,7 @@
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus,num_cpus)
@@ -189,9 +189,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
def createMemoryControllersDDR3(self):
@@ -204,13 +204,13 @@
self.mem_cntrls = [
cls(range = ranges[i],
- port = self.membus.master)
+ port = self.membus.mem_side_ports)
for i in range(num)
] + [kernel_controller]
def _createKernelMemoryController(self, cls):
return cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ port = self.membus.mem_side_ports)
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
from math import log
@@ -240,13 +240,13 @@
IO_address_space_base = 0x8000000000000000
pci_config_address_space_base = 0xc000000000000000
interrupts_address_space_base = 0xa000000000000000
- APIC_range_size = 1 << 12;
+ APIC_range_size = 1 << 12
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -266,8 +266,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -286,8 +286,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
diff --git a/src/hack-back/README.md b/src/hack-back/README.md
old mode 100755
new mode 100644
diff --git a/src/linux-kernel/README.md b/src/linux-kernel/README.md
index 10a9443..417f428 100644
--- a/src/linux-kernel/README.md
+++ b/src/linux-kernel/README.md
@@ -45,12 +45,12 @@
**Note:** The above instructions are tested with `gcc 7.5.0` and the compiled Linux binaries can be downloaded from the following links:
-- [vmlinux-4.4.186](http://dist.gem5.org/kernels/x86/static/vmlinux-4.4.186)
-- [vmlinux-4.9.186](http://dist.gem5.org/kernels/x86/static/vmlinux-4.9.186)
-- [vmlinux-4.14.134](http://dist.gem5.org/kernels/x86/static/vmlinux-4.14.134)
-- [vmlinux-4.19.83](http://dist.gem5.org/kernels/x86/static/vmlinux-4.19.83)
-- [vmlinux-5.4.49](http://dist.gem5.org/kernels/x86/static/vmlinux-5.4.49)
+- [vmlinux-4.4.186](http://dist.gem5.org/dist/v20-1/kernels/x86/static/vmlinux-4.4.186)
+- [vmlinux-4.9.186](http://dist.gem5.org/dist/v20-1/kernels/x86/static/vmlinux-4.9.186)
+- [vmlinux-4.14.134](http://dist.gem5.org/dist/v20-1/kernels/x86/static/vmlinux-4.14.134)
+- [vmlinux-4.19.83](http://dist.gem5.org/dist/v20-1/kernels/x86/static/vmlinux-4.19.83)
+- [vmlinux-5.4.49](http://dist.gem5.org/dist/v20-1/kernels/x86/static/vmlinux-5.4.49)
**Licensing:**
-Linux is released under the GNU General Public License version 2 (GPLv2), but it also contains several files under other compatible licenses. For more information about Linux Kernel Copy Right please refer to [here](https://www.kernel.org/legal.html) and [here](https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing)
\ No newline at end of file
+Linux is released under the GNU General Public License version 2 (GPLv2), but it also contains several files under other compatible licenses. For more information about Linux Kernel Copy Right please refer to [here](https://www.kernel.org/legal.html) and [here](https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing).
diff --git a/src/npb/README.md b/src/npb/README.md
old mode 100755
new mode 100644
index 758d979..a83f1b3
--- a/src/npb/README.md
+++ b/src/npb/README.md
@@ -125,4 +125,4 @@
## Working Status
-The working status of these tests for gem5-20 can be found [here](https://www.gem5.org/documentation/benchmark_status/#npb-tests).
+The working status of these tests for gem5-20 can be found [here](https://www.gem5.org/documentation/benchmark_status/gem5-20#npb-tests).
diff --git a/src/npb/configs/system/MESI_Two_Level.py b/src/npb/configs/system/MESI_Two_Level.py
index 1294445..eac0834 100755
--- a/src/npb/configs/system/MESI_Two_Level.py
+++ b/src/npb/configs/system/MESI_Two_Level.py
@@ -88,7 +88,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
diff --git a/src/npb/configs/system/MI_example_caches.py b/src/npb/configs/system/MI_example_caches.py
index ca69eab..907c3f0 100755
--- a/src/npb/configs/system/MI_example_caches.py
+++ b/src/npb/configs/system/MI_example_caches.py
@@ -89,7 +89,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
diff --git a/src/npb/configs/system/MOESI_CMP_directory.py b/src/npb/configs/system/MOESI_CMP_directory.py
index 5208e73..bf31ab7 100755
--- a/src/npb/configs/system/MOESI_CMP_directory.py
+++ b/src/npb/configs/system/MOESI_CMP_directory.py
@@ -92,7 +92,7 @@
pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
- slave = port)
+ in_port = port)
for i,port in enumerate(dma_ports)
]
diff --git a/src/parsec/README.md b/src/parsec/README.md
index 4e25874..9956be3 100644
--- a/src/parsec/README.md
+++ b/src/parsec/README.md
@@ -90,4 +90,4 @@
## Working Status
-The working status of PARSEC runs for gem5-20 has been documented [here](https://www.gem5.org/documentation/benchmark_status/#parsec-tests).
+The working status of PARSEC runs for gem5-20 has been documented [here](https://www.gem5.org/documentation/benchmark_status/gem5-20#parsec-tests).
diff --git a/src/parsec/configs/system/caches.py b/src/parsec/configs/system/caches.py
index 0a43c81..f5d3100 100755
--- a/src/parsec/configs/system/caches.py
+++ b/src/parsec/configs/system/caches.py
@@ -72,7 +72,7 @@
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -136,13 +136,13 @@
Note: This creates a new crossbar
"""
self.mmubus = L2XBar()
- self.cpu_side = self.mmubus.master
+ self.cpu_side = self.mmubus.mem_side_ports
cpu.mmu.connectWalkerPorts(
self.mmubus.cpu_side_ports, self.mmubus.cpu_side_ports)
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -167,10 +167,10 @@
self.size = opts.l2_size
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L3Cache(Cache):
"""Simple L3 Cache bank with default values
@@ -195,7 +195,7 @@
self.size = (opts.l3_size)
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/parsec/configs/system/system.py b/src/parsec/configs/system/system.py
index f2a5b4f..5becf46 100644
--- a/src/parsec/configs/system/system.py
+++ b/src/parsec/configs/system/system.py
@@ -68,7 +68,7 @@
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus, num_cpus)
@@ -207,9 +207,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
# Memory latency: Using the smaller number from [3]: 96ns
def createMemoryControllersDDR4(self):
@@ -224,7 +224,7 @@
interface.range = ranges[i]
ctrl = MemCtrl()
ctrl.dram = interface
- ctrl.port = self.membus.master
+ ctrl.port = self.membus.mem_side_ports
mem_ctrls.append(ctrl)
self.mem_cntrls = mem_ctrls + [kernel_controller]
@@ -233,7 +233,7 @@
interface.range = self.mem_ranges[0]
ctrl = MemCtrl()
ctrl.dram = interface
- ctrl.port = self.membus.master
+ ctrl.port = self.membus.mem_side_ports
return ctrl
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
@@ -268,8 +268,8 @@
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -289,8 +289,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -309,8 +309,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
diff --git a/src/simple/Makefile b/src/simple/Makefile
index f3113aa..60c7fa8 100644
--- a/src/simple/Makefile
+++ b/src/simple/Makefile
@@ -54,6 +54,7 @@
# Common to C and C++.
CCFLAGS = \
-I $(GEM5_ROOT)/include/ \
+ -I $(GEM5_ROOT)/util/m5/src/ \
-O3 \
-Wall \
-Werror \
@@ -89,6 +90,8 @@
OUT_DIR_BASE = out
OUT_DIR = $(OUT_DIR_BASE)/$(ISA)
OUT_BARE_DIR = $(OUT_DIR)/bare
+OUT_SQUASHFS_DIR = $(OUT_DIR)/squashfs
+OUT_SQUASHFS_EXT = .squashfs
OUT_USER_DIR = $(OUT_DIR)/user
OBJ_EXT = .o
OUT_EXT = .out
@@ -131,6 +134,7 @@
# Calculated values.
BARE_OUTS = $(addprefix $(OUT_BARE_DIR)/, $(addsuffix $(OUT_EXT), $(BARE_INS) $(addprefix $(ISA)/,$(ISA_BARE_INS))))
+SQUASHFS_OUTS = $(addprefix $(OUT_USER_DIR)/, $(addsuffix $(OUT_EXT), $(USER_INS)))
USER_OUTS = $(addprefix $(OUT_USER_DIR)/, $(addsuffix $(OUT_EXT), $(USER_INS)))
.PHONY: all bare clean mkdir user
@@ -156,6 +160,14 @@
$(OUT_USER_DIR)/%$(OUT_EXT): %$(IN_EXT_C) $(M5OP_OBJ)
$(CC) $(CFLAGS_USER) -o '$@' $^ $(LDFLAGS_USER)
+$(OUT_SQUASHFS_DIR)/%$(OUT_SQUASHFS_EXT): $(OUT_USER_DIR)/%$(OUT_EXT)
+ @# Create dev so that the kernel can automount CONFIG_DEVTMPFS=y.
+ mkdir -p '$(basename $@)/sbin' '$(basename $@)/dev'
+ cp '$<' '$(basename $@)/sbin/init'
+ @# Existing squashfs files don't get updated otherwise.
+ rm -f '$@'
+ mksquashfs '$(basename $@)' '$@'
+
$(OUT_BARE_DIR)/%$(OUT_EXT): %$(IN_EXT_CXX) $(M5OP_OBJ) $(BOOTLOADER_OBJ)
$(CXX) $(CXXFLAGS_BARE) -o '$@' $^
diff --git a/src/simple/README.md b/src/simple/README.md
deleted file mode 100644
index c6b1ced..0000000
--- a/src/simple/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Simple single input source userland/baremetal executables in C/C++ etc.
-
-How to build explained in `make help`.
diff --git a/src/simple/m5_exit_addr.c b/src/simple/m5_exit_addr.c
new file mode 100644
index 0000000..18cfefa
--- /dev/null
+++ b/src/simple/m5_exit_addr.c
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <gem5/m5ops.h>
+#include <m5_mmap.h>
+
+#include <stdio.h>
+
+int main(void) {
+#if defined(__aarch64__)
+ m5op_addr = 0x10010000;
+#endif
+ map_m5_mem();
+ m5_exit_addr(0);
+}
diff --git a/src/spec-2006/README.md b/src/spec-2006/README.md
index d4f9ddf..48d05df 100644
--- a/src/spec-2006/README.md
+++ b/src/spec-2006/README.md
@@ -115,4 +115,4 @@
## Working Status
Status of these benchmarks runs with respect to gem5-20, linux kernel version
4.19.83 and gcc version 7.5.0 can be found
-[here](https://www.gem5.org/documentation/benchmark_status/#spec-2006-tests)
+[here](https://www.gem5.org/documentation/benchmark_status/gem5-20#spec-2006-tests)
diff --git a/src/spec-2006/configs/run_spec.py b/src/spec-2006/configs/run_spec.py
index b35d3d2..0a54e44 100644
--- a/src/spec-2006/configs/run_spec.py
+++ b/src/spec-2006/configs/run_spec.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2019 The Regents of the University of California.
+# Copyright (c) 2020 The Regents of the University of California.
# All rights reserved.
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
@@ -76,8 +77,7 @@
import argparse
-from system import MySystem
-
+from system import *
def writeBenchScript(dir, benchmark_name, size, output_path):
"""
@@ -97,6 +97,7 @@
parser.add_argument("disk", type = str,
help = "Path to the disk image containing SPEC benchmarks")
parser.add_argument("cpu", type = str, help = "Name of the detailed CPU")
+ parser.add_argument("mem_sys", type = str, help = "Name of the memory system")
parser.add_argument("benchmark", type = str,
help = "Name of the SPEC benchmark")
parser.add_argument("size", type = str,
@@ -134,13 +135,25 @@
benchmark_name = benchmark_name[:-6]
return benchmark_name
-def create_system(linux_kernel_path, disk_image_path, detailed_cpu_model):
+def create_system(linux_kernel_path, disk_image_path, detailed_cpu_model, memory_system):
# create the system we are going to simulate
- system = MySystem(kernel = linux_kernel_path,
- disk = disk_image_path,
- num_cpus = 1, # run the benchmark in a single thread
- no_kvm = False,
- TimingCPUModel = detailed_cpu_model)
+ ruby_protocols = [ "MI_example", "MESI_Two_Level", "MOESI_CMP_directory"]
+ if memory_system == 'classic':
+ system = MySystem(kernel = linux_kernel_path,
+ disk = disk_image_path,
+ num_cpus = 1, # run the benchmark in a single thread
+ no_kvm = False,
+ TimingCPUModel = detailed_cpu_model)
+ elif memory_system in ruby_protocols:
+ system = MyRubySystem(kernel = linux_kernel_path,
+ disk = disk_image_path,
+ num_cpus = 1, # run the benchmark in a single thread
+ mem_sys = memory_system,
+ no_kvm = False,
+ TimingCPUModel = detailed_cpu_model)
+ else:
+ m5.fatal("Bad option for mem_sys, should be "
+ "{}, or 'classic'".format(', '.join(ruby_protocols)))
# For workitems to work correctly
# This will cause the simulator to exit simulation when the first work
@@ -209,6 +222,7 @@
args = parse_arguments()
cpu_name = args.cpu
+ mem_sys = args.mem_sys
benchmark_name = getBenchmarkName(args.benchmark)
benchmark_size = args.size
linux_kernel_path = args.kernel
@@ -238,9 +252,9 @@
exit(1)
root, system = create_system(linux_kernel_path, disk_image_path,
- detailed_cpu)
+ detailed_cpu, mem_sys)
- # Create and pass a script to the simulated system to run the reuired
+ # Create and pass a script to the simulated system to run the required
# benchmark
system.readfile = writeBenchScript(m5.options.outdir, benchmark_name,
benchmark_size, output_dir)
diff --git a/src/spec-2006/configs/system/MESI_Two_Level.py b/src/spec-2006/configs/system/MESI_Two_Level.py
new file mode 100644
index 0000000..0513041
--- /dev/null
+++ b/src/spec-2006/configs/system/MESI_Two_Level.py
@@ -0,0 +1,341 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020 The Regents of the University of California.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+""" This file creates a set of Ruby caches for the MESI TWO Level protocol
+This protocol models two level cache hierarchy. The L1 cache is split into
+instruction and data cache.
+
+This system support the memory size of up to 3GB.
+
+"""
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import math
+
+from m5.defines import buildEnv
+from m5.util import fatal, panic
+
+from m5.objects import *
+
+class MESITwoLevelCache(RubySystem):
+
+ def __init__(self):
+ if buildEnv['PROTOCOL'] != 'MESI_Two_Level':
+ fatal("This system assumes MESI_Two_Level!")
+
+ super(MESITwoLevelCache, self).__init__()
+
+ self._numL2Caches = 8
+
+ def setup(self, system, cpus, mem_ctrls, dma_ports, iobus):
+ """Set up the Ruby cache subsystem. Note: This can't be done in the
+ constructor because many of these items require a pointer to the
+ ruby system (self). This causes infinite recursion in initialize()
+ if we do this in the __init__.
+ """
+ # Ruby's global network.
+ self.network = MyNetwork(self)
+
+ # MESI_Two_Level example uses 5 virtual networks
+ self.number_of_virtual_networks = 5
+ self.network.number_of_virtual_networks = 5
+
+ # There is a single global list of all of the controllers to make it
+ # easier to connect everything to the global network. This can be
+ # customized depending on the topology/network requirements.
+ # L1 caches are private to a core, hence there are one L1 cache per CPU core.
+ # The number of L2 caches are dependent to the architecture.
+ self.controllers = \
+ [L1Cache(system, self, cpu, self._numL2Caches) for cpu in cpus] + \
+ [L2Cache(system, self, self._numL2Caches) for num in range(self._numL2Caches)] + \
+ [DirController(self, system.mem_ranges, mem_ctrls)] + \
+ [DMAController(self) for i in range(len(dma_ports))]
+
+ # Create one sequencer per CPU and dma controller.
+ # Sequencers for other controllers can be here here.
+ self.sequencers = [RubySequencer(version = i,
+ # I/D cache is combined and grab from ctrl
+ icache = self.controllers[i].L1Icache,
+ dcache = self.controllers[i].L1Dcache,
+ clk_domain = self.controllers[i].clk_domain,
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
+ ) for i in range(len(cpus))] + \
+ [DMASequencer(version = i,
+ in_port = port)
+ for i,port in enumerate(dma_ports)
+ ]
+
+ for i,c in enumerate(self.controllers[:len(cpus)]):
+ c.sequencer = self.sequencers[i]
+
+ #Connecting the DMA sequencer to DMA controller
+ for i,d in enumerate(self.controllers[-len(dma_ports):]):
+ i += len(cpus)
+ d.dma_sequencer = self.sequencers[i]
+
+ self.num_of_sequencers = len(self.sequencers)
+
+ # Create the network and connect the controllers.
+ # NOTE: This is quite different if using Garnet!
+ self.network.connectControllers(self.controllers)
+ self.network.setup_buffers()
+
+ # Set up a proxy port for the system_port. Used for load binaries and
+ # other functional-only things.
+ self.sys_port_proxy = RubyPortProxy()
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
+
+ # Connect the cpu's cache, interrupt, and TLB ports to Ruby
+ for i,cpu in enumerate(cpus):
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
+ cpu.createInterruptController()
+ isa = buildEnv['TARGET_ISA']
+ if isa == 'x86':
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
+ if isa == 'x86' or isa == 'arm':
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
+
+class L1Cache(L1Cache_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, system, ruby_system, cpu, num_l2Caches):
+ """Creating L1 cache controller. Consist of both instruction
+ and data cache. The size of data cache is 512KB and
+ 8-way set associative. The instruction cache is 32KB,
+ 2-way set associative.
+ """
+ super(L1Cache, self).__init__()
+
+ self.version = self.versionCount()
+ block_size_bits = int(math.log(system.cache_line_size, 2))
+ l1i_size = '32kB'
+ l1i_assoc = '2'
+ l1d_size = '512kB'
+ l1d_assoc = '8'
+ # This is the cache memory object that stores the cache data and tags
+ self.L1Icache = RubyCache(size = l1i_size,
+ assoc = l1i_assoc,
+ start_index_bit = block_size_bits ,
+ is_icache = True)
+ self.L1Dcache = RubyCache(size = l1d_size,
+ assoc = l1d_assoc,
+ start_index_bit = block_size_bits,
+ is_icache = False)
+ self.l2_select_num_bits = int(math.log(num_l2Caches , 2))
+ self.clk_domain = cpu.clk_domain
+ self.prefetcher = RubyPrefetcher()
+ self.send_evictions = self.sendEvicts(cpu)
+ self.transitions_per_cycle = 4
+ self.enable_prefetch = False
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def getBlockSizeBits(self, system):
+ bits = int(math.log(system.cache_line_size, 2))
+ if 2**bits != system.cache_line_size.value:
+ panic("Cache line size not a power of 2!")
+ return bits
+
+ def sendEvicts(self, cpu):
+ """True if the CPU model or ISA requires sending evictions from caches
+ to the CPU. Two scenarios warrant forwarding evictions to the CPU:
+ 1. The O3 model must keep the LSQ coherent with the caches
+ 2. The x86 mwait instruction is built on top of coherence
+ 3. The local exclusive monitor in ARM systems
+ """
+ if type(cpu) is DerivO3CPU or \
+ buildEnv['TARGET_ISA'] in ('x86', 'arm'):
+ return True
+ return False
+
+ def connectQueues(self, ruby_system):
+ """Connect all of the queues for this controller.
+ """
+ self.mandatoryQueue = MessageBuffer()
+ self.requestFromL1Cache = MessageBuffer()
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
+ self.responseFromL1Cache = MessageBuffer()
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
+ self.unblockFromL1Cache = MessageBuffer()
+ self.unblockFromL1Cache.out_port = ruby_system.network.in_port
+
+ self.optionalQueue = MessageBuffer()
+
+ self.requestToL1Cache = MessageBuffer()
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
+ self.responseToL1Cache = MessageBuffer()
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
+
+class L2Cache(L2Cache_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, system, ruby_system, num_l2Caches):
+
+ super(L2Cache, self).__init__()
+
+ self.version = self.versionCount()
+ # This is the cache memory object that stores the cache data and tags
+ self.L2cache = RubyCache(size = '1 MB',
+ assoc = 16,
+ start_index_bit = self.getBlockSizeBits(system,
+ num_l2Caches))
+
+ self.transitions_per_cycle = '4'
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def getBlockSizeBits(self, system, num_l2caches):
+ l2_bits = int(math.log(num_l2caches, 2))
+ bits = int(math.log(system.cache_line_size, 2)) + l2_bits
+ return bits
+
+
+ def connectQueues(self, ruby_system):
+ """Connect all of the queues for this controller.
+ """
+ self.DirRequestFromL2Cache = MessageBuffer()
+ self.DirRequestFromL2Cache.out_port = ruby_system.network.in_port
+ self.L1RequestFromL2Cache = MessageBuffer()
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
+ self.responseFromL2Cache = MessageBuffer()
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
+ self.unblockToL2Cache = MessageBuffer()
+ self.unblockToL2Cache.in_port = ruby_system.network.out_port
+ self.L1RequestToL2Cache = MessageBuffer()
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
+ self.responseToL2Cache = MessageBuffer()
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
+
+
+class DirController(Directory_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system, ranges, mem_ctrls):
+ """ranges are the memory ranges assigned to this controller.
+ """
+ if len(mem_ctrls) > 1:
+ panic("This cache system can only be connected to one mem ctrl")
+ super(DirController, self).__init__()
+ self.version = self.versionCount()
+ self.addr_ranges = ranges
+ self.ruby_system = ruby_system
+ self.directory = RubyDirectoryMemory()
+ # Connect this directory to the memory side.
+ self.memory_out_port = mem_ctrls[0].port
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.requestToDir = MessageBuffer()
+ self.requestToDir.in_port = ruby_system.network.out_port
+ self.responseToDir = MessageBuffer()
+ self.responseToDir.in_port = ruby_system.network.out_port
+ self.responseFromDir = MessageBuffer()
+ self.responseFromDir.out_port = ruby_system.network.in_port
+ self.requestToMemory = MessageBuffer()
+ self.responseFromMemory = MessageBuffer()
+
+class DMAController(DMA_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system):
+ super(DMAController, self).__init__()
+ self.version = self.versionCount()
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.mandatoryQueue = MessageBuffer()
+ self.responseFromDir = MessageBuffer(ordered = True)
+ self.responseFromDir.in_port = ruby_system.network.out_port
+ self.requestToDir = MessageBuffer()
+ self.requestToDir.out_port = ruby_system.network.in_port
+
+
+class MyNetwork(SimpleNetwork):
+ """A simple point-to-point network. This doesn't not use garnet.
+ """
+
+ def __init__(self, ruby_system):
+ super(MyNetwork, self).__init__()
+ self.netifs = []
+ self.ruby_system = ruby_system
+
+ def connectControllers(self, controllers):
+ """Connect all of the controllers to routers and connec the routers
+ together in a point-to-point network.
+ """
+ # Create one router/switch per controller in the system
+ self.routers = [Switch(router_id = i) for i in range(len(controllers))]
+
+ # Make a link from each controller to the router. The link goes
+ # externally to the network.
+ self.ext_links = [SimpleExtLink(link_id=i, ext_node=c,
+ int_node=self.routers[i])
+ for i, c in enumerate(controllers)]
+
+ # Make an "internal" link (internal to the network) between every pair
+ # of routers.
+ link_count = 0
+ self.int_links = []
+ for ri in self.routers:
+ for rj in self.routers:
+ if ri == rj: continue # Don't connect a router to itself!
+ link_count += 1
+ self.int_links.append(SimpleIntLink(link_id = link_count,
+ src_node = ri,
+ dst_node = rj))
diff --git a/src/spec-2006/configs/system/MI_example_caches.py b/src/spec-2006/configs/system/MI_example_caches.py
new file mode 100644
index 0000000..b8fd7b4
--- /dev/null
+++ b/src/spec-2006/configs/system/MI_example_caches.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015 Jason Power
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Jason Power
+
+""" This file creates a set of Ruby caches, the Ruby network, and a simple
+point-to-point topology.
+See Part 3 in the Learning gem5 book: learning.gem5.org/book/part3
+You can change simple_ruby to import from this file instead of from msi_caches
+to use the MI_example protocol instead of MSI.
+
+IMPORTANT: If you modify this file, it's likely that the Learning gem5 book
+ also needs to be updated. For now, email Jason <jason@lowepower.com>
+
+"""
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import math
+
+from m5.defines import buildEnv
+from m5.util import fatal, panic
+
+from m5.objects import *
+
+class MIExampleSystem(RubySystem):
+
+ def __init__(self):
+ if buildEnv['PROTOCOL'] != 'MI_example':
+ fatal("This system assumes MI_example!")
+
+ super(MIExampleSystem, self).__init__()
+
+ def setup(self, system, cpus, mem_ctrls, dma_ports, iobus):
+ """Set up the Ruby cache subsystem. Note: This can't be done in the
+ constructor because many of these items require a pointer to the
+ ruby system (self). This causes infinite recursion in initialize()
+ if we do this in the __init__.
+ """
+ # Ruby's global network.
+ self.network = MyNetwork(self)
+
+ # MI example uses 5 virtual networks
+ self.number_of_virtual_networks = 5
+ self.network.number_of_virtual_networks = 5
+
+ # There is a single global list of all of the controllers to make it
+ # easier to connect everything to the global network. This can be
+ # customized depending on the topology/network requirements.
+ # Create one controller for each L1 cache (and the cache mem obj.)
+ # Create a single directory controller (Really the memory cntrl)
+ self.controllers = \
+ [L1Cache(system, self, cpu) for cpu in cpus] + \
+ [DirController(self, system.mem_ranges, mem_ctrls)] + \
+ [DMAController(self) for i in range(len(dma_ports))]
+
+ # Create one sequencer per CPU. In many systems this is more
+ # complicated since you have to create sequencers for DMA controllers
+ # and other controllers, too.
+ self.sequencers = [RubySequencer(version = i,
+ # I/D cache is combined and grab from ctrl
+ icache = self.controllers[i].cacheMemory,
+ dcache = self.controllers[i].cacheMemory,
+ clk_domain = self.controllers[i].clk_domain,
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
+ ) for i in range(len(cpus))] + \
+ [DMASequencer(version = i,
+ in_port = port)
+ for i,port in enumerate(dma_ports)
+ ]
+
+ for i,c in enumerate(self.controllers[0:len(cpus)]):
+ c.sequencer = self.sequencers[i]
+
+ for i,d in enumerate(self.controllers[-len(dma_ports):]):
+ i += len(cpus)
+ d.dma_sequencer = self.sequencers[i]
+
+ self.num_of_sequencers = len(self.sequencers)
+
+ # Create the network and connect the controllers.
+ # NOTE: This is quite different if using Garnet!
+ self.network.connectControllers(self.controllers)
+ self.network.setup_buffers()
+
+ # Set up a proxy port for the system_port. Used for load binaries and
+ # other functional-only things.
+ self.sys_port_proxy = RubyPortProxy()
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
+
+ # Connect the cpu's cache, interrupt, and TLB ports to Ruby
+ for i,cpu in enumerate(cpus):
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
+ cpu.createInterruptController()
+ isa = buildEnv['TARGET_ISA']
+ if isa == 'x86':
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
+ if isa == 'x86' or isa == 'arm':
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
+
+
+class L1Cache(L1Cache_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, system, ruby_system, cpu):
+ """CPUs are needed to grab the clock domain and system is needed for
+ the cache block size.
+ """
+ super(L1Cache, self).__init__()
+
+ self.version = self.versionCount()
+ # This is the cache memory object that stores the cache data and tags
+ self.cacheMemory = RubyCache(size = '16kB',
+ assoc = 8,
+ start_index_bit = self.getBlockSizeBits(system))
+ self.clk_domain = cpu.clk_domain
+ self.send_evictions = self.sendEvicts(cpu)
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def getBlockSizeBits(self, system):
+ bits = int(math.log(system.cache_line_size, 2))
+ if 2**bits != system.cache_line_size.value:
+ panic("Cache line size not a power of 2!")
+ return bits
+
+ def sendEvicts(self, cpu):
+ """True if the CPU model or ISA requires sending evictions from caches
+ to the CPU. Two scenarios warrant forwarding evictions to the CPU:
+ 1. The O3 model must keep the LSQ coherent with the caches
+ 2. The x86 mwait instruction is built on top of coherence
+ 3. The local exclusive monitor in ARM systems
+ """
+ if type(cpu) is DerivO3CPU or \
+ buildEnv['TARGET_ISA'] in ('x86', 'arm'):
+ return True
+ return False
+
+ def connectQueues(self, ruby_system):
+ """Connect all of the queues for this controller.
+ """
+ self.mandatoryQueue = MessageBuffer()
+ self.requestFromCache = MessageBuffer(ordered = True)
+ self.requestFromCache.out_port = ruby_system.network.in_port
+ self.responseFromCache = MessageBuffer(ordered = True)
+ self.responseFromCache.out_port = ruby_system.network.in_port
+ self.forwardToCache = MessageBuffer(ordered = True)
+ self.forwardToCache.in_port = ruby_system.network.out_port
+ self.responseToCache = MessageBuffer(ordered = True)
+ self.responseToCache.in_port = ruby_system.network.out_port
+
+class DirController(Directory_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system, ranges, mem_ctrls):
+ """ranges are the memory ranges assigned to this controller.
+ """
+ if len(mem_ctrls) > 1:
+ panic("This cache system can only be connected to one mem ctrl")
+ super(DirController, self).__init__()
+ self.version = self.versionCount()
+ self.addr_ranges = ranges
+ self.ruby_system = ruby_system
+ self.directory = RubyDirectoryMemory()
+ # Connect this directory to the memory side.
+ self.memory_out_port = mem_ctrls[0].port
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.requestToDir = MessageBuffer(ordered = True)
+ self.requestToDir.in_port = ruby_system.network.out_port
+ self.dmaRequestToDir = MessageBuffer(ordered = True)
+ self.dmaRequestToDir.in_port = ruby_system.network.out_port
+
+ self.responseFromDir = MessageBuffer()
+ self.responseFromDir.out_port = ruby_system.network.in_port
+ self.dmaResponseFromDir = MessageBuffer(ordered = True)
+ self.dmaResponseFromDir.out_port = ruby_system.network.in_port
+ self.forwardFromDir = MessageBuffer()
+ self.forwardFromDir.out_port = ruby_system.network.in_port
+ self.requestToMemory = MessageBuffer()
+ self.responseFromMemory = MessageBuffer()
+
+class DMAController(DMA_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system):
+ super(DMAController, self).__init__()
+ self.version = self.versionCount()
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.mandatoryQueue = MessageBuffer()
+ self.requestToDir = MessageBuffer()
+ self.requestToDir.out_port = ruby_system.network.in_port
+ self.responseFromDir = MessageBuffer(ordered = True)
+ self.responseFromDir.in_port = ruby_system.network.out_port
+
+
+class MyNetwork(SimpleNetwork):
+ """A simple point-to-point network. This doesn't not use garnet.
+ """
+
+ def __init__(self, ruby_system):
+ super(MyNetwork, self).__init__()
+ self.netifs = []
+ self.ruby_system = ruby_system
+
+ def connectControllers(self, controllers):
+ """Connect all of the controllers to routers and connec the routers
+ together in a point-to-point network.
+ """
+ # Create one router/switch per controller in the system
+ self.routers = [Switch(router_id = i) for i in range(len(controllers))]
+
+ # Make a link from each controller to the router. The link goes
+ # externally to the network.
+ self.ext_links = [SimpleExtLink(link_id=i, ext_node=c,
+ int_node=self.routers[i])
+ for i, c in enumerate(controllers)]
+
+ # Make an "internal" link (internal to the network) between every pair
+ # of routers.
+ link_count = 0
+ self.int_links = []
+ for ri in self.routers:
+ for rj in self.routers:
+ if ri == rj: continue # Don't connect a router to itself!
+ link_count += 1
+ self.int_links.append(SimpleIntLink(link_id = link_count,
+ src_node = ri,
+ dst_node = rj))
diff --git a/src/spec-2006/configs/system/MOESI_CMP_directory.py b/src/spec-2006/configs/system/MOESI_CMP_directory.py
new file mode 100644
index 0000000..c657df7
--- /dev/null
+++ b/src/spec-2006/configs/system/MOESI_CMP_directory.py
@@ -0,0 +1,350 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020 The Regents of the University of California.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+""" This file creates a set of Ruby caches for the MOESI CMP directory
+protocol.
+This protocol models two level cache hierarchy. The L1 cache is split into
+instruction and data cache.
+
+This system support the memory size of up to 3GB.
+
+"""
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import math
+
+from m5.defines import buildEnv
+from m5.util import fatal, panic
+
+from m5.objects import *
+
+class MOESICMPDirCache(RubySystem):
+
+ def __init__(self):
+ if buildEnv['PROTOCOL'] != 'MOESI_CMP_directory':
+ fatal("This system assumes MOESI_CMP_directory!")
+
+ super(MOESICMPDirCache, self).__init__()
+
+ self._numL2Caches = 8
+
+ def setup(self, system, cpus, mem_ctrls, dma_ports, iobus):
+ """Set up the Ruby cache subsystem. Note: This can't be done in the
+ constructor because many of these items require a pointer to the
+ ruby system (self). This causes infinite recursion in initialize()
+ if we do this in the __init__.
+ """
+ # Ruby's global network.
+ self.network = MyNetwork(self)
+
+ # MOESI_CMP_directory example uses 3 virtual networks
+ self.number_of_virtual_networks = 3
+ self.network.number_of_virtual_networks = 3
+
+ # There is a single global list of all of the controllers to make it
+ # easier to connect everything to the global network. This can be
+ # customized depending on the topology/network requirements.
+ # L1 caches are private to a core, hence there are one L1 cache per CPU core.
+ # The number of L2 caches are dependent to the architecture.
+ self.controllers = \
+ [L1Cache(system, self, cpu, self._numL2Caches) for cpu in cpus] + \
+ [L2Cache(system, self, self._numL2Caches) for num in range(self._numL2Caches)] + \
+ [DirController(self, system.mem_ranges, mem_ctrls)] + \
+ [DMAController(self) for i in range(len(dma_ports))]
+
+ # Create one sequencer per CPU and dma controller.
+ # Sequencers for other controllers can be here here.
+ self.sequencers = [RubySequencer(version = i,
+ # I/D cache is combined and grab from ctrl
+ icache = self.controllers[i].L1Icache,
+ dcache = self.controllers[i].L1Dcache,
+ clk_domain = self.controllers[i].clk_domain,
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
+ ) for i in range(len(cpus))] + \
+ [DMASequencer(version = i,
+ in_port = port)
+ for i,port in enumerate(dma_ports)
+ ]
+
+ for i,c in enumerate(self.controllers[:len(cpus)]):
+ c.sequencer = self.sequencers[i]
+
+ #Connecting the DMA sequencer to DMA controller
+ for i,d in enumerate(self.controllers[-len(dma_ports):]):
+ i += len(cpus)
+ d.dma_sequencer = self.sequencers[i]
+
+ self.num_of_sequencers = len(self.sequencers)
+
+ # Create the network and connect the controllers.
+ # NOTE: This is quite different if using Garnet!
+ self.network.connectControllers(self.controllers)
+ self.network.setup_buffers()
+
+ # Set up a proxy port for the system_port. Used for load binaries and
+ # other functional-only things.
+ self.sys_port_proxy = RubyPortProxy()
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
+
+ # Connect the cpu's cache, interrupt, and TLB ports to Ruby
+ for i,cpu in enumerate(cpus):
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
+ cpu.createInterruptController()
+ isa = buildEnv['TARGET_ISA']
+ if isa == 'x86':
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
+ if isa == 'x86' or isa == 'arm':
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
+
+
+class L1Cache(L1Cache_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, system, ruby_system, cpu, num_l2Caches):
+ """Creating L1 cache controller. Consist of both instruction
+ and data cache. The size of data cache is 512KB and
+ 8-way set associative. The instruction cache is 32KB,
+ 2-way set associative.
+ """
+ super(L1Cache, self).__init__()
+
+ self.version = self.versionCount()
+ block_size_bits = int(math.log(system.cache_line_size, 2))
+ l1i_size = '32kB'
+ l1i_assoc = '2'
+ l1d_size = '512kB'
+ l1d_assoc = '8'
+ # This is the cache memory object that stores the cache data and tags
+ self.L1Icache = RubyCache(size = l1i_size,
+ assoc = l1i_assoc,
+ start_index_bit = block_size_bits ,
+ is_icache = True,
+ dataAccessLatency = 1,
+ tagAccessLatency = 1)
+ self.L1Dcache = RubyCache(size = l1d_size,
+ assoc = l1d_assoc,
+ start_index_bit = block_size_bits,
+ is_icache = False,
+ dataAccessLatency = 1,
+ tagAccessLatency = 1)
+ self.clk_domain = cpu.clk_domain
+ self.prefetcher = RubyPrefetcher()
+ self.send_evictions = self.sendEvicts(cpu)
+ self.transitions_per_cycle = 4
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def getBlockSizeBits(self, system):
+ bits = int(math.log(system.cache_line_size, 2))
+ if 2**bits != system.cache_line_size.value:
+ panic("Cache line size not a power of 2!")
+ return bits
+
+ def sendEvicts(self, cpu):
+ """True if the CPU model or ISA requires sending evictions from caches
+ to the CPU. Two scenarios warrant forwarding evictions to the CPU:
+ 1. The O3 model must keep the LSQ coherent with the caches
+ 2. The x86 mwait instruction is built on top of coherence
+ 3. The local exclusive monitor in ARM systems
+ """
+ if type(cpu) is DerivO3CPU or \
+ buildEnv['TARGET_ISA'] in ('x86', 'arm'):
+ return True
+ return False
+
+ def connectQueues(self, ruby_system):
+ """Connect all of the queues for this controller.
+ """
+ self.mandatoryQueue = MessageBuffer()
+ self.requestFromL1Cache = MessageBuffer()
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
+ self.responseFromL1Cache = MessageBuffer()
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
+ self.requestToL1Cache = MessageBuffer()
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
+ self.responseToL1Cache = MessageBuffer()
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
+ self.triggerQueue = MessageBuffer(ordered = True)
+
+class L2Cache(L2Cache_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, system, ruby_system, num_l2Caches):
+
+ super(L2Cache, self).__init__()
+
+ self.version = self.versionCount()
+ # This is the cache memory object that stores the cache data and tags
+ self.L2cache = RubyCache(size = '1 MB',
+ assoc = 16,
+ start_index_bit = self.getL2StartIdx(system,
+ num_l2Caches),
+ dataAccessLatency = 20,
+ tagAccessLatency = 20)
+
+ self.transitions_per_cycle = '4'
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def getL2StartIdx(self, system, num_l2caches):
+ l2_bits = int(math.log(num_l2caches, 2))
+ bits = int(math.log(system.cache_line_size, 2)) + l2_bits
+ return bits
+
+
+ def connectQueues(self, ruby_system):
+ """Connect all of the queues for this controller.
+ """
+ self.GlobalRequestFromL2Cache = MessageBuffer()
+ self.GlobalRequestFromL2Cache.out_port = ruby_system.network.in_port
+ self.L1RequestFromL2Cache = MessageBuffer()
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
+ self.responseFromL2Cache = MessageBuffer()
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
+
+ self.GlobalRequestToL2Cache = MessageBuffer()
+ self.GlobalRequestToL2Cache.in_port = ruby_system.network.out_port
+ self.L1RequestToL2Cache = MessageBuffer()
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
+ self.responseToL2Cache = MessageBuffer()
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
+ self.triggerQueue = MessageBuffer(ordered = True)
+
+
+class DirController(Directory_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system, ranges, mem_ctrls):
+ """ranges are the memory ranges assigned to this controller.
+ """
+ if len(mem_ctrls) > 1:
+ panic("This cache system can only be connected to one mem ctrl")
+ super(DirController, self).__init__()
+ self.version = self.versionCount()
+ self.addr_ranges = ranges
+ self.ruby_system = ruby_system
+ self.directory = RubyDirectoryMemory()
+ # Connect this directory to the memory side.
+ self.memory_out_port = mem_ctrls[0].port
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.requestToDir = MessageBuffer()
+ self.requestToDir.in_port = ruby_system.network.out_port
+ self.responseToDir = MessageBuffer()
+ self.responseToDir.in_port = ruby_system.network.out_port
+ self.responseFromDir = MessageBuffer()
+ self.responseFromDir.out_port = ruby_system.network.in_port
+ self.forwardFromDir = MessageBuffer()
+ self.forwardFromDir.out_port = ruby_system.network.in_port
+ self.requestToMemory = MessageBuffer()
+ self.responseFromMemory = MessageBuffer()
+
+class DMAController(DMA_Controller):
+
+ _version = 0
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(self, ruby_system):
+ super(DMAController, self).__init__()
+ self.version = self.versionCount()
+ self.ruby_system = ruby_system
+ self.connectQueues(ruby_system)
+
+ def connectQueues(self, ruby_system):
+ self.mandatoryQueue = MessageBuffer()
+ self.responseFromDir = MessageBuffer()
+ self.responseFromDir.in_port = ruby_system.network.out_port
+ self.reqToDir = MessageBuffer()
+ self.reqToDir.out_port = ruby_system.network.in_port
+ self.respToDir = MessageBuffer()
+ self.respToDir.out_port = ruby_system.network.in_port
+ self.triggerQueue = MessageBuffer(ordered = True)
+
+
+class MyNetwork(SimpleNetwork):
+ """A simple point-to-point network. This doesn't not use garnet.
+ """
+
+ def __init__(self, ruby_system):
+ super(MyNetwork, self).__init__()
+ self.netifs = []
+ self.ruby_system = ruby_system
+
+ def connectControllers(self, controllers):
+ """Connect all of the controllers to routers and connec the routers
+ together in a point-to-point network.
+ """
+ # Create one router/switch per controller in the system
+ self.routers = [Switch(router_id = i) for i in range(len(controllers))]
+
+ # Make a link from each controller to the router. The link goes
+ # externally to the network.
+ self.ext_links = [SimpleExtLink(link_id=i, ext_node=c,
+ int_node=self.routers[i])
+ for i, c in enumerate(controllers)]
+
+ # Make an "internal" link (internal to the network) between every pair
+ # of routers.
+ link_count = 0
+ self.int_links = []
+ for ri in self.routers:
+ for rj in self.routers:
+ if ri == rj: continue # Don't connect a router to itself!
+ link_count += 1
+ self.int_links.append(SimpleIntLink(link_id = link_count,
+ src_node = ri,
+ dst_node = rj))
diff --git a/src/spec-2006/configs/system/__init__.py b/src/spec-2006/configs/system/__init__.py
index 099d7c5..94e676f 100644
--- a/src/spec-2006/configs/system/__init__.py
+++ b/src/spec-2006/configs/system/__init__.py
@@ -28,3 +28,4 @@
# Authors: Jason Lowe-Power
from .system import MySystem
+from .ruby_system import MyRubySystem
diff --git a/src/spec-2006/configs/system/caches.py b/src/spec-2006/configs/system/caches.py
index dd604ac..f15b741 100644
--- a/src/spec-2006/configs/system/caches.py
+++ b/src/spec-2006/configs/system/caches.py
@@ -30,7 +30,8 @@
""" Caches with options for a simple gem5 configuration script
This file contains L1 I/D and L2 caches to be used in the simple
-gem5 configuration script.
+gem5 configuration script. It uses the SimpleOpts wrapper to set up command
+line options from each individual class.
"""
import m5
@@ -43,8 +44,11 @@
class PrefetchCache(Cache):
- def __init__(self):
+ def __init__(self, options = None):
super(PrefetchCache, self).__init__()
+ if not options or options.no_prefetchers:
+ return
+ self.prefetcher = StridePrefetcher()
class L1Cache(PrefetchCache):
"""Simple L1 Cache with default values"""
@@ -59,11 +63,10 @@
def __init__(self):
super(L1Cache, self).__init__()
- pass
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -116,12 +119,12 @@
"""
self.mmubus = L2XBar()
self.cpu_side = self.mmubus.mem_side_ports
- cpu.mmu.connectWalkerPorts(
- self.mmubus.cpu_side_ports, self.mmubus.cpu_side_ports)
+ for tlb in [cpu.itb, cpu.dtb]:
+ self.mmubus.cpu_side_ports = tlb.walker.port
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -140,10 +143,10 @@
super(L2Cache, self).__init__()
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L3Cache(Cache):
"""Simple L3 Cache bank with default values
@@ -166,8 +169,8 @@
super(L3Cache, self).__init__()
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/spec-2006/configs/system/fs_tools.py b/src/spec-2006/configs/system/fs_tools.py
index 99102ad..5e5e2df 100644
--- a/src/spec-2006/configs/system/fs_tools.py
+++ b/src/spec-2006/configs/system/fs_tools.py
@@ -33,8 +33,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
-
diff --git a/src/spec-2006/configs/system/ruby_system.py b/src/spec-2006/configs/system/ruby_system.py
new file mode 100755
index 0000000..e41d16b
--- /dev/null
+++ b/src/spec-2006/configs/system/ruby_system.py
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2016 Jason Lowe-Power
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Jason Lowe-Power
+
+import m5
+from m5.objects import *
+from m5.util import convert
+from .fs_tools import *
+
+
+class MyRubySystem(System):
+
+ def __init__(self, kernel, disk, mem_sys, num_cpus, TimingCPUModel, no_kvm=False):
+ super(MyRubySystem, self).__init__()
+ self._no_kvm = no_kvm
+
+ self._host_parallel = True
+
+ # Set up the clock domain and the voltage domain
+ self.clk_domain = SrcClockDomain()
+ self.clk_domain.clock = '2.3GHz'
+ self.clk_domain.voltage_domain = VoltageDomain()
+
+ self.mem_ranges = [AddrRange(Addr('3GB')), # All data
+ AddrRange(0xC0000000, size=0x100000), # For I/0
+ ]
+
+ self.initFS(num_cpus)
+
+ # Replace these paths with the path to your disk images.
+ # The first disk is the root disk. The second could be used for swap
+ # or anything else.
+ self.setDiskImages(disk, disk)
+
+ # Change this path to point to the kernel you want to use
+ self.workload.object_file = kernel
+ # Options specified on the kernel command line
+ boot_options = ['earlyprintk=ttyS0', 'console=ttyS0', 'lpj=7999923',
+ 'root=/dev/hda1']
+
+ self.workload.command_line = ' '.join(boot_options)
+
+ # Create the CPUs for our system.
+ self.createCPU(num_cpus,TimingCPUModel)
+
+ self.createMemoryControllersDDR4()
+
+ # Create the cache hierarchy for the system.
+ if mem_sys == 'MI_example':
+ from MI_example_caches import MIExampleSystem
+ self.caches = MIExampleSystem()
+ elif mem_sys == 'MESI_Two_Level':
+ from MESI_Two_Level import MESITwoLevelCache
+ self.caches = MESITwoLevelCache()
+ elif mem_sys == 'MOESI_CMP_directory':
+ from MOESI_CMP_directory import MOESICMPDirCache
+ self.caches = MOESICMPDirCache()
+ self.caches.setup(self, self.cpu, self.mem_cntrls,
+ [self.pc.south_bridge.ide.dma, self.iobus.mem_side_ports],
+ self.iobus)
+
+ if self._host_parallel:
+ # To get the KVM CPUs to run on different host CPUs
+ # Specify a different event queue for each CPU
+ for i,cpu in enumerate(self.cpu):
+ for obj in cpu.descendants():
+ obj.eventq_index = 0
+ cpu.eventq_index = i + 1
+
+ def getHostParallel(self):
+ return self._host_parallel
+
+ def totalInsts(self):
+ return sum([cpu.totalInsts() for cpu in self.cpu])
+
+ def createCPU(self, num_cpus, TimingCPUModel):
+ if self._no_kvm:
+ self.cpu = [AtomicSimpleCPU(cpu_id = i, switched_out = False)
+ for i in range(num_cpus)]
+ map(lambda c: c.createThreads(), self.cpu)
+ self.mem_mode = 'timing'
+
+ else:
+ # Note KVM needs a VM and atomic_noncaching
+ self.cpu = [X86KvmCPU(cpu_id = i)
+ for i in range(num_cpus)]
+ map(lambda c: c.createThreads(), self.cpu)
+ self.kvm_vm = KvmVM()
+ self.mem_mode = 'atomic_noncaching'
+
+ self.atomicCpu = [AtomicSimpleCPU(cpu_id = i,
+ switched_out = True)
+ for i in range(num_cpus)]
+ map(lambda c: c.createThreads(), self.atomicCpu)
+
+ self.detailed_cpu = [TimingCPUModel(cpu_id = i,
+ switched_out = True)
+ for i in range(num_cpus)]
+
+ map(lambda c: c.createThreads(), self.detailed_cpu)
+
+ def switchCpus(self, old, new):
+ assert(new[0].switchedOut())
+ m5.switchCpus(self, zip(old, new))
+
+ def setDiskImages(self, img_path_1, img_path_2):
+ disk0 = CowDisk(img_path_1)
+ disk2 = CowDisk(img_path_2)
+ self.pc.south_bridge.ide.disks = [disk0, disk2]
+
+ def createMemoryControllersDDR4(self):
+ self._createMemoryControllers(1, DDR4_2400_16x4)
+
+ def _createMemoryControllers(self, num, cls):
+ self.mem_cntrls = [
+ MemCtrl(dram = cls(range = self.mem_ranges[0]))
+ for i in range(num)
+ ]
+
+ def _createKernelMemoryController(self, cls):
+ return cls(range = self.mem_ranges[0],
+ port = self.membus.mem_side_ports)
+
+ def initFS(self, cpus):
+ self.pc = Pc()
+
+ self.workload = X86FsLinux()
+
+ # North Bridge
+ self.iobus = IOXBar()
+
+ # connect the io bus
+ # Note: pass in a reference to where Ruby will connect to in the future
+ # so the port isn't connected twice.
+ self.pc.attachIO(self.iobus, [self.pc.south_bridge.ide.dma])
+
+ self.intrctrl = IntrControl()
+
+ ###############################################
+
+ # Add in a Bios information structure.
+ self.workload.smbios_table.structures = [X86SMBiosBiosInformation()]
+
+ # Set up the Intel MP table
+ base_entries = []
+ ext_entries = []
+ for i in range(cpus):
+ bp = X86IntelMPProcessor(
+ local_apic_id = i,
+ local_apic_version = 0x14,
+ enable = True,
+ bootstrap = (i ==0))
+ base_entries.append(bp)
+ io_apic = X86IntelMPIOAPIC(
+ id = cpus,
+ version = 0x11,
+ enable = True,
+ address = 0xfec00000)
+ self.pc.south_bridge.io_apic.apic_id = io_apic.id
+ base_entries.append(io_apic)
+ pci_bus = X86IntelMPBus(bus_id = 0, bus_type='PCI ')
+ base_entries.append(pci_bus)
+ isa_bus = X86IntelMPBus(bus_id = 1, bus_type='ISA ')
+ base_entries.append(isa_bus)
+ connect_busses = X86IntelMPBusHierarchy(bus_id=1,
+ subtractive_decode=True, parent_bus=0)
+ ext_entries.append(connect_busses)
+ pci_dev4_inta = X86IntelMPIOIntAssignment(
+ interrupt_type = 'INT',
+ polarity = 'ConformPolarity',
+ trigger = 'ConformTrigger',
+ source_bus_id = 0,
+ source_bus_irq = 0 + (4 << 2),
+ dest_io_apic_id = io_apic.id,
+ dest_io_apic_intin = 16)
+ base_entries.append(pci_dev4_inta)
+ def assignISAInt(irq, apicPin):
+ assign_8259_to_apic = X86IntelMPIOIntAssignment(
+ interrupt_type = 'ExtInt',
+ polarity = 'ConformPolarity',
+ trigger = 'ConformTrigger',
+ source_bus_id = 1,
+ source_bus_irq = irq,
+ dest_io_apic_id = io_apic.id,
+ dest_io_apic_intin = 0)
+ base_entries.append(assign_8259_to_apic)
+ assign_to_apic = X86IntelMPIOIntAssignment(
+ interrupt_type = 'INT',
+ polarity = 'ConformPolarity',
+ trigger = 'ConformTrigger',
+ source_bus_id = 1,
+ source_bus_irq = irq,
+ dest_io_apic_id = io_apic.id,
+ dest_io_apic_intin = apicPin)
+ base_entries.append(assign_to_apic)
+ assignISAInt(0, 2)
+ assignISAInt(1, 1)
+ for i in range(3, 15):
+ assignISAInt(i, i)
+ self.workload.intel_mp_table.base_entries = base_entries
+ self.workload.intel_mp_table.ext_entries = ext_entries
+
+ entries = \
+ [
+ # Mark the first megabyte of memory as reserved
+ X86E820Entry(addr = 0, size = '639kB', range_type = 1),
+ X86E820Entry(addr = 0x9fc00, size = '385kB', range_type = 2),
+ # Mark the rest of physical memory as available
+ X86E820Entry(addr = 0x100000,
+ size = '%dB' % (self.mem_ranges[0].size() - 0x100000),
+ range_type = 1),
+ ]
+
+ # Reserve the last 16kB of the 32-bit address space for m5ops
+ entries.append(X86E820Entry(addr = 0xFFFF0000, size = '64kB',
+ range_type=2))
+
+ self.workload.e820_table.entries = entries
diff --git a/src/spec-2006/configs/system/system.py b/src/spec-2006/configs/system/system.py
index 2f39061..a5fbe16 100644
--- a/src/spec-2006/configs/system/system.py
+++ b/src/spec-2006/configs/system/system.py
@@ -60,15 +60,13 @@
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus, num_cpus)
-
# Replace these paths with the path to your disk images.
# The first disk is the root disk. The second could be used for swap
# or anything else.
-
self.setDiskImages(disk, disk)
# Change this path to point to the kernel you want to use
@@ -129,8 +127,8 @@
self.createCPUThreads(self.atomicCpu)
self.detailed_cpu = [TimingCPUModel(cpu_id = i,
- switched_out = True)
- for i in range(num_cpus)]
+ switched_out = True)
+ for i in range(num_cpus)]
self.createCPUThreads(self.detailed_cpu)
@@ -188,9 +186,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
# Memory latency: Using the smaller number from [3]: 96ns
def createMemoryControllersDDR4(self):
@@ -200,16 +198,13 @@
kernel_controller = self._createKernelMemoryController(cls)
ranges = self._getInterleaveRanges(self.mem_ranges[-1], num, 7, 20)
-
self.mem_cntrls = [
- cls(range = ranges[i],
- port = self.membus.master)
+ MemCtrl(dram = cls(range = ranges[i]), port = self.membus.mem_side_ports)
for i in range(num)
] + [kernel_controller]
def _createKernelMemoryController(self, cls):
- return cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ return MemCtrl(dram = cls(range = self.mem_ranges[0]), port = self.membus.mem_side_ports)
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
from math import log
@@ -242,8 +237,8 @@
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -263,8 +258,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -283,8 +278,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
diff --git a/src/spec-2017/README.md b/src/spec-2017/README.md
index b6b26b6..55367a0 100644
--- a/src/spec-2017/README.md
+++ b/src/spec-2017/README.md
@@ -116,5 +116,5 @@
## Working Status
Status of these benchmarks runs with respect to gem5-20, linux kernel version
4.19.83 and gcc version 7.5.0 can be found
-[here](https://www.gem5.org/documentation/benchmark_status/#spec-2017-tests)
+[here](https://www.gem5.org/documentation/benchmark_status/gem5-20#spec-2017-tests)
diff --git a/src/spec-2017/configs/system/caches.py b/src/spec-2017/configs/system/caches.py
index 5eb3d77..5b273eb 100644
--- a/src/spec-2017/configs/system/caches.py
+++ b/src/spec-2017/configs/system/caches.py
@@ -63,7 +63,7 @@
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -115,13 +115,13 @@
Note: This creates a new crossbar
"""
self.mmubus = L2XBar()
- self.cpu_side = self.mmubus.master
+ self.cpu_side = self.mmubus.mem_side_ports
cpu.mmu.connectWalkerPorts(
self.mmubus.cpu_side_ports, self.mmubus.cpu_side_ports)
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -140,10 +140,10 @@
super(L2Cache, self).__init__()
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L3Cache(Cache):
"""Simple L3 Cache bank with default values
@@ -166,8 +166,8 @@
super(L3Cache, self).__init__()
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/spec-2017/configs/system/fs_tools.py b/src/spec-2017/configs/system/fs_tools.py
index 99102ad..e6421f8 100644
--- a/src/spec-2017/configs/system/fs_tools.py
+++ b/src/spec-2017/configs/system/fs_tools.py
@@ -33,7 +33,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/spec-2017/configs/system/system.py b/src/spec-2017/configs/system/system.py
index 6b4e79a..1f4642c 100644
--- a/src/spec-2017/configs/system/system.py
+++ b/src/spec-2017/configs/system/system.py
@@ -52,7 +52,7 @@
self.membus.badaddr_responder = BadAddr()
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus, num_cpus)
# Replace these paths with the path to your disk images.
# The first disk is the root disk. The second could be used for swap
@@ -148,9 +148,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
# Memory latency: Using the smaller number from [3]: 96ns
def createMemoryControllersDDR4(self):
self._createMemoryControllers(8, DDR4_2400_16x4)
@@ -159,12 +159,12 @@
ranges = self._getInterleaveRanges(self.mem_ranges[-1], num, 7, 20)
self.mem_cntrls = [
cls(range = ranges[i],
- port = self.membus.master)
+ port = self.membus.mem_side_ports)
for i in range(num)
] + [kernel_controller]
def _createKernelMemoryController(self, cls):
return cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ port = self.membus.mem_side_ports)
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
from math import log
bits = int(log(num, 2))
@@ -192,8 +192,8 @@
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -212,8 +212,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -230,8 +230,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
###############################################
# Add in a Bios information structure.