website: Update learning_gem5 part 2 scripts

Signed-off-by: Hoa Nguyen <hoanguyen@ucdavis.edu>
Change-Id: Id39ea9fc6601ee29c3a8763357cb1dc23ff913a3
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-website/+/46360
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: Bobby R. Bruce <bbruce@ucdavis.edu>
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;
 };