website: part 2 memory objects

fixes include inheritance, missing links, figure references,
matching code to github, and other small discrepancies

Change-Id: I7c95da315bb4a66f7e31b873dde5f058f13d6c44
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-website/+/31714
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/_pages/documentation/learning_gem5/part2/part2_5_memoryobject.md b/_pages/documentation/learning_gem5/part2/part2_5_memoryobject.md
index f688a40..9908007 100644
--- a/_pages/documentation/learning_gem5/part2/part2_5_memoryobject.md
+++ b/_pages/documentation/learning_gem5/part2/part2_5_memoryobject.md
@@ -21,7 +21,7 @@
 
 Before diving into the implementation of a memory object, we should
 first understand gem5's master and slave port interface. As previously
-discussed in simple-config-chapter, all memory objects are connected
+discussed in [simple-config-chapter](../../part1/simple_config), all memory objects are connected
 together via ports. These ports provide a rigid interface between these
 memory objects.
 
@@ -87,7 +87,7 @@
 ports, respectively. Master ports send requests (and receive response),
 and slave ports receive requests (and send responses).
 
-master-slave-1-fig outlines the simplest interaction between a master
+The figure below outlines the simplest interaction between a master
 and slave port. This figure shows the interaction in timing mode. The
 other modes are much simpler and use a simple callchain between the
 master and the slave.
@@ -110,7 +110,7 @@
 value of `false`, on the other hand, means that the slave was unable to
 accept and the request must be retried sometime in the future.
 
-In master-slave-1-fig, first, the master sends a timing request by
+In the figure above, first, the master sends a timing request by
 calling `sendTimingReq`, which in turn calls `recvTimingResp`. The
 slave, returns true from `recvTimingResp`, which is returned from the
 call to `sendTimingReq`. The master continue executing, and the slave
@@ -130,7 +130,7 @@
 these functions.
 
 It is possible that the master or slave is busy when they receive a
