website: Merge branch 'stable' into develop

Change-Id: Ica3db1495c5523e245b6c4367b84b30651a076a9
diff --git a/_pages/documentation/learning_gem5/part1/part1_1_building.md b/_pages/documentation/learning_gem5/part1/part1_1_building.md
index 6cddce1..4997b0c 100644
--- a/_pages/documentation/learning_gem5/part1/part1_1_building.md
+++ b/_pages/documentation/learning_gem5/part1/part1_1_building.md
@@ -81,10 +81,9 @@
         sudo apt install libprotobuf-dev protobuf-compiler libgoogle-perftools-dev
         ```
 
-6. [Boost](https://www.boost.org/) (**Optional**) : The Boost library is a set
-        of general purpose C++ libraries. It is a necessary dependency if you
-        wish to use the SystemC implementation.
-
+6. [Boost](https://www.boost.org/) (**Optional**)
+    :   The Boost library is a set of general purpose C++ libraries. It is a
+        necessary dependency if you wish to use the SystemC implementation.
         ```
         sudo apt install libboost-all-dev
         ```
@@ -124,12 +123,12 @@
 directory. These files specify the parameters passed to SCons when
 initially building gem5. We'll use the X86 defaults and specify that we
 want to compile all of the CPU models. You can look at the file
-`build_opts/X86` to see the default values for the Scons options. You
+`build_opts/X86` to see the default values for the SCons options. You
 can also specify these options on the command line to override any
 default.
 
 ```
-python3 scons build/X86/gem5.opt -j9
+python3 `which scons` build/X86/gem5.opt -j9
 ```
 
 > **gem5 binary types**
diff --git a/_pages/documentation/learning_gem5/part1/part1_2_simple_config.md b/_pages/documentation/learning_gem5/part1/part1_2_simple_config.md
index 8f5e405..53fa0c7 100644
--- a/_pages/documentation/learning_gem5/part1/part1_2_simple_config.md
+++ b/_pages/documentation/learning_gem5/part1/part1_2_simple_config.md
@@ -44,6 +44,8 @@
 there. Hopefully, by the end of this section you'll have a good idea of
 how simulation scripts work.
 
+---
+
 > **An aside on SimObjects**
 >
 > gem5's modular design is built around the **SimObject** type. Most of
@@ -55,6 +57,9 @@
 >
 > See [SimObject details](http://doxygen.gem5.org/release/current/classSimObject.html#details) for more information.
 
+---
+
+
 Creating a config file
 ----------------------
 
@@ -146,30 +151,49 @@
 system.cpu.dcache_port = system.membus.cpu_side_ports
 ```
 
+---
 > **An aside on gem5 ports**
 >
 > To connect memory system components together, gem5 uses a port
-> abstraction. Each memory object can have two kinds of ports, *master
-> ports* and *slave ports*. Requests are sent from a master port to a
-> slave port, and responses are sent from a slave port to a master port.
-> When connecting ports, you must connect a master port to a slave port.
+> abstraction. Each memory object can have two kinds of ports,
+> *request ports* and *response ports*. Requests are sent from
+> a request port to a response port, and responses are sent from
+> a response port to a request port. When connecting ports, you
+> must connect a request port to a response port.
 >
 > Connecting ports together is easy to do from the python configuration
-> files. You can simply set the master port `=` to the slave port and
-> they will be connected. For instance:
+> files. You can simply set the request port `=` to the response port
+> and they will be connected. For instance:
 >
 > ```
-> memobject1.master = memobject2.slave
+> system.cpu.icache_port = system.l1_cache.cpu_side
 > ```
 >
-> The master and slave can be on either side of the `=` and the same
-> connection will be made. After making the connection, the master can
-> send requests to the slave port. There is a lot of magic going on
-> behind the scenes to set up the connection, the details of which are
-> unimportant for most users.
+> In this example, the cpu's `icache_port` is a request port, and the cache's
+> `cpu_side` is a response port. The request port and the response port can be
+> on either side of the `=` and the same connection will be made. After making
+> the connection, the requestor can send requests to the responder. There is a
+> lot of magic going on behind the scenes to set up the connection, the details
+> of which are unimportant to most users.
+>
+> Another notable kind of magic of the `=` of two ports in a gem5 Python
+> configuration is that, it is allowed to have one port on one side, and an
+> array of ports on the other side. For example:
+>
+> ```
+> system.cpu.icache_port = system.membus.cpu_side_ports
+> ```
+>
+> In this example, the cpu's `icache_port` is a request port, and the membus's
+> `cpu_side_ports` is an array of response ports. In this case, a new response
+> port is spawned on the `cpu_side_ports`, and this newly created port will be
+> connected to the request port.
 >
 > We will discuss ports and MemObject in more detail in the [MemObject chapter](http://www.gem5.org/documentation/learning_gem5/part2/memoryobject/).
 
+
+---
+
 Next, we need to connect up a few other ports to make sure that our
 system will function correctly. We need to create an I/O controller on
 the CPU and connect it to the memory bus. Also, we need to connect a
@@ -197,7 +221,7 @@
 system.mem_ctrl = MemCtrl()
 system.mem_ctrl.dram = DDR3_1600_8x8()
 system.mem_ctrl.dram.range = system.mem_ranges[0]
-system.mem_ctrl.dram.port = system.membus.mem_side_ports
+system.mem_ctrl.port = system.membus.mem_side_ports
 ```
 
 After those final connections, we've finished instantiating our
@@ -244,8 +268,8 @@
 ```
 binary = 'tests/test-progs/hello/bin/x86/linux/hello'
 
-#for gem5 V21 and beyond, uncomment the following line
-#system.workload = SEWorkload.init_compatible(binary)
+# for gem5 V21 and beyond, uncomment the following line
+# system.workload = SEWorkload.init_compatible(binary)
 
 process = Process()
 process.cmd = [binary]
@@ -287,13 +311,14 @@
 ------------
 
 Now that we've created a simple simulation script (the full version of
-which can be found at gem5/configs/learning\_gem5/part1/simple.py) we're
-ready to run gem5. gem5 can take many parameters, but requires just one
-positional argument, the simulation script. So, we can simply run gem5
+which can be found in the gem5 code base at
+[configs/learning\_gem5/part1/simple.py](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/configs/learning_gem5/part1/simple.py)
+) we're ready to run gem5. gem5 can take many parameters, but requires just
+one positional argument, the simulation script. So, we can simply run gem5
 from the root gem5 directory as:
 
 ```
-build/X86/gem5.opt configs/tutorial/simple.py
+build/X86/gem5.opt configs/tutorial/part1/simple.py
 ```
 
 The output should be:
@@ -301,18 +326,20 @@
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
 
-    gem5 compiled Mar 16 2018 10:24:24
-    gem5 started Mar 16 2018 15:53:27
-    gem5 executing on amarillo, pid 41697
-    command line: build/X86/gem5.opt configs/tutorial/simple.py
+    gem5 version 21.0.0.0
+    gem5 compiled May 17 2021 18:05:59
+    gem5 started May 17 2021 22:05:20
+    gem5 executing on amarillo, pid 75197
+    command line: build/X86/gem5.opt configs/tutorial/part1/simple.py
 
     Global frequency set at 1000000000000 ticks per second
+    warn: No dot file generated. Please install pydot to generate the dot file and pdf.
     warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
-    0: system.remote_gdb: listening for remote gdb on port 7000
+    0: system.remote_gdb: listening for remote gdb on port 7005
     Beginning simulation!
     info: Entering event queue @ 0.  Starting simulation...
     Hello world!
-    Exiting @ tick 507841000 because exiting with last active thread context
+    Exiting @ tick 490394000 because exiting with last active thread context
 
 Parameters in the configuration file can be changed and the results
 should be different. For instance, if you double the system clock, the
diff --git a/_pages/documentation/learning_gem5/part1/part1_3_cache_config.md b/_pages/documentation/learning_gem5/part1/part1_3_cache_config.md
index 2cc018f..f53ca8e 100644
--- a/_pages/documentation/learning_gem5/part1/part1_3_cache_config.md
+++ b/_pages/documentation/learning_gem5/part1/part1_3_cache_config.md
@@ -67,7 +67,7 @@
 is a string. The string argument of each of the parameters is a
 description of what the parameter is (e.g.,
 `tag_latency = Param.Cycles("Tag lookup latency")` means that the
-`` `tag_latency `` controls "The hit latency for this cache").
+`` tag_latency `` controls "The hit latency for this cache").
 
 Many of these parameters do not have defaults, so we are required to set
 these parameters before calling `m5.instantiate()`.
@@ -76,8 +76,8 @@
 
 Now, to create caches with specific parameters, we are first going to
 create a new file, `caches.py`, in the same directory as simple.py,
-`configs/tutorial`. The first step is to import the SimObject(s) we are
-going to extend in this file.
+`configs/tutorial`. The first step is to import the SimObject(s)
+we are going to extend in this file.
 
 ```
 from m5.objects import Cache
@@ -180,13 +180,13 @@
 ```
 
 The full file can be found in the gem5 source at
-`gem5/configs/learning_gem5/part1/caches.py`.
+[`configs/learning_gem5/part1/caches.py`](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/configs/learning_gem5/part1/caches.py).
 
 Adding caches to the simple config file
 ------------------------------------
 
 Now, let's add the caches we just created to the configuration script we
-created in the [last chapter]((http://www.gem5.org/documentation/learning_gem5/part1/simple_config/).
+created in the [last chapter](http://www.gem5.org/documentation/learning_gem5/part1/simple_config/).
 
 First, let's copy the script to a new name.
 
@@ -243,15 +243,14 @@
 ```
 system.l2cache = L2Cache()
 system.l2cache.connectCPUSideBus(system.l2bus)
-
 system.l2cache.connectMemSideBus(system.membus)
 ```
 
 Everything else in the file stays the same! Now we have a complete
 configuration with a two-level cache hierarchy. If you run the current
-file, `hello` should now finish in 58513000 ticks. The full script can
+file, `hello` should now finish in 57467000 ticks. The full script can
 be found in the gem5 source at
-`gem5/configs/learning_gem5/part1/two_level.py`.
+[`configs/learning_gem5/part1/two_level.py](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/configs/learning_gem5/part1/two_level.py).
 
 Adding parameters to your script
 --------------------------------
@@ -261,10 +260,10 @@
 different parameters. To get around this, you can add command-line
 parameters to your gem5 configuration script. Again, because the
 configuration script is just Python, you can use the Python libraries
-that support argument parsing. Although :pyoptparse is officially
+that support argument parsing. Although pyoptparse is officially
 deprecated, many of the configuration scripts that ship with gem5 use it
 instead of pyargparse since gem5's minimum Python version used to be
-2.5. The minimum Python version is now 2.7, so pyargparse is a better
+2.5. The minimum Python version is now 3.6, so Python's argparse is a better
 option when writing new scripts that don't need to interact with the
 current gem5 scripts. To get started using :pyoptparse, you can consult
 the online Python documentation.
@@ -273,14 +272,19 @@
 caches, let's add some options.
 
 ```
-from optparse import OptionParser
+import argparse
 
-parser = OptionParser()
-parser.add_option('--l1i_size', help="L1 instruction cache size")
-parser.add_option('--l1d_size', help="L1 data cache size")
-parser.add_option('--l2_size', help="Unified L2 cache size")
+parser = argparse.ArgumentParser(description='A simple system with 2-level cache.')
+parser.add\_argument("binary", default="", nargs="?", type=str,
+                    help="Path to the binary to execute.")
+parser.add\_argument("--l1i_size",
+                    help=f"L1 instruction cache size. Default: 16kB.")
+parser.add\_argument("--l1d_size",
+                    help="L1 data cache size. Default: Default: 64kB.")
+parser.add\_argument("--l2_size",
+                    help="L2 cache size. Default: 256kB.")
 
-(options, args) = parser.parse_args()
+options = parser.parse\_args()
 ```
 
 Now, you can run
@@ -288,7 +292,7 @@
 will display the options you just added.
 
 Next, we need to pass these options onto the caches that we create in
-the configuration script. To do this, we'll simply change two\_level.py
+the configuration script. To do this, we'll simply change two\_level\_opts.py
 to pass the options into the caches as a parameter to their constructor
 and add an appropriate constructor, next.
 
@@ -360,19 +364,21 @@
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
 
-    gem5 compiled Sep  6 2015 14:17:02
-    gem5 started Sep  6 2015 15:06:51
-    gem5 executing on galapagos-09.cs.wisc.edu
-    command line: build/X86/gem5.opt ../tutorial/_static/scripts/part1/two_level_opts.py --l2_size=1MB --l1d_size=128kB
+    gem5 version 21.0.0.0
+    gem5 compiled May 17 2021 18:05:59
+    gem5 started May 18 2021 00:00:33
+    gem5 executing on amarillo, pid 83118
+    command line: build/X86/gem5.opt configs/tutorial/two_level.py --l2_size=1MB --l1d_size=128kB
 
     Global frequency set at 1000000000000 ticks per second
+    warn: No dot file generated. Please install pydot to generate the dot file and pdf.
     warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
-    0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
+    0: system.remote_gdb: listening for remote gdb on port 7005
     Beginning simulation!
     info: Entering event queue @ 0.  Starting simulation...
     Hello world!
-    Exiting @ tick 56742000 because target called exit()
+    Exiting @ tick 57467000 because exiting with last active thread context
 
 The full scripts can be found in the gem5 source at
