blob: 4950d81d0bf5790eccd09387c40f3cf5540e7397 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gem5</title>
<!-- SITE FAVICON -->
<link rel="shortcut icon" type="image/gif" href="/assets/img/gem5ColorVert.gif"/>
<link rel="canonical" href="http://localhost:4000/helloobject/">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700,800,600' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'>
<!-- FAVICON -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<!-- BOOTSTRAP -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<!-- CUSTOM CSS -->
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="/">
<img src="/assets/img/gem5ColorLong.gif" alt="gem5" height=45px>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav ml-auto">
<li class="nav-item ">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item dropdown ">
<a class="nav-link dropdown-toggle" href="/about" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
About
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="/about">About</a>
<a class="dropdown-item" href="/publications">Publications</a>
<a class="dropdown-item" href="/governance">Governance</a>
</div>
</li>
<li class="nav-item dropdown active">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Documentation
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<!-- Pull navigation from _data/documentation.yml -->
<a class="dropdown-item" href="/introduction">Introduction</a>
<a class="dropdown-item" href="/building">Getting Started</a>
<a class="dropdown-item" href="/environment">Modifying/Extending</a>
<a class="dropdown-item" href="/MSIintro">Modeling Cache Coherence with Ruby</a>
</div>
</li>
<li class="nav-item ">
<a class="nav-link" href="/contributing">Contributing</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="/blog">Blog</a>
</li>
<li class="nav-item ">
<a class="nav-link" href="/search">Search</a>
</li>
</ul>
</div>
</nav>
<main>
<div class="sidenav-top">
<a href="/"><img src="/assets/img/gem5ColorLong.gif" height="80"></a>
<div class="search">
<form action="/search" method="get">
<!-- <label for="search-box"><i class="fa fa-search"></i></label> -->
<input type="text" name="query">
<button type="submit" name="submit"><i class="fa fa-search"></i></button>
</form>
</div>
</div>
<div class="sidenav">
<!-- Pull navigation from _data/documentation.yml -->
<a class="item" href="/introduction" role="button" aria-expanded="false" aria-controls="collapseExample">
Introduction
</a>
<div class="collapse " id="introduction">
</div>
<a class="item" data-toggle="collapse" href="#pt1" role="button" aria-expanded="false" aria-controls="collapseExample">
Getting Started
</a>
<div class="collapse " id="pt1">
<a class="subitem " href="/building">Building gem5</a>
<a class="subitem " href="/simple_config">Creating a simple configuration script</a>
<a class="subitem " href="/cache_config">Adding cache to configuration script</a>
<a class="subitem " href="/gem5_stats">Understanding gem5 statistics and output</a>
<a class="subitem " href="/example_configs">Using the default configuration scripts</a>
</div>
<a class="item" data-toggle="collapse" href="#pt2" role="button" aria-expanded="false" aria-controls="collapseExample">
Modifying/Extending
</a>
<div class="collapse show" id="pt2">
<a class="subitem " href="/environment">Setting up your development environment</a>
<a class="subitem active" href="/helloobject">Creating a very simple SimObject</a>
<a class="subitem " href="/debugging">Debugging gem5</a>
<a class="subitem " href="/events">Event-driven programming</a>
<a class="subitem " href="/parameters">Adding parameters to SimObjects and more events</a>
<a class="subitem " href="/memoryobject">Creating SimObjects in the memory system</a>
<a class="subitem " href="/simplecache">Creating a simple cache object</a>
</div>
<a class="item" data-toggle="collapse" href="#pt3" role="button" aria-expanded="false" aria-controls="collapseExample">
Modeling Cache Coherence with Ruby
</a>
<div class="collapse " id="pt3">
<a class="subitem " href="/MSIintro">Introduction to Ruby</a>
<a class="subitem " href="/cache-intro">MSI example cache protocol</a>
<a class="subitem " href="/cache-declarations">Declaring a state machine</a>
<a class="subitem " href="/cache-in-ports">In port code blocks</a>
<a class="subitem " href="/cache-actions">Action code blocks</a>
<a class="subitem " href="/cache-transitions">Transition code blocks</a>
<a class="subitem " href="/directory">MSI Directory implementation</a>
<a class="subitem " href="/MSIbuilding">Compiling a SLICC protocol</a>
<a class="subitem " href="/configuration">Configuring a simple Ruby system</a>
<a class="subitem " href="/running">Running the simple Ruby system</a>
<a class="subitem " href="/MSIdebugging">Debugging SLICC Protocols</a>
<a class="subitem " href="/simple-MI_example">Configuring for a standard protocol</a>
</div>
</div>
<div class="container" id="doc-container">
<div class="edit"><a href="https://github.com/gem5/new-website/tree/master/_pages/documentation/part2/helloobject.md">Edit this page</a></div>
<dl>
<dt>authors</dt>
<dd>Jason Lowe-Power</dd>
</dl>
<h1 id="creating-a-very-simple-simobject">Creating a <em>very</em> simple SimObject</h1>
<p>Almost all objects in gem5 inherit from the base SimObject type.
SimObjects export the main interfaces to all objects in gem5. SimObjects
are wrapped <code class="highlighter-rouge">C++</code> objects that are accessible from the <code class="highlighter-rouge">Python</code>
configuration scripts.</p>
<p>SimObjects can have many parameters, which are set via the <code class="highlighter-rouge">Python</code>
configuration files. In addition to simple parameters like integers and
floating point numbers, they can also have other SimObjects as
parameters. This allows you to create complex system hierarchies, like
real machines.</p>
<p>In this chapter, we will walk through creating a simple “HelloWorld”
SimObject. The goal is to introduce you to how SimObjects are created
and the required boilerplate code for all SimObjects. We will also
create a simple <code class="highlighter-rouge">Python</code> configuration script which instantiates our
SimObject.</p>
<p>In the next few chapters, we will take this simple SimObject and expand
on it to include <a href="debugging-chapter">debugging support</a>, <a href="events-chapter">dynamic
events</a>, and <a href="parameters-chapter">parameters</a>.</p>
<blockquote>
<p><strong>Using git branches</strong></p>
<p>It is common to use a new git branch for each new feature you add to
gem5.</p>
<p>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_.</p>
<p><code class="highlighter-rouge">{.sourceCode .sh}
git checkout -b hello-simobject
</code></p>
</blockquote>
<h2 id="step-1-create-a-python-class-for-your-new-simobject">Step 1: Create a Python class for your new SimObject</h2>
<p>Each SimObject has a Python class which is associated with it. This
Python class describes the parameters of your SimObject that can be
controlled from the Python configuration files. For our simple
SimObject, we are just going to start out with no parameters. Thus, we
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.</p>
<p>We can create a file, HelloObject.py, in <code class="highlighter-rouge">src/learning_gem5</code></p>
<p>``` {.sourceCode .python}
from m5.params import *
from m5.SimObject import SimObject</p>
<p>class HelloObject(SimObject):
type = ‘HelloObject’
cxx_header = “learning_gem5/hello_object.hh”</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
You can find the complete file
here \&lt;../\_static/scripts/part2/helloobject/HelloObject.py\&gt;.
It is not required that the `type` be the same as the name of the class,
but it is convention. The `type` is the C++ class that you are wrapping
with this Python SimObject. Only in special circumstances should the
`type` and the class name be different.
The `cxx_header` is the file that contains the declaration of the class
used as the `type` parameter. Again, the convention is to use the name
of the SimObject with all lowercase and underscores, but this is only
convention. You can specify any header file here.
Step 2: Implement your SimObject in C++
---------------------------------------
Next, we need to create `hello_object.hh` and `hello_object.cc` which
will implement the hello object.
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
file and the directory its in so there are no circular includes.
The only thing we need to do in the file is to declare our class. Since
`HelloObject` is a SimObject, it must inherit from the C++ SimObject
class. Most of the time, your SimObject's parent will be a subclass of
SimObject, not SimObject itself.
The SimObject class specifies many virtual functions. However, none of
these functions are pure virtual, so in the simplest case, there is no
need to implement any functions except for the constructor.
The constructor for all SimObjects assumes it will take a parameter
object. This parameter object is automatically created by the build
system and is based on the `Python` class for the SimObject, like the
one we created above. The name for this parameter type is generated
automatically from the name of your object. For our "HelloObject" the
parameter type's name is "HelloObject\**Params*\*".
The code required for our simple header file is listed below.
``` {.sourceCode .c++}
#ifndef __LEARNING_GEM5_HELLO_OBJECT_HH__
#define __LEARNING_GEM5_HELLO_OBJECT_HH__
#include "params/HelloObject.hh"
#include "sim/sim_object.hh"
class HelloObject : public SimObject
{
public:
HelloObject(HelloObjectParams *p);
};
#endif // __LEARNING_GEM5_HELLO_OBJECT_HH__
</code></pre></div></div>
<p>You can find the complete file
here &lt;../_static/scripts/part2/helloobject/hello_object.hh&gt;.</p>
<p>Next, we need to implement <em>two</em> functions in the <code class="highlighter-rouge">.cc</code> file, not just
one. The first function, is the constructor for the <code class="highlighter-rouge">HelloObject</code>. Here
we simply pass the parameter object to the SimObject parent and print
“Hello world!”</p>
<p>Normally, you would <strong>never</strong> use <code class="highlighter-rouge">std::cout</code> in gem5. Instead, you
should use debug flags. In the <a href="debugging-chapter">next chapter</a>, we
will modify this to use debug flags instead. However, for now, we’ll
simply use <code class="highlighter-rouge">std::cout</code> because it is simple.</p>
<p>``` {.sourceCode .c++}
#include “learning_gem5/hello_object.hh”</p>
<p>#include <iostream></iostream></p>
<p>HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params)
{
std::cout « “Hello World! From a SimObject!” « std::endl;
}</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
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).
``` {.sourceCode .c++}
HelloObject*
HelloObjectParams::create()
{
return new HelloObject(this);
}
</code></pre></div></div>
<p>You can find the complete file
here &lt;../_static/scripts/part2/helloobject/hello_object.cc&gt;.</p>
<p>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.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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.
</code></pre></div></div>
<p>This <code class="highlighter-rouge">undefined reference to `HelloObjectParams::create()'</code> means
you need to implement the create function for your SimObject.</p>
<h2 id="step-3-register-the-simobject-and-c-file">Step 3: Register the SimObject and C++ file</h2>
<p>In order for the <code class="highlighter-rouge">C++</code> file to be compiled and the <code class="highlighter-rouge">Python</code> file to be
parsed we need to tell the build system about these files. gem5 uses
SCons as the build system, so you simply have to create a SConscript
file in the directory with the code for the SimObject. If there is
already a SConscript file for that directory, simply add the following
declarations to that file.</p>
<p>This file is simply a normal <code class="highlighter-rouge">Python</code> file, so you can write any
<code class="highlighter-rouge">Python</code> code you want in this file. Some of the scripting can become
quite complicated. gem5 leverages this to automatically create code for
SimObjects and to compile the domain-specific languages like SLICC and
the ISA language.</p>
<p>In the SConscript file, there are a number of functions automatically
defined after you import them. See the section on that…</p>
<p>To get your new SimObject to compile, you simply need to create a new
file with the name “SConscript” in the <code class="highlighter-rouge">src/learning_gem5</code> directory. In
this file, you have to declare the SimObject and the <code class="highlighter-rouge">.cc</code> file. Below
is the required code.</p>
<p>``` {.sourceCode .python}
Import(‘*’)</p>
<p>SimObject(‘HelloObject.py’)
Source(‘hello_object.cc’)</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
You can find the complete file
here \&lt;../\_static/scripts/part2/helloobject/SConscript\&gt;.
Step 4: (Re)-build gem5
-----------------------
To compile and link your new files you simply need to recompile gem5.
The below example assumes you are using the x86 ISA, but nothing in our
object requires an ISA so, this will work with any of gem5's ISAs.
``` {.sourceCode .sh}
scons build/X86/gem5.opt
</code></pre></div></div>
<h2 id="step-5-create-the-config-scripts-to-use-your-new-simobject">Step 5: Create the config scripts to use your new SimObject</h2>
<p>Now that you have implemented a SimObject, and it has been compiled into
gem5, you need to create or modify a <code class="highlighter-rouge">Python</code> config file 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 <code class="highlighter-rouge">Root</code>
object. All gem5 instances require a <code class="highlighter-rouge">Root</code> object.</p>
<p>Walking through creating a <em>very</em> simple configuration script, first,
import m5 and all of the objects you have compiled.</p>
<p>``` {.sourceCode .python}
import m5
from m5.objects import *</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Next, you have to instantiate the `Root` object, as required by all gem5
instances.
``` {.sourceCode .python}
root = Root(full_system = False)
</code></pre></div></div>
<p>Now, you can instantiate the <code class="highlighter-rouge">HelloObject</code> you created. All you need to
do is call the <code class="highlighter-rouge">Python</code> “constructor”. Later, we will look at how to
specify parameters via the <code class="highlighter-rouge">Python</code> constructor. In addition to creating
an instantiation of your object, you need to make sure that it is a
child of the root object. Only SimObjects that are children of the
<code class="highlighter-rouge">Root</code> object are instantiated in <code class="highlighter-rouge">C++</code>.</p>
<p>``` {.sourceCode .python}
root.hello = HelloObject()</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Finally, you need to call `instantiate` on the `m5` module and actually
run the simulation!
``` {.sourceCode .python}
m5.instantiate()
print("Beginning simulation!")
exit_event = m5.simulate()
print('Exiting @ tick {} because {}'
.format(m5.curTick(), exit_event.getCause()))
</code></pre></div></div>
<p>You can find the complete file
here &lt;../_static/scripts/part2/helloobject/run_hello.py&gt;.</p>
<p>The output should look something like the following</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem5 Simulator System. http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.
gem5 compiled May 4 2016 11:37:41
gem5 started May 4 2016 11:44:28
gem5 executing on mustardseed.cs.wisc.edu, pid 22480
command line: build/X86/gem5.opt configs/learning_gem5/run_hello.py
Global frequency set at 1000000000000 ticks per second
Hello World! From a SimObject!
Beginning simulation!
info: Entering event queue @ 0. Starting simulation...
Exiting @ tick 18446744073709551615 because simulate() limit reached
</code></pre></div></div>
<p>Congrats! You have written your first SimObject. In the next chapters,
we will extend this SimObject and explore what you can do with
SimObjects.</p>
<br>
<!-- RETRIVE PREVIOUS PAGE LINK -->
<!-- RETRIEVE NEXT PAGE LINK -->
<div class="navbuttons">
<a href="/environment"><button type="button" class="btn btn-outline-primary">PREVIOUS</button></a>
<a href="/debugging"><button type="button" class="btn btn-outline-primary">NEXT</button></a>
</div>
</div>
</main>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script>
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 20) {
document.getElementById("myBtn").style.display = "block";
} else {
document.getElementById("myBtn").style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
</body>
</html>