-request or a response. master-slave-2-fig shows the case where the slave
+request or a response. The figure below shows the case where the slave
 is busy when the original request was sent.
 
 ![Simple master-slave interaction when the slave is
@@ -145,7 +145,7 @@
 master to track the packet that fails, not the slave. The slave *does
 not* keep the pointer to the packet that fails.
 
-Similarly, master-slave-3-fig shows the case when the master is busy at
+Similarly, this figure shows the case when the master is busy at
 the time the slave tries to send a response. In this case, the slave
 cannot call `sendTimingResp` until it receives a `recvRespRetry`.
 
@@ -164,10 +164,10 @@
 
 In this section, we will build a simple memory object. Initially, it
 will simply pass requests through from the CPU-side (a simple CPU) to
-the memory-side (a simple memory bus). See Figure simple-memobj-figure.
+the memory-side (a simple memory bus). See the figure below.
 It will have a single master port, to send requests to the memory bus,
 and two cpu-side ports for the instruction and data cache ports of the
-CPU. In the next chapter \<simplecache-chapter\>, we will add the logic
+CPU. In the next chapter [simplecache-chapter](../simplecache), we will add the logic
 to make this object a cache.
 
 ![System with a simple memory object which sits between a CPU and the
@@ -176,28 +176,27 @@
 ### Declare the SimObject
 
 Just like when we were creating the simple SimObject in
-hello-simobject-chapter, the first step is to create a SimObject Python
+[hello-simobject-chapter](../helloobject), the first step is to create a SimObject Python
 file. We will call this simple memory object `SimpleMemobj` and create
 the SimObject Python file in `src/learning_gem5/simple_memobj`.
 
 ```python
 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")
 ```
 
-For this object, we inherit from `MemObject`, not `SimObject` since we
-are creating an object that will interact with the memory system. The
-`MemObject` class has two pure virtual functions that we will have to
-define in our C++ implementation, `getMasterPort` and `getSlavePort`.
+For this object, we inherit from `SimObject`. The
+`SimObject` class has a pure virtual functions that we will have to
+define in our C++ implementation, `getPort`.
 
 This object's parameters are three ports. Two ports for the CPU to
 connect the instruction and data ports and a port to connect to the
@@ -206,7 +205,7 @@
 
 It is important to remember the names of these ports. We will explicitly
 use these names when implementing `SimpleMemobj` and defining the
-`getMasterPort` and `getSlavePort` functions.
+`getPort` function.
 
 You can download the SimObject file
 [here](/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py).
@@ -221,7 +220,11 @@
 Now, we create a header file for `SimpleMemobj`.
 
 ```cpp
-class SimpleMemobj : public MemObject
+#include "mem/port.hh"
+#include "params/SimpleMemobj.hh"
+#include "sim/sim_object.hh"
+
+class SimpleMemobj : public SimObject
 {
   private:
 
@@ -296,17 +299,17 @@
 
 This class only has three pure virtual functions that we must override.
 
-### Defining the MemObject interface
+### Defining the SimObject interface
 
 Now that we have defined these two new types `CPUSidePort` and
 `MemSidePort`, we can declare our three ports as part of `SimpleMemobj`.
-We also need to declare the two pure virtual functions in the
-`MemObject` class, `getMasterPort` and `getSlavePort`. These two
-functions are used by gem5 during the initialization phase to connect
+We also need to declare the pure virtual function in the
+`SimObject` class, `getPort`. The
+function is used by gem5 during the initialization phase to connect
 memory objects together via ports.
 
 ```cpp
-class SimpleMemobj : public MemObject
+class SimpleMemobj : public SimObject
 {
   private:
 
@@ -321,81 +324,66 @@
   public:
     SimpleMemobj(SimpleMemobjParams *params);
 
-    BaseMasterPort& getMasterPort(const std::string& if_name,
-                                  PortID idx = InvalidPortID) override;
-
-    BaseSlavePort& getSlavePort(const std::string& if_name,
-                                PortID idx = InvalidPortID) override;
-
+    Port &getPort(const std::string &if_name,
+                  PortID idx=InvalidPortID) override;
 };
 ```
 
 You can download the header file for the `SimpleMemobj`
 [here](/_pages/static/scripts/part2/memoryobject/simple_memobj.hh).
 
-### Implementing basic MemObject functions
+### Implementing basic SimObject functions
 
 For the constructor of `SimpleMemobj`, we will simply call the
-`MemObject` constructor. We also need to initialize all of the ports.
+`SimObject` constructor. We also need to initialize all of the ports.
 Each port's constructor takes two parameters: the name and a pointer to
 its owner, as we defined in the header file. The name can be any string,
-but by convention, it is the same name as in the Python SimObject file.
+but by convention, it is the same name as in the Python SimObject file. We also initialize blocked to be false.
 
 ```cpp
+#include "learning_gem5/part2/simple_memobj.hh"
+#include "debug/SimpleMemobj.hh"
+
 SimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
-    MemObject(params),
+    SimObject(params),
     instPort(params->name + ".inst_port", this),
     dataPort(params->name + ".data_port", this),
-    memPort(params->name + ".mem_side", this)
+    memPort(params->name + ".mem_side", this), blocked(false)
 {
 }
 ```
 
 Next, we need to implement the interfaces to get the ports. This
-interface is made of two functions `getMasterPort` and `getSlavePort`.
-These functions take two parameters. The `if_name` is the Python
-variable name of the interface for *this* object. In the case of the
-master port it will be `mem_side` since this is what we declared as a
-`MasterPort` in the Python SimObject file.
+interface is made of the function `getPort`.
+The function takes two parameters. The `if_name` is the Python
+variable name of the interface for *this* object. 
 
-To implement `getMasterPort`, we compare the `if_name` and check to see
+To implement `getPort`, we compare the `if_name` and check to see
 if it is `mem_side` as specified in our Python SimObject file. If it is,
-then we return the `memPort` object. If not, then we pass the request
-name to our parent. However, it will be an error if we try to connect a
-slave port to any other named port since the parent class has no ports
-defined.
+then we return the `memPort` object. If the name is `"inst_port"`, then we return the
+instPort, and if the name is `data_port` we return the data port. If not, then we pass the request name to our parent. 
 
 ```cpp
-BaseMasterPort&
-SimpleMemobj::getMasterPort(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");
+
+    // This is the name from the Python SimObject declaration (SimpleMemobj.py)
     if (if_name == "mem_side") {
         return memPort;
-    } else {
-        return MemObject::getMasterPort(if_name, idx);
-    }
-}
-```
-
-To implement `getSlavePort`, we similarly check if the `if_name` matches
-either of the names we defined for our slave ports in the Python
-SimObject file. If the name is `"inst_port"`, then we return the
-instPort, and if the name is `data_port` we return the data port.
-
-```cpp
-BaseSlavePort&
-SimpleMemobj::getSlavePort(const std::string& if_name, PortID idx)
-{
-    if (if_name == "inst_port") {
+    } else if (if_name == "inst_port") {
         return instPort;
     } else if (if_name == "data_port") {
         return dataPort;
     } else {
-        return MemObject::getSlavePort(if_name, idx);
+        // pass it along to our super class
+        return SimObject::getPort(if_name, idx);
     }
 }
 ```
 
+
 ### Implementing slave and master port functions
 
 The implementation of both the slave and master port is relatively
@@ -647,7 +635,7 @@
 retry is needed which we marked in `recvTimingReq` whenever the
 `SimpleMemobj` was blocked on a new request. Then, if the retry is
 needed, this function calls `sendRetryReq`, which in turn calls
-`recvReqRetry` on the peer master port (the CPU in this case).
+`recvReqRetry` on the peer master port (the CPU in this case). 
 
 ```cpp
 void
@@ -660,11 +648,18 @@
     }
 }
 ```
-
+In addition to this function, to finish the file add the create function for SimpleMemobj.
+```cpp
+SimpleMemobj*
+SimpleMemobjParams::create()
+{
+    return new SimpleMemobj(this);
+}
+```
 You can download the implementation for the `SimpleMemobj`
 [here](/_pages/static/scripts/part2/memoryobject/simple_memobj.cc).
 
-The following figure, memobj-api-figure, shows the relationships between
+The following figure shows the relationships between
 the `CPUSidePort`, `MemSidePort`, and `SimpleMemobj`. This figure shows
 how the peer ports interact with the implementation of the
 `SimpleMemobj`. Each bold function is one that we had to implement, and
@@ -688,7 +683,7 @@
 SimpleMemobj to your system.
 
 This config file builds off of the simple config file in
-simple-config-chapter. However, instead of connecting the CPU directly
+[simple-config-chapter](../../part1/simple_config). However, instead of connecting the CPU directly
 to the memory bus, we are going to instantiate a `SimpleMemobj` and
 place it between the CPU and the memory bus.
 
@@ -733,9 +728,9 @@
 root = Root(full_system = False, system = system)
 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()))
 ```
 
 You can download this config script
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
index 45e16e9..8ea00a3 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
@@ -28,12 +28,12 @@
  * Authors: Jason Lowe-Power
  */
 