-`gem5/configs/learning_gem5/part1/caches.py` and
-`gem5/configs/learning_gem5/part1/two_level.py`.
+[`configs/learning_gem5/part1/caches.py`](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/configs/learning_gem5/part1/caches.py) and
+[`configs/learning_gem5/part1/two_level.py`](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/configs/learning_gem5/part1/two_level.py).
diff --git a/_pages/documentation/learning_gem5/part1/part1_4_gem5_stats.md b/_pages/documentation/learning_gem5/part1/part1_4_gem5_stats.md
index b59aa15..65e0ff6 100644
--- a/_pages/documentation/learning_gem5/part1/part1_4_gem5_stats.md
+++ b/_pages/documentation/learning_gem5/part1/part1_4_gem5_stats.md
@@ -35,7 +35,9 @@
 this file.
 
 Below is pulled from the config.ini generated when the `simple.py`
-configuration file from simple-config-chapter is run.
+configuration file from
+[simple-config-chapter](http://www.gem5.org/documentation/learning_gem5/part1/simple_config/)
+is run.
 
     [root]
     type=Root
@@ -98,10 +100,10 @@
     system=system
 
 Here we see that at the beginning of the description of each SimObject
-is first it's name as created in the configuration file surrounded by
+is first its name as created in the configuration file surrounded by
 square brackets (e.g., `[system.membus]`).
 
-Next, every parameter of the SimObject is shown with it's value,
+Next, every parameter of the SimObject is shown with its value,
 including parameters not explicitly set in the configuration file. For
 instance, the configuration file sets the clock domain to be 1 GHz (1000
 ticks in this case). However, it did not set the cache line size (which
@@ -128,28 +130,30 @@
 execution:
 
     ---------- Begin Simulation Statistics ----------
-    sim_seconds                                  0.000346                       # Number of seconds simulated
-    sim_ticks                                   345518000                       # Number of ticks simulated
-    final_tick                                  345518000                       # Number of ticks from beginning of simulation (restored from checkpoints and never reset)
-    sim_freq                                 1000000000000                       # Frequency of simulated ticks
-    host_inst_rate                                 144400                       # Simulator instruction rate (inst/s)
-    host_op_rate                                   260550                       # Simulator op (including micro ops) rate (op/s)
-    host_tick_rate                             8718625183                       # Simulator tick rate (ticks/s)
-    host_mem_usage                                 778640                       # Number of bytes of host memory used
-    host_seconds                                     0.04                       # Real time elapsed on the host
-    sim_insts                                        5712                       # Number of instructions simulated
-    sim_ops                                         10314                       # Number of ops (including micro ops) simulated
+    simSeconds                                   0.000057                       # Number of seconds simulated (Second)
+    simTicks                                     57467000                       # Number of ticks simulated (Tick)
+    finalTick                                    57467000                       # Number of ticks from beginning of simulation (restored from checkpoints and never reset) (Tick)
+    simFreq                                  1000000000000                       # The number of ticks per simulated second ((Tick/Second))
+    hostSeconds                                      0.03                       # Real time elapsed on the host (Second)
+    hostTickRate                               2295882330                       # The number of ticks simulated per host second (ticks/s) ((Tick/Second))
+    hostMemory                                     665792                       # Number of bytes of host memory used (Byte)
+    simInsts                                         6225                       # Number of instructions simulated (Count)
+    simOps                                          11204                       # Number of ops (including micro ops) simulated (Count)
+    hostInstRate                                   247382                       # Simulator instruction rate (inst/s) ((Count/Second))
+    hostOpRate                                     445086                       # Simulator op (including micro ops) rate (op/s) ((Count/Second))
 
     ---------- Begin Simulation Statistics ----------
-    sim_seconds                                  0.000508                       # Number of seconds simulated 
-    sim_ticks                                   507841000                       # Number of ticks simulated
-    final_tick                                  507841000                       # Number of ticks from beginning of simulation (restored from checkpoints and never reset) 
-    sim_freq                                 1000000000000                       # Frequency of simulated ticks
-    host_inst_rate                                 157744                       # Simulator instruction rate (inst/s) host_op_rate                                   284736                       # Simulator op (including micro ops) rate (op/s)
-    host_tick_rate                            14017997125                       # Simulator tick rate (ticks/s)
-    host_mem_usage                                 642808                       # Number of bytes of host memory used host_seconds                                     0.04                       # Real time elapsed on the host
-    sim_insts                                        5712                       # Number of instructions simulated 
-    sim_ops                                         10313                       # Number of ops (including micro ops) simulated 
+    simSeconds                                   0.000490                       # Number of seconds simulated (Second)
+    simTicks                                    490394000                       # Number of ticks simulated (Tick)
+    finalTick                                   490394000                       # Number of ticks from beginning of simulation (restored from checkpoints and never reset) (Tick)
+    simFreq                                  1000000000000                       # The number of ticks per simulated second ((Tick/Second))
+    hostSeconds                                      0.03                       # Real time elapsed on the host (Second)
+    hostTickRate                              15979964060                       # The number of ticks simulated per host second (ticks/s) ((Tick/Second))
+    hostMemory                                     657488                       # Number of bytes of host memory used (Byte)
+    simInsts                                         6225                       # Number of instructions simulated (Count)
+    simOps                                          11204                       # Number of ops (including micro ops) simulated (Count)
+    hostInstRate                                   202054                       # Simulator instruction rate (inst/s) ((Count/Second))
+    hostOpRate                                     363571                       # Simulator op (including micro ops) rate (op/s) ((Count/Second))
 
 The statistic dump begins with
 `---------- Begin Simulation Statistics ----------`. There may be
@@ -158,7 +162,8 @@
 or when restoring from checkpoints.
 
 Each statistic has a name (first column), a value (second column), and a
-description (last column preceded by \#).
+description (last column preceded by \#) followed by the unit of the
+statistic.
 
 Most of the statistics are self explanatory from their descriptions. A
 couple of important statistics are `sim_seconds` which is the total
@@ -166,80 +171,92 @@
 instructions committed by the CPU, and `host_inst_rate` which tells you
 the performance of gem5.
 
-Next, the SimObjects' statistics are printed. For instance, the memory
-controller statistics. This has information like the bytes read by each
-component and the average bandwidth used by those components.
+Next, the SimObjects' statistics are printed. For instance, the CPU
+statistics, which contains information on the number of syscalls,
+statistics for cache system and translation buffers, etc.
 
-    system.clk_domain.voltage_domain.voltage            1                       # Voltage in Volts
-    system.clk_domain.clock                          1000                       # Clock period in ticks
-    system.mem_ctrl.pwrStateResidencyTicks::UNDEFINED    507841000                       # Cumulative time (in ticks) in various power states
-    system.mem_ctrl.bytes_read::cpu.inst            58264                       # Number of bytes read from this memory
-    system.mem_ctrl.bytes_read::cpu.data             7167                       # Number of bytes read from this memory
-    system.mem_ctrl.bytes_read::total               65431                       # Number of bytes read from this memory
-    system.mem_ctrl.bytes_inst_read::cpu.inst        58264                       # Number of instructions bytes read from this memory
-    system.mem_ctrl.bytes_inst_read::total          58264                       # Number of instructions bytes read from this memory
-    system.mem_ctrl.bytes_written::cpu.data          7160                       # Number of bytes written to this memory
-    system.mem_ctrl.bytes_written::total             7160                       # Number of bytes written to this memory
-    system.mem_ctrl.num_reads::cpu.inst              7283                       # Number of read requests responded to by this memory
-    system.mem_ctrl.num_reads::cpu.data              1084                       # Number of read requests responded to by this memory
-    system.mem_ctrl.num_reads::total                 8367                       # Number of read requests responded to by this memory
-    system.mem_ctrl.num_writes::cpu.data              941                       # Number of write requests responded to by this memory
-    system.mem_ctrl.num_writes::total                 941                       # Number of write requests responded to by this memory
-    system.mem_ctrl.bw_read::cpu.inst           114728823                       # Total read bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_read::cpu.data            14112685                       # Total read bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_read::total              128841507                       # Total read bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_inst_read::cpu.inst      114728823                       # Instruction read bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_inst_read::total         114728823                       # Instruction read bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_write::cpu.data           14098901                       # Write bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_write::total              14098901                       # Write bandwidth from this memory (bytes/s)
-    system.mem_ctrl.bw_total::cpu.inst          114728823                       # Total bandwidth to/from this memory (bytes/s)
-    system.mem_ctrl.bw_total::cpu.data           28211586                       # Total bandwidth to/from this memory (bytes/s)
-    system.mem_ctrl.bw_total::total             142940409                       # Total bandwidth to/from this memory (bytes/s)
+    system.clk_domain.clock                          1000                       # Clock period in ticks (Tick)
+    system.clk_domain.voltage_domain.voltage            1                       # Voltage in Volts (Volt)
+    system.cpu.numCycles                            57467                       # Number of cpu cycles simulated (Cycle)
+    system.cpu.numWorkItemsStarted                      0                       # Number of work items this cpu started (Count)
+    system.cpu.numWorkItemsCompleted                    0                       # Number of work items this cpu completed (Count)
+    system.cpu.dcache.demandHits::cpu.data           1941                       # number of demand (read+write) hits (Count)
+    system.cpu.dcache.demandHits::total              1941                       # number of demand (read+write) hits (Count)
+    system.cpu.dcache.overallHits::cpu.data          1941                       # number of overall hits (Count)
+    system.cpu.dcache.overallHits::total             1941                       # number of overall hits (Count)
+    system.cpu.dcache.demandMisses::cpu.data          133                       # number of demand (read+write) misses (Count)
+    system.cpu.dcache.demandMisses::total             133                       # number of demand (read+write) misses (Count)
+    system.cpu.dcache.overallMisses::cpu.data          133                       # number of overall misses (Count)
+    system.cpu.dcache.overallMisses::total            133                       # number of overall misses (Count)
+    system.cpu.dcache.demandMissLatency::cpu.data     14301000                       # number of demand (read+write) miss ticks (Tick)
+    system.cpu.dcache.demandMissLatency::total     14301000                       # number of demand (read+write) miss ticks (Tick)
+    system.cpu.dcache.overallMissLatency::cpu.data     14301000                       # number of overall miss ticks (Tick)
+    system.cpu.dcache.overallMissLatency::total     14301000                       # number of overall miss ticks (Tick)
+    system.cpu.dcache.demandAccesses::cpu.data         2074                       # number of demand (read+write) accesses (Count)
+    system.cpu.dcache.demandAccesses::total          2074                       # number of demand (read+write) accesses (Count)
+    system.cpu.dcache.overallAccesses::cpu.data         2074                       # number of overall (read+write) accesses (Count)
+    system.cpu.dcache.overallAccesses::total         2074                       # number of overall (read+write) accesses (Count)
+    system.cpu.dcache.demandMissRate::cpu.data     0.064127                       # miss rate for demand accesses (Ratio)
+    system.cpu.dcache.demandMissRate::total      0.064127                       # miss rate for demand accesses (Ratio)
+    system.cpu.dcache.overallMissRate::cpu.data     0.064127                       # miss rate for overall accesses (Ratio)
+    system.cpu.dcache.overallMissRate::total     0.064127                       # miss rate for overall accesses (Ratio)
+    system.cpu.dcache.demandAvgMissLatency::cpu.data 107526.315789                       # average overall miss latency ((Cycle/Count))
+    system.cpu.dcache.demandAvgMissLatency::total 107526.315789                       # average overall miss latency ((Cycle/Count))
+    system.cpu.dcache.overallAvgMissLatency::cpu.data 107526.315789                       # average overall miss latency ((Cycle/Count))
+    system.cpu.dcache.overallAvgMissLatency::total 107526.315789                       # average overall miss latency ((Cycle/Count))
+    ...
+    system.cpu.mmu.dtb.rdAccesses                    1123                       # TLB accesses on read requests (Count)
+    system.cpu.mmu.dtb.wrAccesses                     953                       # TLB accesses on write requests (Count)
+    system.cpu.mmu.dtb.rdMisses                        11                       # TLB misses on read requests (Count)
+    system.cpu.mmu.dtb.wrMisses                         9                       # TLB misses on write requests (Count)
+    system.cpu.mmu.dtb.walker.power_state.pwrStateResidencyTicks::UNDEFINED     57467000                       # Cumulative time (in ticks) in various power states (Tick)
+    system.cpu.mmu.itb.rdAccesses                       0                       # TLB accesses on read requests (Count)
+    system.cpu.mmu.itb.wrAccesses                    7940                       # TLB accesses on write requests (Count)
+    system.cpu.mmu.itb.rdMisses                         0                       # TLB misses on read requests (Count)
+    system.cpu.mmu.itb.wrMisses                        37                       # TLB misses on write requests (Count)
+    system.cpu.mmu.itb.walker.power_state.pwrStateResidencyTicks::UNDEFINED     57467000                       # Cumulative time (in ticks) in various power states (Tick)
+    system.cpu.power_state.pwrStateResidencyTicks::ON     57467000                       # Cumulative time (in ticks) in various power states (Tick)
+    system.cpu.thread_0.numInsts                        0                       # Number of Instructions committed (Count)
+    system.cpu.thread_0.numOps                          0                       # Number of Ops committed (Count)
+    system.cpu.thread_0.numMemRefs                      0                       # Number of Memory References (Count)
+    system.cpu.workload.numSyscalls                    11                       # Number of system calls (Count)
 
-Later in the file is the CPU statistics, which contains information on
-the number of syscalls, the number of branches, total committed
-instructions, etc.
+Later in the file is memory controller statistics. This has information like
+the bytes read by each component and the average bandwidth used by those
+components.
 
-    system.cpu.dtb.walker.pwrStateResidencyTicks::UNDEFINED    507841000                       # Cumulative time (in ticks) in various power states
-    system.cpu.dtb.rdAccesses                        1084                       # TLB accesses on read requests
-    system.cpu.dtb.wrAccesses                         941                       # TLB accesses on write requests
-    system.cpu.dtb.rdMisses                             9                       # TLB misses on read requests
-    system.cpu.dtb.wrMisses                             7                       # TLB misses on write requests
-    system.cpu.apic_clk_domain.clock                16000                       # Clock period in ticks
-    system.cpu.interrupts.pwrStateResidencyTicks::UNDEFINED    507841000                       # Cumulative time (in ticks) in various power states
-    system.cpu.itb.walker.pwrStateResidencyTicks::UNDEFINED    507841000                       # Cumulative time (in ticks) in various power states
-    system.cpu.itb.rdAccesses                           0                       # TLB accesses on read requests
-    system.cpu.itb.wrAccesses                        7284                       # TLB accesses on write requests
-    system.cpu.itb.rdMisses                             0                       # TLB misses on read requests
-    system.cpu.itb.wrMisses                            31                       # TLB misses on write requests
-    system.cpu.workload.numSyscalls                    11                       # Number of system calls
-    system.cpu.pwrStateResidencyTicks::ON       507841000                       # Cumulative time (in ticks) in various power states
-    system.cpu.numCycles                           507841                       # number of cpu cycles simulated
-    system.cpu.numWorkItemsStarted                      0                       # number of work items this cpu started
-    system.cpu.numWorkItemsCompleted                    0                       # number of work items this cpu completed
-    system.cpu.committedInsts                        5712                       # Number of instructions committed
-    system.cpu.committedOps                         10313                       # Number of ops (including micro ops) committed
-    system.cpu.num_int_alu_accesses                 10204                       # Number of integer alu accesses
-    system.cpu.num_fp_alu_accesses                      0                       # Number of float alu accesses
-    system.cpu.num_vec_alu_accesses                     0                       # Number of vector alu accesses
-    system.cpu.num_func_calls                         221                       # number of times a function call or return occured
-    system.cpu.num_conditional_control_insts          986                       # number of instructions that are conditional controls
-    system.cpu.num_int_insts                        10204                       # number of integer instructions
-    system.cpu.num_fp_insts                             0                       # number of float instructions
-    system.cpu.num_vec_insts                            0                       # number of vector instructions
-    system.cpu.num_int_register_reads               19293                       # number of times the integer registers were read
-    system.cpu.num_int_register_writes               7976                       # number of times the integer registers were written
-    system.cpu.num_fp_register_reads                    0                       # number of times the floating registers were read
-    system.cpu.num_fp_register_writes                   0                       # number of times the floating registers were written
-    system.cpu.num_vec_register_reads                   0                       # number of times the vector registers were read
-    system.cpu.num_vec_register_writes                  0                       # number of times the vector registers were written
-    system.cpu.num_cc_register_reads                 7020                       # number of times the CC registers were read
-    system.cpu.num_cc_register_writes                3825                       # number of times the CC registers were written
-    system.cpu.num_mem_refs                          2025                       # number of memory refs
-    system.cpu.num_load_insts                        1084                       # Number of load instructions
-    system.cpu.num_store_insts                        941                       # Number of store instructions
-    system.cpu.num_idle_cycles                          0                       # Number of idle cycles
-    system.cpu.num_busy_cycles                     507841                       # Number of busy cycles
-    system.cpu.not_idle_fraction                        1                       # Percentage of non-idle cycles
-    system.cpu.idle_fraction                            0                       # Percentage of idle cycles
-    system.cpu.Branches                              1306                       # Number of branches fetched
+    system.mem_ctrl.bytesReadWrQ                        0                       # Total number of bytes read from write queue (Byte)
+    system.mem_ctrl.bytesReadSys                    23168                       # Total read bytes from the system interface side (Byte)
+    system.mem_ctrl.bytesWrittenSys                     0                       # Total written bytes from the system interface side (Byte)
+    system.mem_ctrl.avgRdBWSys               403153113.96105593                       # Average system read bandwidth in Byte/s ((Byte/Second))
+    system.mem_ctrl.avgWrBWSys                 0.00000000                       # Average system write bandwidth in Byte/s ((Byte/Second))
+    system.mem_ctrl.totGap                       57336000                       # Total gap between requests (Tick)
+    system.mem_ctrl.avgGap                      158386.74                       # Average gap between requests ((Tick/Count))
+    system.mem_ctrl.requestorReadBytes::cpu.inst        14656                       # Per-requestor bytes read from memory (Byte)
+    system.mem_ctrl.requestorReadBytes::cpu.data         8512                       # Per-requestor bytes read from memory (Byte)
+    system.mem_ctrl.requestorReadRate::cpu.inst 255033323.472601681948                       # Per-requestor bytes read from memory rate ((Byte/Second))
+    system.mem_ctrl.requestorReadRate::cpu.data 148119790.488454252481                       # Per-requestor bytes read from memory rate ((Byte/Second))
+    system.mem_ctrl.requestorReadAccesses::cpu.inst          229                       # Per-requestor read serviced memory accesses (Count)
+    system.mem_ctrl.requestorReadAccesses::cpu.data          133                       # Per-requestor read serviced memory accesses (Count)
+    system.mem_ctrl.requestorReadTotalLat::cpu.inst      6234000                       # Per-requestor read total memory access latency (Tick)
+    system.mem_ctrl.requestorReadTotalLat::cpu.data      4141000                       # Per-requestor read total memory access latency (Tick)
+    system.mem_ctrl.requestorReadAvgLat::cpu.inst     27222.71                       # Per-requestor read average memory access latency ((Tick/Count))
+    system.mem_ctrl.requestorReadAvgLat::cpu.data     31135.34                       # Per-requestor read average memory access latency ((Tick/Count))
+    system.mem_ctrl.dram.bytesRead::cpu.inst        14656                       # Number of bytes read from this memory (Byte)
+    system.mem_ctrl.dram.bytesRead::cpu.data         8512                       # Number of bytes read from this memory (Byte)
+    system.mem_ctrl.dram.bytesRead::total           23168                       # Number of bytes read from this memory (Byte)
+    system.mem_ctrl.dram.bytesInstRead::cpu.inst        14656                       # Number of instructions bytes read from this memory (Byte)
+    system.mem_ctrl.dram.bytesInstRead::total        14656                       # Number of instructions bytes read from this memory (Byte)
+    system.mem_ctrl.dram.numReads::cpu.inst           229                       # Number of read requests responded to by this memory (Count)
+    system.mem_ctrl.dram.numReads::cpu.data           133                       # Number of read requests responded to by this memory (Count)
+    system.mem_ctrl.dram.numReads::total              362                       # Number of read requests responded to by this memory (Count)
+    system.mem_ctrl.dram.bwRead::cpu.inst       255033323                       # Total read bandwidth from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwRead::cpu.data       148119790                       # Total read bandwidth from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwRead::total          403153114                       # Total read bandwidth from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwInstRead::cpu.inst    255033323                       # Instruction read bandwidth from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwInstRead::total      255033323                       # Instruction read bandwidth from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwTotal::cpu.inst      255033323                       # Total bandwidth to/from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwTotal::cpu.data      148119790                       # Total bandwidth to/from this memory ((Byte/Second))
+    system.mem_ctrl.dram.bwTotal::total         403153114                       # Total bandwidth to/from this memory ((Byte/Second))
+    system.mem_ctrl.dram.readBursts                   362                       # Number of DRAM read bursts (Count)
+    system.mem_ctrl.dram.writeBursts                    0                       # Number of DRAM write bursts (Count)
diff --git a/_pages/documentation/learning_gem5/part1/part1_5_gem5_example_configs.md b/_pages/documentation/learning_gem5/part1/part1_5_gem5_example_configs.md
index d706670..fa48250 100644
--- a/_pages/documentation/learning_gem5/part1/part1_5_gem5_example_configs.md
+++ b/_pages/documentation/learning_gem5/part1/part1_5_gem5_example_configs.md
@@ -34,30 +34,40 @@
 directory structure is shown below:
 
     configs/boot:
-    ammp.rcS            halt.sh                micro_tlblat2.rcS              netperf-stream-udp-local.rcS
-    ...
+    bbench-gb.rcS  bbench-ics.rcS  hack_back_ckpt.rcS  halt.sh
 
     configs/common:
-    Benchmarks.py     cpu2000.py     Options.py
-    Caches.py         FSConfig.py    O3_ARM_v7a.py     SysPaths.py
-    CacheConfig.py    CpuConfig.py   MemConfig.py      Simulation.py
+    Benchmarks.py   Caches.py  cpu2000.py    FileSystemConfig.py  GPUTLBConfig.py   HMC.py       MemConfig.py   Options.py     Simulation.py
+    CacheConfig.py  cores      CpuConfig.py  FSConfig.py          GPUTLBOptions.py  __init__.py  ObjectList.py  SimpleOpts.py  SysPaths.py
+
+    configs/dist:
+    sw.py
 
     configs/dram:
-    sweep.py
+    lat_mem_rd.py  low_power_sweep.py  sweep.py
 
     configs/example:
-    fs.py       read_config.py       ruby_mem_test.py      ruby_random_test.py
-    memtest.py  ruby_direct_test.py  ruby_network_test.py  se.py
+    apu_se.py  etrace_replay.py  garnet_synth_traffic.py  hmctest.py    hsaTopology.py  memtest.py  read_config.py  ruby_direct_test.py      ruby_mem_test.py     sc_main.py
+    arm        fs.py             hmc_hello.py             hmc_tgen.cfg  memcheck.py     noc_config  riscv           ruby_gpu_random_test.py  ruby_random_test.py  se.py
+
+    configs/learning_gem5:
+    part1  part2  part3  README
+
+    configs/network:
+    __init__.py  Network.py
+
+    configs/nvm:
+    sweep_hybrid.py  sweep.py
 
     configs/ruby:
-    MESI_Three_Level.py  MI_example.py           MOESI_CMP_token.py  Network_test.py
-    MESI_Two_Level.py    MOESI_CMP_directory.py  MOESI_hammer.py     Ruby.py
+    AMD_Base_Constructor.py  CHI.py        Garnet_standalone.py  __init__.py              MESI_Three_Level.py  MI_example.py      MOESI_CMP_directory.py  MOESI_hammer.py
+    CHI_config.py            CntrlBase.py  GPU_VIPER.py          MESI_Three_Level_HTM.py  MESI_Two_Level.py    MOESI_AMD_Base.py  MOESI_CMP_token.py      Ruby.py
 
     configs/splash2:
     cluster.py  run.py
 
     configs/topologies:
-    BaseTopology.py  Cluster.py  Crossbar.py  MeshDirCorners.py  Mesh.py  Pt2Pt.py  Torus.py
+    BaseTopology.py  Cluster.py  CrossbarGarnet.py  Crossbar.py  CustomMesh.py  __init__.py  MeshDirCorners_XY.py  Mesh_westfirst.py  Mesh_XY.py  Pt2Pt.py
 
 Each directory is briefly described below:
 
@@ -107,6 +117,17 @@
     next section. There are also some other utility configuration
     scripts in this directory.
 
+**learning_gem5/**
+:   This directory contains all gem5 configuration scripts found in the
+    learning\_gem5 book.
+
+**network/**
+:   This directory contains the configurations scripts for a HeteroGarnet
+    network.
+
+**nvm/**
+:   This directory contains example scripts using the NVM interface.
+
 **ruby/**
 :   This directory contains the configurations scripts for Ruby and its
     included cache coherence protocols. More details can be found in the
@@ -145,32 +166,34 @@
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
 
-    gem5 compiled Jan 14 2015 16:11:34
-    gem5 started Feb  2 2015 15:22:24
-    gem5 executing on mustardseed.cs.wisc.edu
+    gem5 version 21.0.0.0
+    gem5 compiled May 17 2021 18:05:59
+    gem5 started May 18 2021 00:33:42
+    gem5 executing on amarillo, pid 85168
     command line: build/X86/gem5.opt configs/example/se.py --cmd=tests/test-progs/hello/bin/x86/linux/hello
+
     Global frequency set at 1000000000000 ticks per second
+    warn: No dot file generated. Please install pydot to generate the dot file and pdf.
     warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
-    0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
+    0: system.remote_gdb: listening for remote gdb on port 7005
     **** REAL SIMULATION ****
     info: Entering event queue @ 0.  Starting simulation...
     Hello world!
-    Exiting @ tick 5942000 because target called exit()
+    Exiting @ tick 5943000 because exiting with last active thread context
 
 However, this isn't a very interesting simulation at all! By default,
 gem5 uses the atomic CPU and uses atomic memory accesses, so there's no
 real timing data reported! To confirm this, you can look at
-m5out/config.ini. The CPU is shown on line 46:
+m5out/config.ini. The CPU is shown on line 51:
 
     [system.cpu]
     type=AtomicSimpleCPU
-    children=apic_clk_domain dtb interrupts isa itb tracer workload
+    children=interrupts isa mmu power_state tracer workload
     branchPred=Null
     checker=Null
     clk_domain=system.cpu_clk_domain
     cpu_id=0
     do_checkpoint_insts=true
-    do_quiesce=true
     do_statistics_insts=true
 
 To actually run gem5 in timing mode, let's specify a CPU type. While
@@ -183,17 +206,20 @@
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
 
-    gem5 compiled Jan 14 2015 16:11:34
-    gem5 started Feb  2 2015 15:26:57
-    gem5 executing on mustardseed.cs.wisc.edu
+    gem5 version 21.0.0.0
+    gem5 compiled May 17 2021 18:05:59
+    gem5 started May 18 2021 00:36:10
+    gem5 executing on amarillo, pid 85269
     command line: build/X86/gem5.opt configs/example/se.py --cmd=tests/test-progs/hello/bin/x86/linux/hello --cpu-type=TimingSimpleCPU --l1d_size=64kB --l1i_size=16kB
+
     Global frequency set at 1000000000000 ticks per second
+    warn: No dot file generated. Please install pydot to generate the dot file and pdf.
     warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
-    0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
+    0: system.remote_gdb: listening for remote gdb on port 7005
     **** REAL SIMULATION ****
     info: Entering event queue @ 0.  Starting simulation...
     Hello world!
-    Exiting @ tick 344986500 because target called exit()
+    Exiting @ tick 454646000 because exiting with last active thread context
 
 Now, let's check the config.ini file and make sure that these options
 propagated correctly to the final system. If you search
@@ -209,47 +235,59 @@
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
 
-    gem5 compiled Jan 14 2015 16:11:34
-    gem5 started Feb  2 2015 15:29:20
-    gem5 executing on mustardseed.cs.wisc.edu
+    gem5 version 21.0.0.0
+    gem5 compiled May 17 2021 18:05:59
+    gem5 started May 18 2021 00:37:03
+    gem5 executing on amarillo, pid 85560
     command line: build/X86/gem5.opt configs/example/se.py --cmd=tests/test-progs/hello/bin/x86/linux/hello --cpu-type=TimingSimpleCPU --l1d_size=64kB --l1i_size=16kB --caches
+
     Global frequency set at 1000000000000 ticks per second
+    warn: No dot file generated. Please install pydot to generate the dot file and pdf.
     warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
-    0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
+    0: system.remote_gdb: listening for remote gdb on port 7005
     **** REAL SIMULATION ****
     info: Entering event queue @ 0.  Starting simulation...
     Hello world!
-    Exiting @ tick 29480500 because target called exit()
+    Exiting @ tick 31680000 because exiting with last active thread context
 
-On the last line, we see that the total time went from 344986500 ticks
-to 29480500, much faster! Looks like caches are probably enabled now.
+On the last line, we see that the total time went from 454646000 ticks
+to 31680000, much faster! Looks like caches are probably enabled now.
 But, it's always a good idea to double check the `config.ini` file.
 
     [system.cpu.dcache]
-    type=BaseCache
-    children=tags
+    type=Cache
+    children=power_state replacement_policy tags
     addr_ranges=0:18446744073709551615
     assoc=2
     clk_domain=system.cpu_clk_domain
+    clusivity=mostly_incl
+    compressor=Null
+    data_latency=2
     demand_mshr_reserve=1
     eventq_index=0
-    forward_snoops=true
-    hit_latency=2
-    is_top_level=true
+    is_read_only=false
     max_miss_count=0
+    move_contractions=true
     mshrs=4
+    power_model=
+    power_state=system.cpu.dcache.power_state
     prefetch_on_access=false
     prefetcher=Null
+    replace_expansions=true
+    replacement_policy=system.cpu.dcache.replacement_policy
     response_latency=2
     sequential_access=false
     size=65536
     system=system
+    tag_latency=2
     tags=system.cpu.dcache.tags
     tgts_per_mshr=20
-    two_queue=false
+    warmup_percentage=0
+    write_allocator=Null
     write_buffers=8
+    writeback_clean=false
     cpu_side=system.cpu.dcache_port
-    mem_side=system.membus.slave[2]
+    mem_side=system.membus.cpu_side_ports[2]
 
 Some common options `se.py` and `fs.py`
 ---------------------------------------
diff --git a/_pages/documentation/learning_gem5/part2/part2_1_helloobject.md b/_pages/documentation/learning_gem5/part2/part2_1_helloobject.md
index f19c761..9b4e3e4 100644
--- a/_pages/documentation/learning_gem5/part2/part2_1_helloobject.md
+++ b/_pages/documentation/learning_gem5/part2/part2_1_helloobject.md
@@ -11,6 +11,9 @@
 Creating a *very* simple SimObject
 ==================================
 
+**Note**: gem5 has SimObject named `SimpleObject`. Implementing another
+`SimpleObject` SimObject will result in confusing compiler issues.
+
 Almost all objects in gem5 inherit from the base SimObject type.
 SimObjects export the main interfaces to all objects in gem5. SimObjects
 are wrapped `C++` objects that are accessible from the `Python`
@@ -39,7 +42,7 @@
 >
 > The first step when adding a new feature or modifying something in
 > gem5, is to create a new branch to store your changes. Details on git
-> branches can be found in the Git book\_.
+> branches can be found in the Git book.
 >
 > ```
 > git checkout -b hello-simobject
@@ -55,7 +58,11 @@
 simply need to declare a new class for our SimObject and set it's name
 and the C++ header that will define the C++ class for the SimObject.
 
-We can create a file, HelloObject.py, in `src/learning_gem5/part2`. If you have cloned the gem5 repository you'll have the files mentioned in this tutorial completed under `src/learning_gem5/part2` and `configs/learning_gem5/part2`. You can delete these or move them elsewhere to follow this tutorial.
+We can create a file, `HelloObject.py`, in `src/learning_gem5/part2`.
+If you have cloned the gem5 repository you'll have the files mentioned
+in this tutorial completed under `src/learning_gem5/part2` and
+`configs/learning_gem5/part2`. You can delete these or move them
+elsewhere to follow this tutorial.
 
 ```python
 from m5.params import *
@@ -82,7 +89,8 @@
 Step 2: Implement your SimObject in C++
 ---------------------------------------
 
-Next, we need to create `hello_object.hh` and `hello_object.cc` in `src/learning_gem5/part2/` directory which will implement the `HelloObject`.
+Next, we need to create `hello_object.hh` and `hello_object.cc` in
+`src/learning_gem5/part2/` directory which will implement the `HelloObject`.
 
 We'll start with the header file for our `C++` object. By convention,
 gem5 wraps all header files in `#ifndef/#endif` with the name of the
@@ -116,7 +124,7 @@
 class HelloObject : public SimObject
 {
   public:
-    HelloObject(HelloObjectParams *p);
+    HelloObject(const HelloObjectParams &p);
 };
 
 #endif // __LEARNING_GEM5_HELLO_OBJECT_HH__
@@ -140,43 +148,31 @@
 
 #include <iostream>
 
-HelloObject::HelloObject(HelloObjectParams *params) :
+HelloObject::HelloObject(const HelloObjectParams &params) :
     SimObject(params)
 {
     std::cout << "Hello World! From a SimObject!" << std::endl;
 }
 ```
 
-There is another function that we have to implement as well for the
-SimObject to be complete. We must implement one function for the
-parameter type that is implicitly created from the SimObject `Python`
-declaration, namely, the `create` function. This function simply returns
-a new instantiation of the SimObject. Usually this function is very
-simple (as below).
+**Note**: If the constructor of your SimObject follows the following
+signature,
 
 ```cpp
-HelloObject*
-HelloObjectParams::create()
-{
-    return new HelloObject(this);
-}
+Foo(const FooParams &)
 ```
 
+then a `FooParams::create()` method will be automatically defined. The purpose
+of the `create()` method is to call the SimObject constructor and return an
+instance of the SimObject. Most SimObject will follow this pattern; however,
+if your SimObject does not follow this pattern,
+[the gem5 SimObject documetation](http://doxygen.gem5.org/release/current/classSimObject.html#details)
+provides more information about manually implementing the `create()` method.
+
+
 [//]: # You can find the complete file
 [//]: # [here](/_pages/static/scripts/part2/helloobject/hello_object.cc).
 
-If you forget to add the create function for your SimObject, you will
-get a linker error when you compile. It will look something like the
-following.
-
-    build/X86/python/m5/internal/param_HelloObject_wrap.o: In function `_wrap_HelloObjectParams_create':
-    /local.chinook/gem5/gem5-tutorial/gem5/build/X86/python/m5/internal/param_HelloObject_wrap.cc:3096: undefined reference to `HelloObjectParams::create()'
-    collect2: error: ld returned 1 exit status
-    scons: *** [build/X86/gem5.opt] Error 1
-    scons: building terminated because of errors.
-
-This `` undefined reference to `HelloObjectParams::create()' `` means
-you need to implement the create function for your SimObject.
 
 Step 3: Register the SimObject and C++ file
 -------------------------------------------
@@ -227,7 +223,11 @@
 -----------------------------------------------------------
 
 Now that you have implemented a SimObject, and it has been compiled into
-gem5, you need to create or modify a `Python` config file `run_hello.py` in `configs/learning_gem5/part2` to instantiate your object. Since your object is very simple a system object is not required! CPUs are not needed, or caches, or anything, except a `Root` object. All gem5 instances require a `Root` object.
+gem5, you need to create or modify a `Python` config file `run_hello.py` in
+`configs/learning_gem5/part2` to instantiate your object. Since your object
+is very simple a system object is not required! CPUs are not needed, or
+caches, or anything, except a `Root` object. All gem5 instances require a
+`Root` object.
 
 Walking through creating a *very* simple configuration script, first,
 import m5 and all of the objects you have compiled.
@@ -270,10 +270,15 @@
 [//]: # You can find the complete file
 [//]: # [here](/_pages/static/scripts/part2/helloobject/run_hello.py).
 
-Remember to rebuild gem5 after modifying files in the src/ directory. The command line to run the config file is in the output below after 'command line:'. 
-The output should look something like the following:
+Remember to rebuild gem5 after modifying files in the src/ directory. The
+command line to run the config file is in the output below after
+'command line:'. The output should look something like the following:
 
-Note: If the code for the future section "Adding parameters to SimObjects and more events", (goodbye_object) is in your src/learning_gem5/part2 directory, run_hello.py will cause an error. If you delete those files or move them outside of the gem5 directory `run_hello.py` should give the output below.
+Note: If the code for the future section "Adding parameters to SimObjects
+and more events", (goodbye_object) is in your `src/learning_gem5/part2`
+directory, run_hello.py will cause an error. If you delete those files or
+move them outside of the gem5 directory `run_hello.py` should give the output
+below.
 ```
     gem5 Simulator System.  http://gem5.org
     gem5 is copyrighted software; use the --copyright option for details.
diff --git a/_pages/documentation/learning_gem5/part2/part2_2_debugging.md b/_pages/documentation/learning_gem5/part2/part2_2_debugging.md
index 1024399..28aad86 100644
--- a/_pages/documentation/learning_gem5/part2/part2_2_debugging.md
+++ b/_pages/documentation/learning_gem5/part2/part2_2_debugging.md
@@ -29,7 +29,7 @@
 following output. Note that this generates *a lot* of output to the
 console (about 7 MB).
 
-```sh
+```
     build/X86/gem5.opt --debug-flags=DRAM configs/learning_gem5/part1/simple.py | head -n 50
 ```
 
@@ -90,7 +90,7 @@
 flags shows details of how each instruction is executed by the simulated
 CPU.
 
-```sh
+```
     build/X86/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple.py | head -n 50
 ```
 
@@ -151,40 +151,42 @@
 flags. You can see this, and all of the available debug flags, by
 running gem5 with the `--debug-help` parameter.
 
-```sh
+```
     build/X86/gem5.opt --debug-help
 ```
 
     Base Flags:
-    Activity: None
-    AddrRanges: None
-    Annotate: State machine annotation debugging
-    AnnotateQ: State machine annotation queue debugging
-    AnnotateVerbose: Dump all state machine annotation details
-    BaseXBar: None
-    Branch: None
-    Bridge: None
-    CCRegs: None
-    CMOS: Accesses to CMOS devices
-    Cache: None
-    CachePort: None
-    CacheRepl: None
-    CacheTags: None
-    CacheVerbose: None
-    Checker: None
-    Checkpoint: None
-    ClockDomain: None
+        Activity: None
+        AddrRanges: None
+        Annotate: State machine annotation debugging
+        AnnotateQ: State machine annotation queue debugging
+        AnnotateVerbose: Dump all state machine annotation details
+        BaseXBar: None
+        Branch: None
+        Bridge: None
+        CCRegs: None
+        CMOS: Accesses to CMOS devices
+        Cache: None
+        CacheComp: None
+        CachePort: None
+        CacheRepl: None
+        CacheTags: None
+        CacheVerbose: None
+        Checker: None
+        Checkpoint: None
+        ClockDomain: None
     ...
     Compound Flags:
-    AnnotateAll: All Annotation flags
-        Annotate, AnnotateQ, AnnotateVerbose
-    CacheAll: None
-        Cache, CachePort, CacheRepl, CacheVerbose, HWPrefetch
-    DiskImageAll: None
-        DiskImageRead, DiskImageWrite
+        All: Controls all debug flags. It should not be used within C++ code.
+            All Base Flags
+        AnnotateAll: All Annotation flags
+            Annotate, AnnotateQ, AnnotateVerbose
+        CacheAll: None
+            Cache, CacheComp, CachePort, CacheRepl, CacheVerbose, HWPrefetch
+        DiskImageAll: None
+            DiskImageRead, DiskImageWrite
     ...
     XBar: None
-        BaseXBar, CoherentXBar, NoncoherentXBar, SnoopFilter    XBar: None
         BaseXBar, CoherentXBar, NoncoherentXBar, SnoopFilter
 
 Adding a new debug flag
@@ -200,10 +202,10 @@
 directory with your hello object code (src/learning\_gem5/).
 
 ```python
-DebugFlag('Hello')
+DebugFlag('HelloExample')
 ```
 
-This declares a debug flag of "Hello". Now, we can use this in debug
+This declares a debug flag of "HelloExample". Now, we can use this in debug
 statements in our SimObject.
 
 By declaring the flag in the SConscript file, a debug header is
@@ -216,14 +218,14 @@
 In the `hello_object.cc` file, we need to include the header file.
 
 ```cpp
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
 ```
 
 Now that we have included the necessary header file, let's replace the
 `std::cout` call with a debug statement like so.
 
 ```cpp
-DPRINTF(Hello, "Created the hello object\n");
+DPRINTF(HelloExample, "Created the hello object\n");
 ```
 
 `DPRINTF` is a C++ macro. The first parameter is a *debug flag* that has
@@ -235,7 +237,7 @@
 Now, if you recompile gem5 and run it with the "Hello" debug flag, you
 get the following result.
 
-```sh
+```
     build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py
 ```
 
@@ -254,9 +256,9 @@
     Exiting @ tick 18446744073709551615 because simulate() limit reached
 
 You can find the updated SConcript file
-[here](/_pages/static/scripts/part2/debugging/SConscript) and the updated
-hello object code
-[here](/_pages/static/scripts/part2/debugging/hello_object.cc).
+[here](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/src/learning_gem5/part2/SConscript)
+and the updated hello object code
+[here](https://gem5.googlesource.com/public/gem5/+/refs/heads/stable/src/learning_gem5/part2/hello_object.cc).
 
 Debug output
 ------------
diff --git a/_pages/documentation/learning_gem5/part2/part2_3_events.md b/_pages/documentation/learning_gem5/part2/part2_3_events.md
index 58b418b..d7081f2 100644
--- a/_pages/documentation/learning_gem5/part2/part2_3_events.md
+++ b/_pages/documentation/learning_gem5/part2/part2_3_events.md
@@ -13,7 +13,7 @@
 
 gem5 is an event-driven simulator. In this chapter, we will explore how
 to create and schedule events. We will be building from the simple
-`HelloObject` from hello-simobject-chapter.
+`HelloObject` from [hello-simobject-chapter](../helloobject).
 
 Creating a simple event callback
 --------------------------------
@@ -143,12 +143,12 @@
 
     EventFunctionWrapper event;
 
-    Tick latency;
+    const Tick latency;
 
     int timesLeft;
 
   public:
-    HelloObject(HelloObjectParams *p);
+    HelloObject(const HelloObjectParams &p);
 
     void startup();
 };
@@ -162,7 +162,7 @@
     SimObject(params), event([this]{processEvent();}, name()),
     latency(100), timesLeft(10)
 {
-    DPRINTF(Hello, "Created the hello object\n");
+    DPRINTF(HelloExample, "Created the hello object\n");
 }
 ```
 
@@ -179,10 +179,10 @@
 HelloObject::processEvent()
 {
     timesLeft--;
-    DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
+    DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);
 
     if (timesLeft <= 0) {
-        DPRINTF(Hello, "Done firing!\n");
+        DPRINTF(HelloExample, "Done firing!\n");
     } else {
         schedule(event, curTick() + latency);
     }
diff --git a/_pages/static/scripts/part1/caches.py b/_pages/static/scripts/part1/caches.py
index 5733e39..755f6b2 100644
--- a/_pages/static/scripts/part1/caches.py
+++ b/_pages/static/scripts/part1/caches.py
@@ -24,25 +24,23 @@
 # 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
 
-""" Simple caches with default values
+""" 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
 from m5.objects import Cache
 
 # Some specific options for caches
-# For all options see src/mem/cache/Cache.py
+# For all options see src/mem/cache/BaseCache.py
 
 class L1Cache(Cache):
     """Simple L1 Cache with default values"""
 
-    # Default parameters for both L1 I and D caches
     assoc = 2
     tag_latency = 2
     data_latency = 2
@@ -50,21 +48,31 @@
     mshrs = 4
     tgts_per_mshr = 20
 
-    def connectCPU(self, cpu):
-        """Connect this cache's port to a CPU-side port
-           This must be defined in a subclass"""
-        raise NotImplementedError
+    def __init__(self, options=None):
+        super(L1Cache, self).__init__()
+        pass
 
     def connectBus(self, bus):
         """Connect this cache to a memory-side bus"""
         self.mem_side = bus.slave
 
+    def connectCPU(self, cpu):
+        """Connect this cache's port to a CPU-side port
+           This must be defined in a subclass"""
+        raise NotImplementedError
+
 class L1ICache(L1Cache):
     """Simple L1 instruction cache with default values"""
 
     # Set the default size
     size = '16kB'
 
+    def __init__(self, opts=None):
+        super(L1ICache, self).__init__(opts)
+        if not opts or not opts.l1i_size:
+            return
+        self.size = opts.l1i_size
+
     def connectCPU(self, cpu):
         """Connect this cache's port to a CPU icache port"""
         self.cpu_side = cpu.icache_port
@@ -75,6 +83,12 @@
     # Set the default size
     size = '64kB'
 
+    def __init__(self, opts=None):
+        super(L1DCache, self).__init__(opts)
+        if not opts or not opts.l1d_size:
+            return
+        self.size = opts.l1d_size
+
     def connectCPU(self, cpu):
         """Connect this cache's port to a CPU dcache port"""
         self.cpu_side = cpu.dcache_port
@@ -91,10 +105,14 @@
     mshrs = 20
     tgts_per_mshr = 12
 
+    def __init__(self, opts=None):
+        super(L2Cache, self).__init__()
+        if not opts or not opts.l2_size:
+            return
+        self.size = opts.l2_size
+
     def connectCPUSideBus(self, bus):
-        """"Connect this cache to a cpu-side bus"""
-        self.cpu_side = bus.master
+        self.cpu_side = bus.mem_side_ports
 
     def connectMemSideBus(self, bus):
-        """"Connect this cache to a memory-side bus"""
-        self.mem_side = bus.slave
+        self.mem_side = bus.cpu_side_ports
diff --git a/_pages/static/scripts/part1/caches_opts.py b/_pages/static/scripts/part1/caches_opts.py
index 670d718..9a05aa0 100644
--- a/_pages/static/scripts/part1/caches_opts.py
+++ b/_pages/static/scripts/part1/caches_opts.py
@@ -24,26 +24,23 @@
 # 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
 
 """ 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. These caches take options as a parameter to their
-constructors to initialize some of their parameters.
-
+gem5 configuration script. It uses the SimpleOpts wrapper to set up command
+line options from each individual class.
 """
 
+import m5
 from m5.objects import Cache
 
 # Some specific options for caches
-# For all options see src/mem/cache/Cache.py
+# For all options see src/mem/cache/BaseCache.py
 
 class L1Cache(Cache):
     """Simple L1 Cache with default values"""
 
-    # Default parameters for both L1 I and D caches
     assoc = 2
     tag_latency = 2
     data_latency = 2
@@ -55,26 +52,26 @@
         super(L1Cache, self).__init__()
         pass
 
+    def connectBus(self, bus):
+        """Connect this cache to a memory-side bus"""
+        self.mem_side = bus.cpu_side_ports
+
     def connectCPU(self, cpu):
         """Connect this cache's port to a CPU-side port
            This must be defined in a subclass"""
         raise NotImplementedError
 
-    def connectBus(self, bus):
-        """Connect this cache to a memory-side bus"""
-        self.mem_side = bus.slave
-
 class L1ICache(L1Cache):
     """Simple L1 instruction cache with default values"""
 
     # Set the default size
     size = '16kB'
 
-    def __init__(self, options=None):
-        super(L1ICache, self).__init__(options)
-        if not options or not options.l1i_size:
+    def __init__(self, opts=None):
+        super(L1ICache, self).__init__(opts)
+        if not opts or not opts.l1i_size:
             return
-        self.size = options.l1i_size
+        self.size = opts.l1i_size
 
     def connectCPU(self, cpu):
         """Connect this cache's port to a CPU icache port"""
@@ -86,11 +83,11 @@
     # Set the default size
     size = '64kB'
 
-    def __init__(self, options=None):
-        super(L1DCache, self).__init__(options)
-        if not options or not options.l1d_size:
+    def __init__(self, opts=None):
+        super(L1DCache, self).__init__(opts)
+        if not opts or not opts.l1d_size:
             return
-        self.size = options.l1d_size
+        self.size = opts.l1d_size
 
     def connectCPU(self, cpu):
         """Connect this cache's port to a CPU dcache port"""
@@ -108,16 +105,14 @@
     mshrs = 20
     tgts_per_mshr = 12
 
-    def __init__(self, options=None):
+    def __init__(self, opts=None):
         super(L2Cache, self).__init__()
-        if not options or not options.l2_size:
+        if not opts or not opts.l2_size:
             return
-        self.size = options.l2_size
+        self.size = opts.l2_size
 
     def connectCPUSideBus(self, bus):
-        """"Connect this cache to a cpu-side bus"""
-        self.cpu_side = bus.master
+        self.cpu_side = bus.mem_side_ports
 
     def connectMemSideBus(self, bus):
-        """"Connect this cache to a memory-side bus"""
-        self.mem_side = bus.slave
+        self.mem_side = bus.cpu_side_ports
diff --git a/_pages/static/scripts/part1/simple.py b/_pages/static/scripts/part1/simple.py
index 1bf3eae..69521fe 100644
--- a/_pages/static/scripts/part1/simple.py
+++ b/_pages/static/scripts/part1/simple.py
@@ -24,14 +24,14 @@
 # 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 barebones system and executes 'hello', a simple Hello
 World application.
+See Part 1, Chapter 2: Creating a simple configuration script in the
+learning_gem5 book for more information about this script.
 
-This config file assumes that the x86 ISA was built.
-See gem5/configs/learning_gem5/part1/simple.py for a general script.
+IMPORTANT: If you modify this file, it's likely that the Learning gem5 book
+           also needs to be updated. For now, email Jason <power.jg@gmail.com>
 
 """
 
@@ -55,7 +55,7 @@
 # Create a simple CPU
 system.cpu = TimingSimpleCPU()
 
-# Create a memory bus, a coherent crossbar, in this case
+# Create a memory bus, a system crossbar, in this case
 system.membus = SystemXBar()
 
 # Hook the CPU ports up to the membus
@@ -64,23 +64,39 @@
 
 # create the interrupt controller for the CPU and connect to the membus
 system.cpu.createInterruptController()
-system.cpu.interrupts[0].pio = system.membus.master
-system.cpu.interrupts[0].int_master = system.membus.slave
-system.cpu.interrupts[0].int_slave = system.membus.master
+
+# For x86 only, make sure the interrupts are connected to the memory
+# Note: these are directly connected to the memory bus and are not cached
+if m5.defines.buildEnv['TARGET_ISA'] == "x86":
+    system.cpu.interrupts[0].pio = system.membus.master
+    system.cpu.interrupts[0].int_master = system.membus.slave
+    system.cpu.interrupts[0].int_slave = system.membus.master
 
 # Create a DDR3 memory controller and connect it to the membus
-system.mem_ctrl = DDR3_1600_8x8()
-system.mem_ctrl.range = system.mem_ranges[0]
+system.mem_ctrl = MemCtrl()
+system.mem_ctrl.dram = DDR3_1600_8x8()
+system.mem_ctrl.dram.range = system.mem_ranges[0]
 system.mem_ctrl.port = system.membus.master
 
 # Connect the system up to the membus
 system.system_port = system.membus.slave
 
+# get ISA for the binary to run.
+isa = str(m5.defines.buildEnv['TARGET_ISA']).lower()
+
+# Default to running 'hello', use the compiled ISA to find the binary
+# grab the specific path to the binary
+thispath = os.path.dirname(os.path.realpath(__file__))
+binary = os.path.join(thispath, '../../../',
+                      'tests/test-progs/hello/bin/', isa, 'linux/hello')
+
+system.workload = SEWorkload.init_compatible(binary)
+
 # Create a process for a simple "Hello World" application
 process = Process()
 # Set the command
 # cmd is a list which begins with the executable (like argv)
-process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
+process.cmd = [binary]
 # Set the cpu to use the process as its workload and create thread contexts
 system.cpu.workload = process
 system.cpu.createThreads()
@@ -90,6 +106,6 @@
 # instantiate all of the objects we've created above
 m5.instantiate()
 
-print "Beginning simulation!"
+print("Beginning simulation!")
 exit_event = m5.simulate()
-print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause())
+print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
diff --git a/_pages/static/scripts/part1/two_level.py b/_pages/static/scripts/part1/two_level.py
index 23c519b..64ee33c 100644
--- a/_pages/static/scripts/part1/two_level.py
+++ b/_pages/static/scripts/part1/two_level.py
@@ -24,13 +24,17 @@
 # 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 simple system with a single CPU and a 2-level cache
-and executes 'hello', a simple Hello World application.
+""" This file creates a single CPU and a two-level cache system.
+This script takes a single parameter which specifies a binary to execute.
+If none is provided it executes 'hello' by default (mostly used for testing)
 
-This config file assumes that the x86 ISA was built.
+See Part 1, Chapter 3: Adding cache to the configuration script in the
+learning_gem5 book for more information about this script.
+This file exports options for the L1 I/D and L2 cache sizes.
+
+IMPORTANT: If you modify this file, it's likely that the Learning gem5 book
+           also needs to be updated. For now, email Jason <power.jg@gmail.com>
 
 """
 
@@ -42,6 +46,15 @@
 # import the caches which we made
 from caches import *
 
+# get ISA for the default binary to run. This is mostly for simple testing
+isa = str(m5.defines.buildEnv['TARGET_ISA']).lower()
+
+# Default to running 'hello', use the compiled ISA to find the binary
+# grab the specific path to the binary
+thispath = os.path.dirname(os.path.realpath(__file__))
+binary = os.path.join(thispath, '../../../',
+                      'tests/test-progs/hello/bin/', isa, 'linux/hello')
+
 # create the system we are going to simulate
 system = System()
 
@@ -82,26 +95,32 @@
 # Connect the L2 cache to the membus
 system.l2cache.connectMemSideBus(system.membus)
 
-# create the interrupt controller for the CPU and connect to the membus
-# Note: these are directly connected to the memory bus and are not cached
+# create the interrupt controller for the CPU
 system.cpu.createInterruptController()
-system.cpu.interrupts[0].pio = system.membus.master
-system.cpu.interrupts[0].int_master = system.membus.slave
-system.cpu.interrupts[0].int_slave = system.membus.master
+
+# For x86 only, make sure the interrupts are connected to the memory
+# Note: these are directly connected to the memory bus and are not cached
+if m5.defines.buildEnv['TARGET_ISA'] == "x86":
+    system.cpu.interrupts[0].pio = system.membus.mem_side_ports
+    system.cpu.interrupts[0].int_requestor = system.membus.cpu_side_ports
+    system.cpu.interrupts[0].int_responder = system.membus.mem_side_ports
 
 # Connect the system up to the membus
-system.system_port = system.membus.slave
+system.system_port = system.membus.cpu_side_ports
 
 # Create a DDR3 memory controller
-system.mem_ctrl = DDR3_1600_8x8()
-system.mem_ctrl.range = system.mem_ranges[0]
-system.mem_ctrl.port = system.membus.master
+system.mem_ctrl = MemCtrl()
+system.mem_ctrl.dram = DDR3_1600_8x8()
+system.mem_ctrl.dram.range = system.mem_ranges[0]
+system.mem_ctrl.port = system.membus.mem_side_ports
+
+system.workload = SEWorkload.init_compatible(binary)
 
 # Create a process for a simple "Hello World" application
 process = Process()
 # Set the command
 # cmd is a list which begins with the executable (like argv)
-process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
+process.cmd = [binary]
 # Set the cpu to use the process as its workload and create thread contexts
 system.cpu.workload = process
 system.cpu.createThreads()
@@ -111,6 +130,6 @@
 # instantiate all of the objects we've created above
 m5.instantiate()
 
-print "Beginning simulation!"
+print("Beginning simulation!")
 exit_event = m5.simulate()
-print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause())
+print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
diff --git a/_pages/static/scripts/part1/two_level_opts.py b/_pages/static/scripts/part1/two_level_opts.py
index b176b6d..ce0dd47 100644
--- a/_pages/static/scripts/part1/two_level_opts.py
+++ b/_pages/static/scripts/part1/two_level_opts.py
@@ -24,14 +24,17 @@
 # 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 simple system with a single CPU and a 2-level cache
-and executes 'hello', a simple Hello World application.
+""" This file creates a single CPU and a two-level cache system.
+This script takes a single parameter which specifies a binary to execute.
+If none is provided it executes 'hello' by default (mostly used for testing)
 
-This config file assumes that the x86 ISA was built.
-See gem5/configs/learning_gem5/part1/two_level.py for a general script.
+See Part 1, Chapter 3: Adding cache to the configuration script in the
+learning_gem5 book for more information about this script.
+This file exports options for the L1 I/D and L2 cache sizes.
+
+IMPORTANT: If you modify this file, it's likely that the Learning gem5 book
+           also needs to be updated. For now, email Jason <power.jg@gmail.com>
 
 """
 
@@ -43,16 +46,34 @@
 # import the caches which we made
 from caches_opts import *
 
-# import the options parser
-from optparse import OptionParser
+# import the argparse module
+import argparse
 
-# add the options we want to be able to control from the command line
-parser = OptionParser()
-parser.add_option('--l1i_size', help="L1 instruction cache size")
-parser.add_option('--l1d_size', help="L1 data cache size")
-parser.add_option('--l2_size', help="Unified L2 cache size")
+# Set the usage message to display
+parser = argparse.ArgumentParser(description='A simple system with 2-level cache.')
+parser.add_argument("binary", default="", nargs="?", type=str,
+                    help="Path to the binary to execute.")
+parser.add_argument("--l1i_size",
+                    help=f"L1 instruction cache size. Default: 16kB.")
+parser.add_argument("--l1d_size",
+                    help="L1 data cache size. Default: Default: 64kB.")
+parser.add_argument("--l2_size",
+                    help="L2 cache size. Default: 256kB.")
+# Finalize the arguments and grab the opts so we can pass it on to our objects
+options = parser.parse_args()
 
-(options, args) = parser.parse_args()
+# get ISA for the default binary to run. This is mostly for simple testing
+isa = str(m5.defines.buildEnv['TARGET_ISA']).lower()
+
+# Default to running 'hello', use the compiled ISA to find the binary
+# grab the specific path to the binary
+thispath = os.path.dirname(os.path.realpath(__file__))
+binary = os.path.join(thispath, '../../../',
+                      'tests/test-progs/hello/bin/', isa, 'linux/hello')
+
+# If the executable is specified by user, run the hello program
+if hasattr(parser, "binary"):
+    binary = parser.binary
 
 # create the system we are going to simulate
 system = System()
@@ -94,26 +115,32 @@
 # Connect the L2 cache to the membus
 system.l2cache.connectMemSideBus(system.membus)
 
-# create the interrupt controller for the CPU and connect to the membus
-# Note: these are directly connected to the memory bus and are not cached
+# create the interrupt controller for the CPU
 system.cpu.createInterruptController()
-system.cpu.interrupts[0].pio = system.membus.master
-system.cpu.interrupts[0].int_master = system.membus.slave
-system.cpu.interrupts[0].int_slave = system.membus.master
+
+# For x86 only, make sure the interrupts are connected to the memory
+# Note: these are directly connected to the memory bus and are not cached
+if m5.defines.buildEnv['TARGET_ISA'] == "x86":
+    system.cpu.interrupts[0].pio = system.membus.mem_side_ports
+    system.cpu.interrupts[0].int_requestor = system.membus.cpu_side_ports
+    system.cpu.interrupts[0].int_responder = system.membus.mem_side_ports
 
 # Connect the system up to the membus
-system.system_port = system.membus.slave
+system.system_port = system.membus.cpu_side_ports
 
 # Create a DDR3 memory controller
-system.mem_ctrl = DDR3_1600_8x8()
-system.mem_ctrl.range = system.mem_ranges[0]
-system.mem_ctrl.port = system.membus.master
+system.mem_ctrl = MemCtrl()
+system.mem_ctrl.dram = DDR3_1600_8x8()
+system.mem_ctrl.dram.range = system.mem_ranges[0]
+system.mem_ctrl.port = system.membus.mem_side_ports
+
+system.workload = SEWorkload.init_compatible(binary)
 
 # Create a process for a simple "Hello World" application
 process = Process()
 # Set the command
 # cmd is a list which begins with the executable (like argv)
-process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
+process.cmd = [binary]
 # Set the cpu to use the process as its workload and create thread contexts
 system.cpu.workload = process
 system.cpu.createThreads()
@@ -123,6 +150,6 @@
 # instantiate all of the objects we've created above
 m5.instantiate()
 
-print "Beginning simulation!"
+print("Beginning simulation!")
 exit_event = m5.simulate()
-print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause())
+print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
diff --git a/_pages/static/scripts/part2/debugging/SConscript b/_pages/static/scripts/part2/debugging/SConscript
index 287f33b..312a559 100644
--- a/_pages/static/scripts/part2/debugging/SConscript
+++ b/_pages/static/scripts/part2/debugging/SConscript
@@ -32,4 +32,4 @@
 SimObject('HelloObject.py')
 Source('hello_object.cc')
 
-DebugFlag('Hello')
+DebugFlag('HelloExample', "For Learning gem5 Part 2. Simple example debug flag")
diff --git a/_pages/static/scripts/part2/debugging/hello_object.cc b/_pages/static/scripts/part2/debugging/hello_object.cc
index 6ba4813..b6add7d 100644
--- a/_pages/static/scripts/part2/debugging/hello_object.cc
+++ b/_pages/static/scripts/part2/debugging/hello_object.cc
@@ -28,16 +28,10 @@
  * Authors: Jason Lowe-Power
  */
 
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
 #include "learning_gem5/hello_object.hh"
 
-HelloObject::HelloObject(HelloObjectParams *params) : SimObject(params)
+HelloObject::HelloObject(const HelloObjectParams &params) : SimObject(params)
 {
-    DPRINTF(Hello, "Created the hello object\n");
-}
-
-HelloObject*
-HelloObjectParams::create()
-{
-    return new HelloObject(this);
+    DPRINTF(HelloExample, "Created the hello object\n");
 }
diff --git a/_pages/static/scripts/part2/events/hello_object.cc b/_pages/static/scripts/part2/events/hello_object.cc
index 9e622e0..41f577a 100644
--- a/_pages/static/scripts/part2/events/hello_object.cc
+++ b/_pages/static/scripts/part2/events/hello_object.cc
@@ -28,14 +28,14 @@
  * Authors: Jason Lowe-Power
  */
 
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
 #include "learning_gem5/hello_object.hh"
 
-HelloObject::HelloObject(HelloObjectParams *params) :
+HelloObject::HelloObject(const HelloObjectParams &params) :
     SimObject(params), event([this]{processEvent();}, name()),
     latency(100), timesLeft(10)
 {
-    DPRINTF(Hello, "Created the hello object\n");
+    DPRINTF(HelloExample, "Created the hello object\n");
 }
 
 void
@@ -48,17 +48,11 @@
 HelloObject::processEvent()
 {
     timesLeft--;
-    DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
+    DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);
 
     if (timesLeft <= 0) {
-        DPRINTF(Hello, "Done firing!\n");
+        DPRINTF(HelloExample, "Done firing!\n");
     } else {
         schedule(event, curTick() + latency);
     }
 }
-
-HelloObject*
-HelloObjectParams::create()
-{
-    return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/events/hello_object.hh b/_pages/static/scripts/part2/events/hello_object.hh
index 8aee5a9..022afb9 100644
--- a/_pages/static/scripts/part2/events/hello_object.hh
+++ b/_pages/static/scripts/part2/events/hello_object.hh
@@ -48,7 +48,7 @@
     int timesLeft;
 
   public:
-    HelloObject(HelloObjectParams *p);
+    HelloObject(const HelloObjectParams &p);
 
     void startup();
 };
diff --git a/_pages/static/scripts/part2/helloobject/hello_object.cc b/_pages/static/scripts/part2/helloobject/hello_object.cc
index 2e151dc..c1fead7 100644
--- a/_pages/static/scripts/part2/helloobject/hello_object.cc
+++ b/_pages/static/scripts/part2/helloobject/hello_object.cc
@@ -32,13 +32,7 @@
 
 #include <iostream>
 
-HelloObject::HelloObject(HelloObjectParams *params) : SimObject(params)
+HelloObject::HelloObject(const HelloObjectParams &params) : SimObject(params)
 {
     std::cout << "Hello World! From a SimObject!" << std::endl;
 }
-
-HelloObject*
-HelloObjectParams::create()
-{
-    return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/helloobject/hello_object.hh b/_pages/static/scripts/part2/helloobject/hello_object.hh
index ad1b6cc..a1680aa 100644
--- a/_pages/static/scripts/part2/helloobject/hello_object.hh
+++ b/_pages/static/scripts/part2/helloobject/hello_object.hh
@@ -37,7 +37,7 @@
 class HelloObject : public SimObject
 {
   public:
-    HelloObject(HelloObjectParams *p);
+    HelloObject(const HelloObjectParams &p);
 };
 
 #endif // __LEARNING_GEM5_HELLO_OBJECT_HH__
diff --git a/_pages/static/scripts/part2/memoryobject/SConscript b/_pages/static/scripts/part2/memoryobject/SConscript
index a8c948e..bebcec3 100644
--- a/_pages/static/scripts/part2/memoryobject/SConscript
+++ b/_pages/static/scripts/part2/memoryobject/SConscript
@@ -32,4 +32,4 @@
 SimObject('SimpleMemobj.py')
 Source('simple_memobj.cc')
 
-DebugFlag('SimpleMemobj')
+DebugFlag('SimpleMemobj', "For Learning gem5 Part 2.")
diff --git a/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py b/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
index 0f0b6da..b72ebe2 100644
--- a/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
+++ b/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
@@ -24,17 +24,14 @@
 # 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
 
 from m5.params import *
-from m5.proxy import *
-from MemObject import MemObject
+from m5.SimObject import SimObject
 
-class SimpleMemobj(MemObject):
+class SimpleMemobj(SimObject):
     type = 'SimpleMemobj'
-    cxx_header = "learning_gem5/simple_memobj/simple_memobj.hh"
+    cxx_header = "learning_gem5/part2/simple_memobj.hh"
 
-    inst_port = SlavePort("CPU side port, receives requests")
-    data_port = SlavePort("CPU side port, receives requests")
-    mem_side = MasterPort("Memory side port, sends requests")
+    inst_port = ResponsePort("CPU side port, receives requests")
+    data_port = ResponsePort("CPU side port, receives requests")
+    mem_side = RequestPort("Memory side port, sends requests")
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
index 8ea00a3..f8e52b8 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
@@ -30,9 +30,10 @@
 
 #include "learning_gem5/part2/simple_memobj.hh"
 
+#include "base/trace.hh"
 #include "debug/SimpleMemobj.hh"
 
-SimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
+SimpleMemobj::SimpleMemobj(const SimpleMemobjParams &params) :
     SimObject(params),
     instPort(params->name + ".inst_port", this),
     dataPort(params->name + ".data_port", this),
@@ -41,7 +42,8 @@
 {
 }
 
-Port &SimpleMemobj::getPort(const std::string &if_name, PortID idx)
+Port &
+SimpleMemobj::getPort(const std::string &if_name, PortID idx)
 {
     panic_if(idx != InvalidPortID, "This object doesn't support vector ports");
 
@@ -228,11 +230,3 @@
     instPort.sendRangeChange();
     dataPort.sendRangeChange();
 }
-
-
-
-SimpleMemobj*
-SimpleMemobjParams::create()
-{
-    return new SimpleMemobj(this);
-}
\ No newline at end of file
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.hh b/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
index a6c9c6d..4b7719a 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
@@ -50,7 +50,7 @@
      * Mostly just forwards requests to the owner.
      * Part of a vector of ports. One for each CPU port (e.g., data, inst)
      */
-    class CPUSidePort : public SlavePort
+    class CPUSidePort : public ResponsePort
     {
       private:
         /// The object that owns this object (SimpleMemobj)
@@ -67,7 +67,7 @@
          * Constructor. Just calls the superclass constructor.
          */
         CPUSidePort(const std::string& name, SimpleMemobj *owner) :
-            SlavePort(name, owner), owner(owner), needRetry(false),
+            ResponsePort(name, owner), owner(owner), needRetry(false),
             blockedPacket(nullptr)
         { }
 
@@ -81,7 +81,7 @@
 
         /**
          * Get a list of the non-overlapping address ranges the owner is
-         * responsible for. All slave ports must override this function
+         * responsible for. All response ports must override this function
          * and return a populated list with at least one item.
          *
          * @return a list of ranges responded to
@@ -96,14 +96,14 @@
 
       protected:
         /**
-         * Receive an atomic request packet from the master port.
+         * Receive an atomic request packet from the request port.
          * No need to implement in this simple memobj.
          */
         Tick recvAtomic(PacketPtr pkt) override
         { panic("recvAtomic unimpl."); }
 
         /**
-         * Receive a functional request packet from the master port.
+         * Receive a functional request packet from the request port.
          * Performs a "debug" access updating/reading the data in place.
          *
          * @param packet the requestor sent.
@@ -111,7 +111,7 @@
         void recvFunctional(PacketPtr pkt) override;
 
         /**
-         * Receive a timing request from the master port.
+         * Receive a timing request from the request port.
          *
          * @param the packet that the requestor sent
          * @return whether this object can consume the packet. If false, we
@@ -121,8 +121,8 @@
         bool recvTimingReq(PacketPtr pkt) override;
 
         /**
-         * Called by the master port if sendTimingResp was called on this
-         * slave port (causing recvTimingResp to be called on the master
+         * Called by the request port if sendTimingResp was called on this
+         * response port (causing recvTimingResp to be called on the request
          * port) and was unsuccesful.
          */
         void recvRespRetry() override;
@@ -132,7 +132,7 @@
      * Port on the memory-side that receives responses.
      * Mostly just forwards requests to the owner
      */
-    class MemSidePort : public MasterPort
+    class MemSidePort : public RequestPort
     {
       private:
         /// The object that owns this object (SimpleMemobj)
@@ -146,7 +146,7 @@
          * Constructor. Just calls the superclass constructor.
          */
         MemSidePort(const std::string& name, SimpleMemobj *owner) :
-            MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
+            RequestPort(name, owner), owner(owner), blockedPacket(nullptr)
         { }
 
         /**
@@ -159,19 +159,19 @@
 
       protected:
         /**
-         * Receive a timing response from the slave port.
+         * Receive a timing response from the response port.
          */
         bool recvTimingResp(PacketPtr pkt) override;
 
         /**
-         * Called by the slave port if sendTimingReq was called on this
-         * master port (causing recvTimingReq to be called on the slave
+         * Called by the response port if sendTimingReq was called on this
+         * request port (causing recvTimingReq to be called on the response
          * port) and was unsuccesful.
          */
         void recvReqRetry() override;
 
         /**
-         * Called to receive an address range change from the peer slave
+         * Called to receive an address range change from the peer response
          * port. The default implementation ignores the change and does
          * nothing. Override this function in a derived class if the owner
          * needs to be aware of the address ranges, e.g. in an
@@ -233,7 +233,7 @@
 
     /** constructor
      */
-    SimpleMemobj(SimpleMemobjParams *params);
+    SimpleMemobj(const SimpleMemobjParams &params);
 
     /**
      * Get a port with a given name and index. This is used at
@@ -250,4 +250,4 @@
 };
 
 
-#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
\ No newline at end of file
+#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.py b/_pages/static/scripts/part2/memoryobject/simple_memobj.py
index 8bc2baf..e13a372 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.py
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.py
@@ -24,8 +24,6 @@
 # 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
 
 """ This file creates a barebones system and executes 'hello', a simple Hello
 World application. Adds a simple memobj between the CPU and the membus.
@@ -68,32 +66,39 @@
 
 # create the interrupt controller for the CPU and connect to the membus
 system.cpu.createInterruptController()
-system.cpu.interrupts[0].pio = system.membus.master
-system.cpu.interrupts[0].int_master = system.membus.slave
-system.cpu.interrupts[0].int_slave = system.membus.master
+system.cpu.interrupts[0].pio = system.membus.mem_side_ports
+system.cpu.interrupts[0].int_master = system.membus.cpu_side_ports
+system.cpu.interrupts[0].int_slave = system.membus.mem_side_ports
 
 # Create a DDR3 memory controller and connect it to the membus
-system.mem_ctrl = DDR3_1600_8x8()
-system.mem_ctrl.range = system.mem_ranges[0]
-system.mem_ctrl.port = system.membus.master
+system.mem_ctrl = MemCtrl()
+system.mem_ctrl.dram = DDR3_1600_8x8()
+system.mem_ctrl.dram.range = system.mem_ranges[0]
+system.mem_ctrl.port = system.membus.mem_side_ports
 
 # Connect the system up to the membus
-system.system_port = system.membus.slave
+system.system_port = system.membus.cpu_side_ports
 
 # Create a process for a simple "Hello World" application
 process = Process()
 # Set the command
+# grab the specific path to the binary
+thispath = os.path.dirname(os.path.realpath(__file__))
+binpath = os.path.join(thispath, '../../../',
+                       'tests/test-progs/hello/bin/x86/linux/hello')
 # cmd is a list which begins with the executable (like argv)
-process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
+process.cmd = [binpath]
 # Set the cpu to use the process as its workload and create thread contexts
 system.cpu.workload = process
 system.cpu.createThreads()
 
+system.workload = SEWorkload.init_compatible(binpath)
+
 # set up the root SimObject and start the simulation
 root = Root(full_system = False, system = system)
 # instantiate all of the objects we've created above
 m5.instantiate()
 
-print('Beginning simulation!')
+print("Beginning simulation!")
 exit_event = m5.simulate()
 print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
diff --git a/_pages/static/scripts/part2/parameters/SConscript b/_pages/static/scripts/part2/parameters/SConscript
index f0949f7..660fc50 100644
--- a/_pages/static/scripts/part2/parameters/SConscript
+++ b/_pages/static/scripts/part2/parameters/SConscript
@@ -33,4 +33,4 @@
 Source('hello_object.cc')
 Source('goodbye_object.cc')
 
-DebugFlag('Hello')
+DebugFlag('HelloExample', 'For Learning gem5 Part 2. Simple example debug flag')
diff --git a/_pages/static/scripts/part2/parameters/goodbye_object.cc b/_pages/static/scripts/part2/parameters/goodbye_object.cc
index 779302c..2c6343d 100644
--- a/_pages/static/scripts/part2/parameters/goodbye_object.cc
+++ b/_pages/static/scripts/part2/parameters/goodbye_object.cc
@@ -30,15 +30,15 @@
 
 #include "learning_gem5/goodbye_object.hh"
 
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
 #include "sim/sim_exit.hh"
 
-GoodbyeObject::GoodbyeObject(GoodbyeObjectParams *params) :
+GoodbyeObject::GoodbyeObject(const GoodbyeObjectParams &params) :
     SimObject(params), event(*this), bandwidth(params->write_bandwidth),
     bufferSize(params->buffer_size), buffer(nullptr), bufferUsed(0)
 {
     buffer = new char[bufferSize];
-    DPRINTF(Hello, "Created the goodbye object\n");
+    DPRINTF(HelloExample, "Created the goodbye object\n");
 }
 
 GoodbyeObject::~GoodbyeObject()
@@ -49,14 +49,14 @@
 void
 GoodbyeObject::processEvent()
 {
-    DPRINTF(Hello, "Processing the event!\n");
+    DPRINTF(HelloExample, "Processing the event!\n");
     fillBuffer();
 }
 
 void
 GoodbyeObject::sayGoodbye(std::string other_name)
 {
-    DPRINTF(Hello, "Saying goodbye to %s\n", other_name);
+    DPRINTF(HelloExample, "Saying goodbye to %s\n", other_name);
 
     message = "Goodbye " + other_name + "!! ";
 
@@ -80,18 +80,12 @@
 
     if (bufferUsed < bufferSize - 1) {
         // Wait for the next copy for as long as it would have taken
-        DPRINTF(Hello, "Scheduling another fillBuffer in %d ticks\n",
+        DPRINTF(HelloExample, "Scheduling another fillBuffer in %d ticks\n",
                 bandwidth * bytes_copied);
         schedule(event, curTick() + bandwidth * bytes_copied);
     } else {
-        DPRINTF(Hello, "Goodbye done copying!\n");
+        DPRINTF(HelloExample, "Goodbye done copying!\n");
         // Be sure to take into account the time for the last bytes
         exitSimLoop(buffer, 0, curTick() + bandwidth * bytes_copied);
     }
 }
-
-GoodbyeObject*
-GoodbyeObjectParams::create()
-{
-    return new GoodbyeObject(this);
-}
diff --git a/_pages/static/scripts/part2/parameters/hello_object.cc b/_pages/static/scripts/part2/parameters/hello_object.cc
index 73ee372..173a8ce 100644
--- a/_pages/static/scripts/part2/parameters/hello_object.cc
+++ b/_pages/static/scripts/part2/parameters/hello_object.cc
@@ -28,10 +28,10 @@
  * Authors: Jason Lowe-Power
  */
 
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
 #include "learning_gem5/hello_object.hh"
 
-HelloObject::HelloObject(HelloObjectParams *params) :
+HelloObject::HelloObject(const HelloObjectParams &params) :
     SimObject(params),
     event(*this),
     goodbye(params->goodbye_object),
@@ -39,7 +39,7 @@
     latency(params->time_to_wait),
     timesLeft(params->number_of_fires)
 {
-    DPRINTF(Hello, "Created the hello object\n");
+    DPRINTF(HelloExample, "Created the hello object\n");
 }
 
 void
@@ -52,7 +52,7 @@
 HelloObject::processEvent()
 {
     timesLeft--;
-    DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
+    DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);
 
     if (timesLeft <= 0) {
         DPRINTF(Hello, "Done firing!\n");
@@ -61,9 +61,3 @@
         schedule(event, curTick() + latency);
     }
 }
-
-HelloObject*
-HelloObjectParams::create()
-{
-    return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/parameters/hello_object.hh b/_pages/static/scripts/part2/parameters/hello_object.hh
index f70de97..8f408b3 100644
--- a/_pages/static/scripts/part2/parameters/hello_object.hh
+++ b/_pages/static/scripts/part2/parameters/hello_object.hh
@@ -57,7 +57,7 @@
     int timesLeft;
 
   public:
-    HelloObject(HelloObjectParams *p);
+    HelloObject(const HelloObjectParams &p);
 
     void startup();
 };
diff --git a/_pages/static/scripts/part2/simplecache/SimpleCache.py b/_pages/static/scripts/part2/simplecache/SimpleCache.py
index ef88d5f..97b38a6 100644
--- a/_pages/static/scripts/part2/simplecache/SimpleCache.py
+++ b/_pages/static/scripts/part2/simplecache/SimpleCache.py
@@ -35,8 +35,8 @@
     type = 'SimpleCache'
     cxx_header = "learning_gem5/simple_cache/simple_cache.hh"
 
-    cpu_side = VectorSlavePort("CPU side port, receives requests")
-    mem_side = MasterPort("Memory side port, sends requests")
+    cpu_side = VectorResponsePort("CPU side port, receives requests")
+    mem_side = RequestPort("Memory side port, sends requests")
 
     latency = Param.Cycles(1, "Cycles taken on a hit or to resolve a miss")
 
diff --git a/_pages/static/scripts/part2/simplecache/simple_cache.cc b/_pages/static/scripts/part2/simplecache/simple_cache.cc
index 1cfd0d9..788291f 100644
--- a/_pages/static/scripts/part2/simplecache/simple_cache.cc
+++ b/_pages/static/scripts/part2/simplecache/simple_cache.cc
@@ -24,45 +24,45 @@
  * 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
  */
 
-#include "learning_gem5/simple_cache/simple_cache.hh"
+#include "learning_gem5/part2/simple_cache.hh"
 
 #include "base/random.hh"
 #include "debug/SimpleCache.hh"
 #include "sim/system.hh"
 
-SimpleCache::SimpleCache(SimpleCacheParams *params) :
-    MemObject(params),
-    latency(params->latency),
-    blockSize(params->system->cacheLineSize()),
-    capacity(params->size / blockSize),
-    memPort(params->name + ".mem_side", this),
-    blocked(false), outstandingPacket(nullptr), waitingPortId(-1)
+SimpleCache::SimpleCache(const SimpleCacheParams &params) :
+    ClockedObject(params),
+    latency(params.latency),
+    blockSize(params.system->cacheLineSize()),
+    capacity(params.size / blockSize),
+    memPort(params.name + ".mem_side", this),
+    blocked(false), originalPacket(nullptr), waitingPortId(-1), stats(this)
 {
     // Since the CPU side ports are a vector of ports, create an instance of
     // the CPUSidePort for each connection. This member of params is
     // automatically created depending on the name of the vector port and
     // holds the number of connections to this port name
-    for (int i = 0; i < params->port_cpu_side_connection_count; ++i) {
+    for (int i = 0; i < params.port_cpu_side_connection_count; ++i) {
         cpuPorts.emplace_back(name() + csprintf(".cpu_side[%d]", i), i, this);
     }
 }
 
-Port&
-SimpleCache::getPort(const std::string& if_name, PortID idx)
+Port &
+SimpleCache::getPort(const std::string &if_name, PortID idx)
 {
-    // This is the name from the Python SimObject declaration (SimpleMemobj.py)
-    if (if_name == "cpu_side" && idx < cpuPorts.size()) {
+    // This is the name from the Python SimObject declaration in SimpleCache.py
+    if (if_name == "mem_side") {
+        panic_if(idx != InvalidPortID,
+                 "Mem side of simple cache not a vector port");
+        return memPort;
+    } else if (if_name == "cpu_side" && idx < cpuPorts.size()) {
         // We should have already created all of the ports in the constructor
         return cpuPorts[idx];
-    } else if (if_name == "mem_side") {
-        return memPort;
     } else {
         // pass it along to our super class
-        return MemObject::getPort(if_name, idx);
+        return ClockedObject::getPort(if_name, idx);
     }
 }
 
@@ -204,7 +204,9 @@
     waitingPortId = port_id;
 
     // Schedule an event after cache access latency to actually access
-    schedule(new AccessEvent(this, pkt), clockEdge(latency));
+    schedule(new EventFunctionWrapper([this, pkt]{ accessTiming(pkt); },
+                                      name() + ".accessEvent", true),
+             clockEdge(latency));
 
     return true;
 }
@@ -219,18 +221,20 @@
     // for any added latency.
     insert(pkt);
 
-    missLatency.sample(curTick() - missTime);
+    stats.missLatency.sample(curTick() - missTime);
 
-    if (outstandingPacket != nullptr) {
+    // If we had to upgrade the request packet to a full cache line, now we
+    // can use that packet to construct the response.
+    if (originalPacket != nullptr) {
         DPRINTF(SimpleCache, "Copying data from new packet to old\n");
         // We had to upgrade a previous packet. We can functionally deal with
         // the cache access now. It better be a hit.
-        bool hit M5_VAR_USED = accessFunctional(outstandingPacket);
+        M5_VAR_USED bool hit = accessFunctional(originalPacket);
         panic_if(!hit, "Should always hit after inserting");
-        outstandingPacket->makeResponse();
+        originalPacket->makeResponse();
         delete pkt; // We may need to delay this, I'm not sure.
-        pkt = outstandingPacket;
-        outstandingPacket = nullptr;
+        pkt = originalPacket;
+        originalPacket = nullptr;
     } // else, pkt contains the data it needs
 
     sendResponse(pkt);
@@ -282,12 +286,12 @@
 
     if (hit) {
         // Respond to the CPU side
-        hits++; // update stats
+        stats.hits++; // update stats
         DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), pkt->getSize());
         pkt->makeResponse();
         sendResponse(pkt);
     } else {
-        misses++; // update stats
+        stats.misses++; // update stats
         missTime = curTick();
         // Forward to the memory side.
         // We can't directly forward the packet unless it is exactly the size
@@ -322,7 +326,7 @@
             assert(new_pkt->getAddr() == new_pkt->getBlockAddr(blockSize));
 
             // Save the old packet
-            outstandingPacket = pkt;
+            originalPacket = pkt;
 
             DPRINTF(SimpleCache, "forwarding packet\n");
             memPort.sendPacket(new_pkt);
@@ -374,13 +378,15 @@
 
         // Write back the data.
         // Create a new request-packet pair
-        RequestPtr req(new Request(block->first, blockSize, 0, 0));
+        RequestPtr req = std::make_shared<Request>(
+            block->first, blockSize, 0, 0);
+
         PacketPtr new_pkt = new Packet(req, MemCmd::WritebackDirty, blockSize);
         new_pkt->dataDynamic(block->second); // This will be deleted later
 
         DPRINTF(SimpleCache, "Writing packet back %s\n", pkt->print());
         // Send the write to memory
-        memPort.sendTimingReq(new_pkt);
+        memPort.sendPacket(new_pkt);
 
         // Delete this entry
         cacheStore.erase(block->first);
@@ -415,36 +421,14 @@
     }
 }
 
-void
-SimpleCache::regStats()
+SimpleCache::SimpleCacheStats::SimpleCacheStats(Stats::Group *parent)
+      : Stats::Group(parent),
+      ADD_STAT(hits, UNIT_COUNT, "Number of hits"),
+      ADD_STAT(misses, UNIT_COUNT, "Number of misses"),
+      ADD_STAT(missLatency, UNIT_TICK, "Ticks for misses to the cache"),
+      ADD_STAT(hitRatio, UNIT_RATIO,
+               "The ratio of hits to the total accesses to the cache",
+               hits / (hits + misses))
 {
-    // If you don't do this you get errors about uninitialized stats.
-    MemObject::regStats();
-
-    hits.name(name() + ".hits")
-        .desc("Number of hits")
-        ;
-
-    misses.name(name() + ".misses")
-        .desc("Number of misses")
-        ;
-
-    missLatency.name(name() + ".missLatency")
-        .desc("Ticks for misses to the cache")
-        .init(16) // number of buckets
-        ;
-
-    hitRatio.name(name() + ".hitRatio")
-        .desc("The ratio of hits to the total accesses to the cache")
-        ;
-
-    hitRatio = hits / (hits + misses);
-
-}
-
-
-SimpleCache*
-SimpleCacheParams::create()
-{
-    return new SimpleCache(this);
+    missLatency.init(16); // number of buckets
 }
diff --git a/_pages/static/scripts/part2/simplecache/simple_cache.hh b/_pages/static/scripts/part2/simplecache/simple_cache.hh
index 725cc6c..68ab001 100644
--- a/_pages/static/scripts/part2/simplecache/simple_cache.hh
+++ b/_pages/static/scripts/part2/simplecache/simple_cache.hh
@@ -24,8 +24,6 @@
  * 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
  */
 
 #ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__
@@ -33,8 +31,10 @@
 
 #include <unordered_map>
 
-#include "mem/mem_object.hh"
+#include "base/statistics.hh"
+#include "mem/port.hh"
 #include "params/SimpleCache.hh"
+#include "sim/clocked_object.hh"
 
 /**
  * A very simple cache object. Has a fully-associative data store with random
@@ -43,7 +43,7 @@
  * be outstanding at a time.
  * This cache is a writeback cache.
  */
-class SimpleCache : public MemObject
+class SimpleCache : public ClockedObject
 {
   private:
 
@@ -51,7 +51,7 @@
      * Port on the CPU-side that receives requests.
      * Mostly just forwards requests to the cache (owner)
      */
-    class CPUSidePort : public SlavePort
+    class CPUSidePort : public ResponsePort
     {
       private:
         /// Since this is a vector port, need to know what number this one is
@@ -71,7 +71,7 @@
          * Constructor. Just calls the superclass constructor.
          */
         CPUSidePort(const std::string& name, int id, SimpleCache *owner) :
-            SlavePort(name, owner), id(id), owner(owner), needRetry(false),
+            ResponsePort(name, owner), id(id), owner(owner), needRetry(false),
             blockedPacket(nullptr)
         { }
 
@@ -86,7 +86,7 @@
 
         /**
          * Get a list of the non-overlapping address ranges the owner is
-         * responsible for. All slave ports must override this function
+         * responsible for. All response ports must override this function
          * and return a populated list with at least one item.
          *
          * @return a list of ranges responded to
@@ -101,14 +101,14 @@
 
       protected:
         /**
-         * Receive an atomic request packet from the master port.
+         * Receive an atomic request packet from the request port.
          * No need to implement in this simple cache.
          */
         Tick recvAtomic(PacketPtr pkt) override
         { panic("recvAtomic unimpl."); }
 
         /**
-         * Receive a functional request packet from the master port.
+         * Receive a functional request packet from the request port.
          * Performs a "debug" access updating/reading the data in place.
          *
          * @param packet the requestor sent.
@@ -116,7 +116,7 @@
         void recvFunctional(PacketPtr pkt) override;
 
         /**
-         * Receive a timing request from the master port.
+         * Receive a timing request from the request port.
          *
          * @param the packet that the requestor sent
          * @return whether this object can consume to packet. If false, we
@@ -126,9 +126,9 @@
         bool recvTimingReq(PacketPtr pkt) override;
 
         /**
-         * Called by the master port if sendTimingResp was called on this
-         * slave port (causing recvTimingResp to be called on the master
-         * port) and was unsuccesful.
+         * Called by the request port if sendTimingResp was called on this
+         * response port (causing recvTimingResp to be called on the request
+         * port) and was unsuccessful.
          */
         void recvRespRetry() override;
     };
@@ -137,7 +137,7 @@
      * Port on the memory-side that receives responses.
      * Mostly just forwards requests to the cache (owner)
      */
-    class MemSidePort : public MasterPort
+    class MemSidePort : public RequestPort
     {
       private:
         /// The object that owns this object (SimpleCache)
@@ -151,7 +151,7 @@
          * Constructor. Just calls the superclass constructor.
          */
         MemSidePort(const std::string& name, SimpleCache *owner) :
-            MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
+            RequestPort(name, owner), owner(owner), blockedPacket(nullptr)
         { }
 
         /**
@@ -165,19 +165,19 @@
 
       protected:
         /**
-         * Receive a timing response from the slave port.
+         * Receive a timing response from the response port.
          */
         bool recvTimingResp(PacketPtr pkt) override;
 
         /**
-         * Called by the slave port if sendTimingReq was called on this
-         * master port (causing recvTimingReq to be called on the slave
+         * Called by the response port if sendTimingReq was called on this
+         * request port (causing recvTimingReq to be called on the response
          * port) and was unsuccesful.
          */
         void recvReqRetry() override;
 
         /**
-         * Called to receive an address range change from the peer slave
+         * Called to receive an address range change from the peer response
          * port. The default implementation ignores the change and does
          * nothing. Override this function in a derived class if the owner
          * needs to be aware of the address ranges, e.g. in an
@@ -198,7 +198,7 @@
     bool handleRequest(PacketPtr pkt, int port_id);
 
     /**
-     * Handle the response from the memory side. Called from the memory port
+     * Handle the respone from the memory side. Called from the memory port
      * on a timing response.
      *
      * @param responding packet
@@ -280,7 +280,7 @@
 
     /// Packet that we are currently handling. Used for upgrading to larger
     /// cache line sizes
-    PacketPtr outstandingPacket;
+    PacketPtr originalPacket;
 
     /// The port to send the response when we recieve it back
     int waitingPortId;
@@ -291,61 +291,36 @@
     /// An incredibly simple cache storage. Maps block addresses to data
     std::unordered_map<Addr, uint8_t*> cacheStore;
 
-    /**
-     * Class for an event to delay handling a packet.
-     * Automatically deletes itself after process is called.
-     */
-    class AccessEvent : public Event
-    {
-      private:
-        /// Pointer to the cache object
-        SimpleCache *cache;
-
-        /// The packet we need to handle
-        PacketPtr pkt;
-      public:
-        AccessEvent(SimpleCache *cache, PacketPtr pkt) :
-            Event(Default_Pri, AutoDelete), cache(cache), pkt(pkt)
-        { }
-
-        /** Process the event. Just call into the cache.
-         */
-        void process() override {
-            cache->accessTiming(pkt);
-        }
-    };
-
-    friend class AccessEvent;
-
     /// Cache statistics
-    Stats::Scalar hits;
-    Stats::Scalar misses;
-    Stats::Histogram missLatency;
-    Stats::Formula hitRatio;
+  protected:
+    struct SimpleCacheStats : public Stats::Group
+    {
+        SimpleCacheStats(Stats::Group *parent);
+        Stats::Scalar hits;
+        Stats::Scalar misses;
+        Stats::Histogram missLatency;
+        Stats::Formula hitRatio;
+    } stats;
 
   public:
 
     /** constructor
      */
-    SimpleCache(SimpleCacheParams *params);
+    SimpleCache(const SimpleCacheParams &params);
 
     /**
      * Get a port with a given name and index. This is used at
      * binding time and returns a reference to a protocol-agnostic
-     * base master port.
+     * port.
      *
      * @param if_name Port name
      * @param idx Index in the case of a VectorPort
      *
      * @return A reference to the given port
      */
-    Port& getPort(const std::string& if_name,
-                                  PortID idx = InvalidPortID) override;
+    Port &getPort(const std::string &if_name,
+                  PortID idx=InvalidPortID) override;
 
-    /**
-     * Register the stats
-     */
-    void regStats() override;
 };