blob: 3b396d59ba34f8707ba3b9ccddb81431b4bdad1b [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/events/">
<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="/search">Search</a>
</li>
</ul>
</div>
</nav>
<main>
<div class="sidenav-top">
<img src="/assets/img/gem5ColorLong.gif" height="80">
<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="introdution">
</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 " href="/helloobject">Creating a very simple SimObject</a>
<a class="subitem " href="/debugging">Debugging gem5</a>
<a class="subitem active" 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">
<!-- <h1>Event-driven programming</h1> -->
<dl>
<dt>authors</dt>
<dd>Jason Lowe-Power</dd>
</dl>
<h1 id="event-driven-programming">Event-driven programming</h1>
<p>gem5 is an event-driven simulator. In this chapter, we will explore how
to create and schedule events. We will be building from the simple
<code class="highlighter-rouge">HelloObject</code> from hello-simobject-chapter.</p>
<h2 id="creating-a-simple-event-callback">Creating a simple event callback</h2>
<p>In gem5’s event-driven model, each event has a callback function in
which the event is <em>processed</em>. Generally, this is a class that inherits
from :cppEvent. However, gem5 provides a wrapper function for creating
simple events.</p>
<p>In the header file for our <code class="highlighter-rouge">HelloObject</code>, we simply need to declare a
new function that we want to execute every time the event fires
(<code class="highlighter-rouge">processEvent()</code>). This function must take no parameters and return
nothing.</p>
<p>Next, we add an <code class="highlighter-rouge">Event</code> instance. In this case, we will use an
<code class="highlighter-rouge">EventFunctionWrapper</code> which allows us to execute any function.</p>
<p>We also add a <code class="highlighter-rouge">startup()</code> function that will be explained below.</p>
<p>``` {.sourceCode .c++}
class HelloObject : public SimObject
{
private:
void processEvent();</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EventFunctionWrapper event;
</code></pre></div></div>
<p>public:
HelloObject(HelloObjectParams *p);</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>void startup(); }; ```
</code></pre></div></div>
<p>Next, we must construct this event in the constructor of <code class="highlighter-rouge">HelloObject</code>.
The <code class="highlighter-rouge">EventFuntionWrapper</code> takes two parameters, a function to execute
and a name. The name is usually the name of the SimObject that owns the
event. When printing the name, there will be an automatic
“.wrapped_function_event” appended to the end of the name.</p>
<p>The first parameter is simply a function that takes no parameters and
has no return value (<code class="highlighter-rouge">std::function&lt;void(void)&gt;</code>). Usually, this is a
simple lambda function that calls a member function. However, it can be
any function you want. Below, we captute <code class="highlighter-rouge">this</code> in the lambda (<code class="highlighter-rouge">[this]</code>)
so we can call member functions of the instance of the class.</p>
<p>``` {.sourceCode .c++}
HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params), event([this]{processEvent();}, name())
{
DPRINTF(Hello, “Created the hello object\n”);
}</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
We also must define the implementation of the process function. In this
case, we'll simply print something if we are debugging.
``` {.sourceCode .c++}
void
HelloObject::processEvent()
{
DPRINTF(Hello, "Hello world! Processing the event!\n");
}
</code></pre></div></div>
<h2 id="scheduling-events">Scheduling events</h2>
<p>Finally, for the event to be processed, we first have to <em>schedule</em> the
event. For this we use the :cppschedule function. This function
schedules some instance of an <code class="highlighter-rouge">Event</code> for some time in the future
(event-driven simulation does not allow events to execute in the past).</p>
<p>We will initially schedule the event in the <code class="highlighter-rouge">startup()</code> function we
added to the <code class="highlighter-rouge">HelloObject</code> class. The <code class="highlighter-rouge">startup()</code> function is where
SimObjects are allowed to schedule internal events. It does not get
executed until the simulation begins for the first time (i.e. the
<code class="highlighter-rouge">simulate()</code> function is called from a Python config file).</p>
<p>``` {.sourceCode .c++}
void
HelloObject::startup()
{
schedule(event, 100);
}</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Here, we simply schedule the event to execute at tick 100. Normally, you
would use some offset from `curTick()`, but since we know the startup()
function is called when the time is currently 0, we can use an explicit
tick value.
The output when you run gem5 with the "Hello" debug flag is now
gem5 Simulator System. http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.
gem5 compiled Jan 4 2017 11:01:46
gem5 started Jan 4 2017 13:41:38
gem5 executing on chinook, pid 1834
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py
Global frequency set at 1000000000000 ticks per second
0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0. Starting simulation...
100: hello: Hello world! Processing the event!
Exiting @ tick 18446744073709551615 because simulate() limit reached
More event scheduling
---------------------
We can also schedule new events within an event process action. For
instance, we are going to add a latency parameter to the `HelloObject`
and a parameter for how many times to fire the event. In the [next
chapter](parameters-chapter) we will make these parameters accessible
from the Python config files.
To the HelloObject class declaration, add a member variable for the
latency and number of times to fire.
``` {.sourceCode .c++}
class HelloObject : public SimObject
{
private:
void processEvent();
EventFunctionWrapper event;
Tick latency;
int timesLeft;
public:
HelloObject(HelloObjectParams *p);
void startup();
};
</code></pre></div></div>
<p>Then, in the constructor add default values for the <code class="highlighter-rouge">latency</code> and
<code class="highlighter-rouge">timesLeft</code>.</p>
<p>``` {.sourceCode .c++}
HelloObject::HelloObject(HelloObjectParams *params) :
SimObject(params), event([this]{processEvent();}, name()),
latency(100), timesLeft(10)
{
DPRINTF(Hello, “Created the hello object\n”);
}</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Finally, update `startup()` and `processEvent()`.
``` {.sourceCode .c++}
void
HelloObject::startup()
{
schedule(event, latency);
}
void
HelloObject::processEvent()
{
timesLeft--;
DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
if (timesLeft &lt;= 0) {
DPRINTF(Hello, "Done firing!\n");
} else {
schedule(event, curTick() + latency);
}
}
</code></pre></div></div>
<p>Now, when we run gem5, the event should fire 10 times, and the
simulation will end after 1000 ticks. The output should now look 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 Jan 4 2017 13:53:35
gem5 started Jan 4 2017 13:54:11
gem5 executing on chinook, pid 2326
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py
Global frequency set at 1000000000000 ticks per second
0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0. Starting simulation...
100: hello: Hello world! Processing the event! 9 left
200: hello: Hello world! Processing the event! 8 left
300: hello: Hello world! Processing the event! 7 left
400: hello: Hello world! Processing the event! 6 left
500: hello: Hello world! Processing the event! 5 left
600: hello: Hello world! Processing the event! 4 left
700: hello: Hello world! Processing the event! 3 left
800: hello: Hello world! Processing the event! 2 left
900: hello: Hello world! Processing the event! 1 left
1000: hello: Hello world! Processing the event! 0 left
1000: hello: Done firing!
Exiting @ tick 18446744073709551615 because simulate() limit reached
</code></pre></div></div>
<p>You can find the updated header file
here &lt;../_static/scripts/part2/events/hello_object.hh&gt; and the
implementation file
here &lt;../_static/scripts/part2/events/hello_object.cc&gt;.</p>
</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>
<footer class="page-footer">
<div class="container">
<div class="row">
<div class="col-12 col-sm-4">
<p><a href="/about">About</a></p>
<p><a href="/publications">Publications</a></p>
<p><a href="/contributing">Contributing</a></p>
</div><br>
<div class="col-12 col-sm-4">
<p><a href="/gettingstarted">Documentation</a></p>
<p><a href="#">Source</a></p>
</div><br>
<div class="col-12 col-sm-4">
<p><a href="/help">Help</a></p>
<p><a href="/search">Search</a></p>
<p><a href="#">Mailing Lists</a></p>
</div>
</div>
</div>
</footer>
</html>