-#include "learning_gem5/simple_memobj/simple_memobj.hh"
+#include "learning_gem5/part2/simple_memobj.hh"
 
 #include "debug/SimpleMemobj.hh"
 
 SimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
-    MemObject(params),
+    SimObject(params),
     instPort(params->name + ".inst_port", this),
     dataPort(params->name + ".data_port", this),
     memPort(params->name + ".mem_side", this),
@@ -41,21 +41,20 @@
 {
 }
 
-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");
 
-    // This is the name from the Python SimObject declaration in SimpleCache.py
-    if (if_name == "inst_port") {
+    // This is the name from the Python SimObject declaration (SimpleMemobj.py)
+    if (if_name == "mem_side") {
+        return memPort;
+    } else if (if_name == "inst_port") {
         return instPort;
     } else if (if_name == "data_port") {
         return dataPort;
-    } else if (if_name == "mem_side") {
-        return memPort;
     } else {
         // pass it along to our super class
-        return MemObject::getPort(if_name, idx);
+        return SimObject::getPort(if_name, idx);
     }
 }
 
@@ -236,4 +235,4 @@
 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 6f7301e..a6c9c6d 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
@@ -28,13 +28,12 @@
  * Authors: Jason Lowe-Power
  */
 
-#ifndef __LEARNING_GEM5_SIMPLE_MEMOBJ_SIMPLE_MEMOBJ_HH__
-#define __LEARNING_GEM5_SIMPLE_MEMOBJ_SIMPLE_MEMOBJ_HH__
+#ifndef __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
+#define __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
 
-#include <vector>
-
-#include "mem/mem_object.hh"
+#include "mem/port.hh"
 #include "params/SimpleMemobj.hh"
+#include "sim/sim_object.hh"
 
 /**
  * A very simple memory object. Current implementation doesn't even cache
@@ -42,7 +41,7 @@
  * This memobj is fully blocking (not non-blocking). Only a single request can
  * be outstanding at a time.
  */
-class SimpleMemobj : public MemObject
+class SimpleMemobj : public SimObject
 {
   private:
 
@@ -91,7 +90,7 @@
 
         /**
          * Send a retry to the peer port only if it is needed. This is called
-         * from the SimpleCache whenever it is unblocked.
+         * from the SimpleMemobj whenever it is unblocked.
          */
         void trySendRetry();
 
@@ -115,7 +114,7 @@
          * Receive a timing request from the master port.
          *
          * @param the packet that the requestor sent
-         * @return whether this object can consume to packet. If false, we
+         * @return whether this object can consume the packet. If false, we
          *         will call sendRetry() when we can try to receive this
          *         request again.
          */
@@ -239,16 +238,16 @@
     /**
      * 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;
 };
 
 
-#endif // __LEARNING_GEM5_SIMPLE_MEMOBJ_SIMPLE_MEMOBJ_HH__
+#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
\ No newline at end of file