website: Fix code formatting and links for learning gem5 part 2
Change-Id: Id0c79c4550379227e297b88a03783ec5bfb0b92e
diff --git a/_pages/documentation/learning_gem5/part2/debugging.md b/_pages/documentation/learning_gem5/part2/debugging.md
index 1b186d8..1024399 100644
--- a/_pages/documentation/learning_gem5/part2/debugging.md
+++ b/_pages/documentation/learning_gem5/part2/debugging.md
@@ -11,7 +11,7 @@
Debugging gem5
==============
-In the previous chapters \<hello-simobject-chapter\> we covered how to
+In the [previous chapters](../helloobject) we covered how to
create a very simple SimObject. In this chapter, we will replace the
simple print to `stdout` with gem5's debugging support.
@@ -29,8 +29,8 @@
following output. Note that this generates *a lot* of output to the
console (about 7 MB).
-``` {.sourceCode .sh}
-build/X86/gem5.opt --debug-flags=DRAM configs/learning_gem5/part1/simple.py | head -n 50
+```sh
+ build/X86/gem5.opt --debug-flags=DRAM configs/learning_gem5/part1/simple.py | head -n 50
```
gem5 Simulator System. http://gem5.org
@@ -90,8 +90,8 @@
flags shows details of how each instruction is executed by the simulated
CPU.
-``` {.sourceCode .sh}
-build/X86/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple.py | head -n 50
+```sh
+ build/X86/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple.py | head -n 50
```
gem5 Simulator System. http://gem5.org
@@ -151,8 +151,8 @@
flags. You can see this, and all of the available debug flags, by
running gem5 with the `--debug-help` parameter.
-``` {.sourceCode .sh}
-build/X86/gem5.opt --debug-help
+```sh
+ build/X86/gem5.opt --debug-help
```
Base Flags:
@@ -190,7 +190,7 @@
Adding a new debug flag
-----------------------
-In the previous chapters \<hello-simobject-chapter\>, we used a simple
+In the [previous chapters](../helloobject), we used a simple
`std::cout` to print from our SimObject. While it is possible to use the
normal C/C++ I/O in gem5, it is highly discouraged. So, we are now going
to replace this and use gem5's debugging facilities instead.
@@ -199,7 +199,7 @@
SConscript file. Add the following to the SConscript file in the
directory with your hello object code (src/learning\_gem5/).
-``` {.sourceCode .python}
+```python
DebugFlag('Hello')
```
@@ -215,14 +215,14 @@
In the `hello_object.cc` file, we need to include the header file.
-``` {.sourceCode .c++}
+```cpp
#include "debug/Hello.hh"
```
Now that we have included the necessary header file, let's replace the
`std::cout` call with a debug statement like so.
-``` {.sourceCode .c++}
+```cpp
DPRINTF(Hello, "Created the hello object\n");
```
@@ -235,8 +235,8 @@
Now, if you recompile gem5 and run it with the "Hello" debug flag, you
get the following result.
-``` {.sourceCode .sh}
-build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py
+```sh
+ build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py
```
gem5 Simulator System. http://gem5.org
@@ -254,9 +254,9 @@
Exiting @ tick 18446744073709551615 because simulate() limit reached
You can find the updated SConcript file
-here \<../\_static/scripts/part2/debugging/SConscript\> and the updated
+[here](/_pages/static/scripts/part2/debugging/SConscript) and the updated
hello object code
-here \<../\_static/scripts/part2/debugging/hello\_object.cc\>.
+[here](/_pages/static/scripts/part2/debugging/hello_object.cc).
Debug output
------------
@@ -281,8 +281,8 @@
gem5 provides a number of other functions that are useful in specific
circumstances.
-> These functions are like the previous functions :cppDDUMP,
-> :cppDPRINTF, and :cppDPRINTFR except they do not take a flag as a
+> These functions are like the previous functions `:cppDDUMP`,
+> `:cppDPRINTF`, and `:cppDPRINTFR` except they do not take a flag as a
> parameter. Therefore, these statements will *always* print whenever
> debugging is enabled.
diff --git a/_pages/documentation/learning_gem5/part2/events.md b/_pages/documentation/learning_gem5/part2/events.md
index c288d77..58b418b 100644
--- a/_pages/documentation/learning_gem5/part2/events.md
+++ b/_pages/documentation/learning_gem5/part2/events.md
@@ -33,7 +33,7 @@
We also add a `startup()` function that will be explained below.
-``` {.sourceCode .c++}
+```cpp
class HelloObject : public SimObject
{
private:
@@ -60,7 +60,7 @@
any function you want. Below, we captute `this` in the lambda (`[this]`)
so we can call member functions of the instance of the class.
-``` {.sourceCode .c++}
+```cpp
HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params), event([this]{processEvent();}, name())
{
@@ -71,7 +71,7 @@
We also must define the implementation of the process function. In this
case, we'll simply print something if we are debugging.
-``` {.sourceCode .c++}
+```cpp
void
HelloObject::processEvent()
{
@@ -93,7 +93,7 @@
executed until the simulation begins for the first time (i.e. the
`simulate()` function is called from a Python config file).
-``` {.sourceCode .c++}
+```cpp
void
HelloObject::startup()
{
@@ -135,7 +135,7 @@
To the HelloObject class declaration, add a member variable for the
latency and number of times to fire.
-``` {.sourceCode .c++}
+```cpp
class HelloObject : public SimObject
{
private:
@@ -157,7 +157,7 @@
Then, in the constructor add default values for the `latency` and
`timesLeft`.
-``` {.sourceCode .c++}
+```cpp
HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params), event([this]{processEvent();}, name()),
latency(100), timesLeft(10)
@@ -168,7 +168,7 @@
Finally, update `startup()` and `processEvent()`.
-``` {.sourceCode .c++}
+```cpp
void
HelloObject::startup()
{
@@ -219,6 +219,6 @@
Exiting @ tick 18446744073709551615 because simulate() limit reached
You can find the updated header file
-here \<../\_static/scripts/part2/events/hello\_object.hh\> and the
+[here](/_pages/static/scripts/part2/events/hello_object.hh) and the
implementation file
-here \<../\_static/scripts/part2/events/hello\_object.cc\>.
+[here](/_pages/static/scripts/part2/events/hello_object.cc).
diff --git a/_pages/documentation/learning_gem5/part2/helloobject.md b/_pages/documentation/learning_gem5/part2/helloobject.md
index e181e64..190e77a 100644
--- a/_pages/documentation/learning_gem5/part2/helloobject.md
+++ b/_pages/documentation/learning_gem5/part2/helloobject.md
@@ -29,8 +29,8 @@
SimObject.
In the next few chapters, we will take this simple SimObject and expand
-on it to include [debugging support](debugging-chapter), [dynamic
-events](events-chapter), and [parameters](parameters-chapter).
+on it to include [debugging support](../debugging), [dynamic
+events](../events), and [parameters](../parameters).
> **Using git branches**
>
@@ -55,7 +55,7 @@
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`
+We can create a file, HelloObject.py, in `src/learning_gem5`.
```python
from m5.params import *
@@ -124,7 +124,7 @@
```
[//]: # You can find the complete file
-[//]: # here \<../\_static/scripts/part2/helloobject/hello\_object.hh\>.
+[//]: # [here](/_pages/static/scripts/part2/helloobject/hello_object.hh).
Next, we need to implement *two* functions in the `.cc` file, not just
one. The first function, is the constructor for the `HelloObject`. Here
@@ -132,7 +132,7 @@
"Hello world!"
Normally, you would **never** use `std::cout` in gem5. Instead, you
-should use debug flags. In the [next chapter](debugging-chapter), we
+should use debug flags. In the [next chapter](../debugging), we
will modify this to use debug flags instead. However, for now, we'll
simply use `std::cout` because it is simple.
@@ -164,7 +164,7 @@
```
[//]: # You can find the complete file
-[//]: # here \<../\_static/scripts/part2/helloobject/hello\_object.cc\>.
+[//]: # [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
@@ -211,7 +211,7 @@
```
[//]: # You can find the complete file
-[//]: # here \<../\_static/scripts/part2/helloobject/SConscript\>.
+[//]: # [here](/_pages/static/scripts/part2/helloobject/SConscript).
Step 4: (Re)-build gem5
-----------------------
@@ -236,7 +236,7 @@
Walking through creating a *very* simple configuration script, first,
import m5 and all of the objects you have compiled.
-```
+```python
import m5
from m5.objects import *
```
@@ -244,7 +244,7 @@
Next, you have to instantiate the `Root` object, as required by all gem5
instances.
-```
+```python
root = Root(full_system = False)
```
@@ -255,14 +255,14 @@
child of the root object. Only SimObjects that are children of the
`Root` object are instantiated in `C++`.
-```
+```python
root.hello = HelloObject()
```
Finally, you need to call `instantiate` on the `m5` module and actually
run the simulation!
-```
+```python
m5.instantiate()
print("Beginning simulation!")
@@ -272,7 +272,7 @@
```
[//]: # You can find the complete file
-[//]: # here \<../\_static/scripts/part2/helloobject/run\_hello.py\>.
+[//]: # [here](/_pages/static/scripts/part2/helloobject/run_hello.py).
The output should look something like the following
diff --git a/_pages/documentation/learning_gem5/part2/memoryobject.md b/_pages/documentation/learning_gem5/part2/memoryobject.md
index 42b3a25..f688a40 100644
--- a/_pages/documentation/learning_gem5/part2/memoryobject.md
+++ b/_pages/documentation/learning_gem5/part2/memoryobject.md
@@ -12,7 +12,7 @@
========================================
In this chapter, we will create a simple memory object that sits between
-the CPU and the memory bus. In the next chapter \<simplecache-chapter\>
+the CPU and the memory bus. In the [next chapter](../simplecache)
we will take this simple memory object and add some logic to it to make
it a very simple blocking uniprocessor cache.
@@ -180,7 +180,7 @@
file. We will call this simple memory object `SimpleMemobj` and create
the SimObject Python file in `src/learning_gem5/simple_memobj`.
-``` {.sourceCode .python}
+```python
from m5.params import *
from m5.proxy import *
from MemObject import MemObject
@@ -209,18 +209,18 @@
`getMasterPort` and `getSlavePort` functions.
You can download the SimObject file
-here \<../\_static/scripts/part2/memoryobject/SimpleMemobj.py\>
+[here](/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py).
Of course, you also need to create a SConscript file in the new
directory as well that declares the SimObject Python file. You can
download the SConscript file
-here \<../\_static/scripts/part2/memoryobject/SConscript\>
+[here](/_pages/static/scripts/part2/memoryobject/SConscript).
### Define the SimpleMemobj class
Now, we create a header file for `SimpleMemobj`.
-``` {.sourceCode .c++}
+```cpp
class SimpleMemobj : public MemObject
{
private:
@@ -244,7 +244,7 @@
inherit from the `SlavePort` class. The following is the required code
to override all of the pure virtual functions in the `SlavePort` class.
-``` {.sourceCode .c++}
+```cpp
class CPUSidePort : public SlavePort
{
private:
@@ -276,7 +276,7 @@
port which will forward request from the CPU-side to the rest of the
memory system.
-``` {.sourceCode .c++}
+```cpp
class MemSidePort : public MasterPort
{
private:
@@ -305,7 +305,7 @@
functions are used by gem5 during the initialization phase to connect
memory objects together via ports.
-``` {.sourceCode .c++}
+```cpp
class SimpleMemobj : public MemObject
{
private:
@@ -331,7 +331,7 @@
```
You can download the header file for the `SimpleMemobj`
-here \<../\_static/scripts/part2/memoryobject/simple\_memobj.hh\>
+[here](/_pages/static/scripts/part2/memoryobject/simple_memobj.hh).
### Implementing basic MemObject functions
@@ -341,7 +341,7 @@
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.
-``` {.sourceCode .c++}
+```cpp
SimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
MemObject(params),
instPort(params->name + ".inst_port", this),
@@ -365,7 +365,7 @@
slave port to any other named port since the parent class has no ports
defined.
-``` {.sourceCode .c++}
+```cpp
BaseMasterPort&
SimpleMemobj::getMasterPort(const std::string& if_name, PortID idx)
{
@@ -382,7 +382,7 @@
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.
-``` {.sourceCode .c++}
+```cpp
BaseSlavePort&
SimpleMemobj::getSlavePort(const std::string& if_name, PortID idx)
{
@@ -405,7 +405,7 @@
Starting with two simple functions, `getAddrRanges` and `recvFunctional`
simply call into the `SimpleMemobj`.
-``` {.sourceCode .c++}
+```cpp
AddrRangeList
SimpleMemobj::CPUSidePort::getAddrRanges() const
{
@@ -424,7 +424,7 @@
memory side. We can use `DPRINTF` calls here to track what is happening
for debug purposes as well.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::handleFunctional(PacketPtr pkt)
{
@@ -442,7 +442,7 @@
Similarly for the `MemSidePort`, we need to implement `recvRangeChange`
and forward the request through the `SimpleMemobj` to the slave port.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::MemSidePort::recvRangeChange()
{
@@ -450,7 +450,7 @@
}
```
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::sendRangeChange()
{
@@ -475,7 +475,7 @@
becomes free. Then, if the `SimpleMemobj` is blocked on a request, we
set that we need to send a retry sometime in the future.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleMemobj::CPUSidePort::recvTimingReq(PacketPtr pkt)
{
@@ -499,7 +499,7 @@
`true` from `handleRequest` since we were successful in consuming the
request.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleMemobj::handleRequest(PacketPtr pkt)
{
@@ -527,7 +527,7 @@
defensive code to make sure there is not a bug and we never try to
overwrite the `blockedPacket` variable incorrectly.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::MemSidePort::sendPacket(PacketPtr pkt)
{
@@ -542,7 +542,7 @@
function, we try to resend the packet by calling the `sendPacket`
function we wrote above.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::MemSidePort::recvReqRetry()
{
@@ -561,7 +561,7 @@
`MemSidePort` gets a response, we forward the response through the
`SimpleMemobj` to the appropriate `CPUSidePort`.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleMemobj::MemSidePort::recvTimingResp(PacketPtr pkt)
{
@@ -582,7 +582,7 @@
Finally, since the object is now unblocked, we may need to notify the
CPU side ports that they can now retry their requests that failed.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleMemobj::handleResponse(PacketPtr pkt)
{
@@ -612,7 +612,7 @@
master port. If this call fails and the peer port is currently blocked,
then we store the packet to be sent later.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt)
{
@@ -628,7 +628,7 @@
`recvRespRetry`. This function is exactly the same as the `recvReqRetry`
above and simply tries to resend the packet, which may be blocked again.
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::CPUSidePort::recvRespRetry()
{
@@ -649,7 +649,7 @@
needed, this function calls `sendRetryReq`, which in turn calls
`recvReqRetry` on the peer master port (the CPU in this case).
-``` {.sourceCode .c++}
+```cpp
void
SimpleMemobj::CPUSidePort::trySendRetry()
{
@@ -662,7 +662,7 @@
```
You can download the implementation for the `SimpleMemobj`
-here \<../\_static/scripts/part2/memoryobject/simple\_memobj.cc\>
+[here](/_pages/static/scripts/part2/memoryobject/simple_memobj.cc).
The following figure, memobj-api-figure, shows the relationships between
the `CPUSidePort`, `MemSidePort`, and `SimpleMemobj`. This figure shows
@@ -672,25 +672,17 @@
colors highlight one API path through the object (e.g., receiving a
request or updating the memory ranges).
-![](../_static/figures/memobj_api.png)
-
-> width
-> : 100 %
->
-> alt
-> : Interaction between SimpleMemobj and its ports
->
-> Interaction between SimpleMemobj and its ports
+![Interaction between SimpleMemobj and its ports](/_pages/static/figures/memobj_api.png)
For this simple memory object, packets are just forwarded from the
CPU-side to the memory side. However, by modifying `handleRequest` and
`handleResponse`, we can create rich featureful objects, like a cache in
-the next chapter \<simplecache-chapter\>.
+the [next chapter](../simplecache).
### Create a config file
This is all of the code needed to implement a simple memory object! In
-the next chapter \<simplecache-chapter\>, we will take this framework
+the [next chapter](../simplecache), we will take this framework
and add some caching logic to make this memory object into a simple
cache. However, before that, let's look at the config file to add the
SimpleMemobj to your system.
@@ -700,7 +692,7 @@
to the memory bus, we are going to instantiate a `SimpleMemobj` and
place it between the CPU and the memory bus.
-``` {.sourceCode .python}
+```python
import m5
from m5.objects import *
@@ -747,7 +739,7 @@
```
You can download this config script
-here \<../\_static/scripts/part2/memoryobject/simple\_memobj.py\>
+[here](/_pages/static/scripts/part2/memoryobject/simple_memobj.py).
Now, when you run this config file you get the following output.
diff --git a/_pages/documentation/learning_gem5/part2/parameters.md b/_pages/documentation/learning_gem5/part2/parameters.md
index f47b538..7ce0910 100644
--- a/_pages/documentation/learning_gem5/part2/parameters.md
+++ b/_pages/documentation/learning_gem5/part2/parameters.md
@@ -26,11 +26,11 @@
(`src/learning_gem5/HelloObject.py`). Parameters are set by adding new
statements to the Python class that include a `Param` type.
-For instance, the following code as a parameter `time_to_wait` which is
+For instance, the following code has a parameter `time_to_wait` which is
a "Latency" parameter and `number_of_fires` which is an integer
parameter.
-``` {.sourceCode .python}
+```python
class HelloObject(SimObject):
type = 'HelloObject'
cxx_header = "learning_gem5/hello_object.hh"
@@ -67,7 +67,7 @@
to copy their values to your C++ class in its constructor. The following
code shows the changes to the `HelloObject` constructor.
-``` {.sourceCode .c++}
+```cpp
HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params),
event(*this),
@@ -93,7 +93,7 @@
To the HelloObject class declaration, add a member variable for the
name.
-``` {.sourceCode .c++}
+```cpp
class HelloObject : public SimObject
{
private:
@@ -131,7 +131,7 @@
value. Therefore, we need to update the Python config file
(`run_hello.py`) to specify this value.
-``` {.sourceCode .python}
+```python
root.hello = HelloObject(time_to_wait = '2us')
```
@@ -139,7 +139,7 @@
exactly the same because the C++ objects are not created until
`m5.instantiate()` is called.
-``` {.sourceCode .python}
+```python
root.hello = HelloObject()
root.hello.time_to_wait = '2us'
```
@@ -177,7 +177,7 @@
First, declare the SimObject in the SConscript file:
-``` {.sourceCode .python}
+```python
Import('*')
SimObject('HelloObject.py')
@@ -188,7 +188,7 @@
```
The new SConscript file can be downloaded
-here \<../\_static/scripts/part2/parameters/SConscript\>
+[here](/_pages/static/scripts/part2/parameters/SConscript).
Next, you need to declare the new SimObject in a SimObject Python file.
Since the `GoodbyeObject` is highly related to the `HelloObject`, we
@@ -200,7 +200,7 @@
Second is the `write_bandwidth` which specifies the speed to fill the
buffer. Once the buffer is full, the simulation will exit.
-``` {.sourceCode .python}
+```python
class GoodbyeObject(SimObject):
type = 'GoodbyeObject'
cxx_header = "learning_gem5/goodbye_object.hh"
@@ -212,11 +212,11 @@
```
The updated `HelloObject.py` file can be downloaded
-here \<../\_static/scripts/part2/parameters/HelloObject.py\>
+[here](/_pages/static/scripts/part2/parameters/HelloObject.py).
Now, we need to implement the `GoodbyeObject`.
-``` {.sourceCode .c++}
+```cpp
#ifndef __LEARNING_GEM5_GOODBYE_OBJECT_HH__
#define __LEARNING_GEM5_GOODBYE_OBJECT_HH__
@@ -269,7 +269,7 @@
#endif // __LEARNING_GEM5_GOODBYE_OBJECT_HH__
```
-``` {.sourceCode .c++}
+```cpp
#include "learning_gem5/goodbye_object.hh"
#include "debug/Hello.hh"
@@ -340,9 +340,9 @@
```
The header file can be downloaded
-here \<../\_static/scripts/part2/parameters/goodbye\_object.hh\> and the
+[here](/_pages/static/scripts/part2/parameters/goodbye_object.hh) and the
implementation can be downloaded
-here \<../\_static/scripts/part2/parameters/goodbye\_object.cc\>
+[here](/_pages/static/scripts/part2/parameters/goodbye_object.cc).
The interface to this `GoodbyeObject` is simple a function `sayGoodbye`
which takes a string as a parameter. When this function is called, the
@@ -371,7 +371,7 @@
as the `TypeName` of the `Param`. You can have a default, or not, just
like a normal parameter.
-``` {.sourceCode .python}
+```python
class HelloObject(SimObject):
type = 'HelloObject'
cxx_header = "learning_gem5/hello_object.hh"
@@ -384,12 +384,12 @@
```
The updated `HelloObject.py` file can be downloaded
-here \<../\_static/scripts/part2/parameters/HelloObject.py\>
+[here](/_pages/static/scripts/part2/parameters/HelloObject.py).
Second, we will add a reference to a `GoodbyeObject` to the
`HelloObject` class.
-``` {.sourceCode .c++}
+```cpp
class HelloObject : public SimObject
{
private:
@@ -423,7 +423,7 @@
Python SimObject. We should *panic* when this happens since it is not a
case this object has been coded to accept.
-``` {.sourceCode .c++}
+```cpp
#include "learning_gem5/part2/hello_object.hh"
#include "base/misc.hh"
@@ -445,7 +445,7 @@
Once we have processed the number of event specified by the parameter,
we should call the `sayGoodbye` function in the `GoodbyeObject`.
-``` {.sourceCode .c++}
+```cpp
void
HelloObject::processEvent()
{
@@ -462,9 +462,9 @@
```
You can find the updated header file
-here \<../\_static/scripts/part2/parameters/hello\_object.hh\> and the
+[here](/_pages/static/scripts/part2/parameters/hello_object.hh) and the
implementation file
-here \<../\_static/scripts/part2/parameters/hello\_object.cc\>.
+[here](/_pages/static/scripts/part2/parameters/hello_object.cc).
### Updating the config script
@@ -473,7 +473,7 @@
and the goodbye objects. For instance, one possible script is the
following.
-``` {.sourceCode .python}
+```python
import m5
from m5.objects import *
@@ -490,7 +490,7 @@
```
You can download this script
-here \<../\_static/scripts/part2/parameters/hello\_goodbye.py\>
+[here](/_pages/static/scripts/part2/parameters/hello_goodbye.py).
Running this script generates the following output.
diff --git a/_pages/documentation/learning_gem5/part2/simplecache.md b/_pages/documentation/learning_gem5/part2/simplecache.md
index d33052c..5016fc9 100644
--- a/_pages/documentation/learning_gem5/part2/simplecache.md
+++ b/_pages/documentation/learning_gem5/part2/simplecache.md
@@ -12,19 +12,19 @@
==============================
In this chapter, we will take the framework for a memory object we
-created in the last chapter \<memoryobject-chapter\> and add caching
+created in the [last chapter](../memoryobject) and add caching
logic to it.
SimpleCache SimObject
---------------------
After creating the SConscript file, that you can download
-here \<../\_static/scripts/part2/simplecache/SConscript\>, we can create
+[here](/_pages/static/scripts/part2/simplecache/SConscript), we can create
the SimObject Python file. We will call this simple memory object
`SimpleCache` and create the SimObject Python file in
`src/learning_gem5/simple_cache`.
-``` {.sourceCode .python}
+```python
from m5.params import *
from m5.proxy import *
from MemObject import MemObject
@@ -44,7 +44,7 @@
```
There are a couple of differences between this SimObject file and the
-one from the previous chapter \<memoryobject-chapter\>. First, we have a
+one from the [previous chapter](../memoryobject). First, we have a
couple of extra parameters. Namely, a latency for cache accesses and the
size of the cache. parameters-chapter goes into more detail about these
kinds of SimObject parameters.
@@ -75,7 +75,7 @@
Implementing the SimpleCache
----------------------------
-Most of the code for the `` `SimpleCache `` is the same as the
+Most of the code for the `SimpleCache` is the same as the
`SimpleMemobj`. There are a couple of changes in the constructor and the
key memory object functions.
@@ -83,7 +83,7 @@
constructor and initialize the extra member functions based on the
SimObject parameters.
-``` {.sourceCode .c++}
+```cpp
SimpleCache::SimpleCache(SimpleCacheParams *params) :
MemObject(params),
latency(params->latency),
@@ -117,7 +117,7 @@
`getSlavePort`, we now need to return the port based on the id
requested.
-``` {.sourceCode .c++}
+```cpp
BaseSlavePort&
SimpleCache::getSlavePort(const std::string& if_name, PortID idx)
{
@@ -152,7 +152,7 @@
the future. The `clockEdge` function returns the *tick* that the *nth*
cycle in the future occurs on.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleCache::handleRequest(PacketPtr pkt, int port_id)
{
@@ -182,7 +182,7 @@
dynamically created object. The event code will automatically delete the
object after the `process` function has executed.
-``` {.sourceCode .c++}
+```cpp
class AccessEvent : public Event
{
private:
@@ -200,7 +200,7 @@
Now, we need to implement the event handler, `accessTiming`.
-``` {.sourceCode .c++}
+```cpp
void
SimpleCache::accessTiming(PacketPtr pkt)
{
@@ -234,7 +234,7 @@
retries to the CPU side ports if the `SimpleCache` can now receive
requests and the ports need to be sent retries.
-``` {.sourceCode .c++}
+```cpp
void SimpleCache::sendResponse(PacketPtr pkt)
{
int port = waitingPortId;
@@ -276,7 +276,7 @@
receives a response. Then, we send the new packet across the memory side
port.
-``` {.sourceCode .c++}
+```cpp
void
SimpleCache::accessTiming(PacketPtr pkt)
{
@@ -329,7 +329,7 @@
cache on a write. Then, we need to delete the new packet that we made in
the miss handling logic.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleCache::handleResponse(PacketPtr pkt)
{
@@ -362,7 +362,7 @@
that maps from addresses to data. Thus, we will add the following member
to the `SimpleCache`.
-``` {.sourceCode .c++}
+```cpp
std::unordered_map<Addr, uint8_t*> cacheStore;
```
@@ -386,7 +386,7 @@
the same offset calculation as the `writeDataToBlock` function, but
writes the packet with the data from the pointer in the first parameter.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleCache::accessFunctional(PacketPtr pkt)
{
@@ -428,7 +428,7 @@
the cache block since we made sure to make a new packet in the cache
miss logic if the packet was smaller than a cache block.
-``` {.sourceCode .c++}
+```cpp
void
SimpleCache::insert(PacketPtr pkt)
{
@@ -463,14 +463,14 @@
The last step in our implementation is to create a new Python config
script that uses our cache. We can use the outline from the
-last chapter \<memoryobject-chapter\> as a starting point. The only
+[last chapter](../memoryobject) as a starting point. The only
difference is we may want to set the parameters of this cache (e.g., set
the size of the cache to `1kB`) and instead of using the named ports
(`data_port` and `inst_port`), we just use the `cpu_side` port twice.
Since `cpu_side` is a `VectorPort`, it will automatically create
multiple port connections.
-``` {.sourceCode .python}
+```python
import m5
from m5.objects import *
@@ -489,7 +489,7 @@
```
The Python config file can be downloaded
-here \<../\_static/scripts/part2/simplecache/simple\_cache.py\>
+[here](/_pages/static/scripts/part2/simplecache/simple_cache.py).
Running this script should produce the expected output from the hello
binary.
@@ -549,7 +549,7 @@
special statistic called a `Formula` for the `hitRatio` that is a
combination of other statistics (the number of hits and misses).
-``` {.sourceCode .c++}
+```cpp
class SimpleCache : public MemObject
{
private:
@@ -577,7 +577,7 @@
Finally, for the formula, we simply need to write the formula down in
code.
-``` {.sourceCode .c++}
+```cpp
void
SimpleCache::regStats()
{
@@ -611,7 +611,7 @@
and miss respectively. Additionally, on a miss, we save the current time
so we can measure the latency.
-``` {.sourceCode .c++}
+```cpp
void
SimpleCache::accessTiming(PacketPtr pkt)
{
@@ -631,7 +631,7 @@
point to the histogram. This histogram automatically resizes the buckets
to fit the data it receives.
-``` {.sourceCode .c++}
+```cpp
bool
SimpleCache::handleResponse(PacketPtr pkt)
{
@@ -642,10 +642,10 @@
```
The complete code for the `SimpleCache` header file can be downloaded
-here \<../\_static/scripts/part2/simplecache/simple\_cache.hh\>, and the
+[here](/_pages/static/scripts/part2/simplecache/simple_cache.hh), and the
complete code for the implementation of the `SimpleCache` can be
downloaded
-here \<../\_static/scripts/part2/simplecache/simple\_cache.cc\>.
+[here](/_pages/static/scripts/part2/simplecache/simple_cache.cc).
Now, if we run the above config file, we can check on the statistics in
the `stats.txt` file. For the 1 KB case, we get the following