| <!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/parameters/"> |
| <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 " 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 active" 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/parameters.md">Edit this page</a></div> |
| <dl> |
| <dt>authors</dt> |
| <dd>Jason Lowe-Power</dd> |
| </dl> |
| |
| <h1 id="adding-parameters-to-simobjects-and-more-events">Adding parameters to SimObjects and more events</h1> |
| |
| <p>One of the most powerful parts of gem5’s Python interface is the ability |
| to pass parameters from Python to the C++ objects in gem5. In this |
| chapter, we will explore some of the kinds of parameters for SimObjects |
| and how to use them building off of the simple <code class="highlighter-rouge">HelloObject</code> from the |
| previous chapters <events-chapter>.</p> |
| |
| <h2 id="simple-parameters">Simple parameters</h2> |
| |
| <p>First, we will add parameters for the latency and number of times to |
| fire the event in the <code class="highlighter-rouge">HelloObject</code>. To add a parameter, modify the |
| <code class="highlighter-rouge">HelloObject</code> class in the SimObject Python file |
| (<code class="highlighter-rouge">src/learning_gem5/HelloObject.py</code>). Parameters are set by adding new |
| statements to the Python class that include a <code class="highlighter-rouge">Param</code> type.</p> |
| |
| <p>For instance, the following code as a parameter <code class="highlighter-rouge">time_to_wait</code> which is |
| a “Latency” parameter and <code class="highlighter-rouge">number_of_fires</code> which is an integer |
| parameter.</p> |
| |
| <p>``` {.sourceCode .python} |
| class HelloObject(SimObject): |
| type = ‘HelloObject’ |
| cxx_header = “learning_gem5/hello_object.hh”</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>time_to_wait = Param.Latency("Time before firing the event") |
| number_of_fires = Param.Int(1, "Number of times to fire the event before " |
| "goodbye") ``` |
| </code></pre></div></div> |
| |
| <p><code class="highlighter-rouge">Param.<TypeName></code> declares a parameter of type <code class="highlighter-rouge">TypeName</code>. Common types |
| are <code class="highlighter-rouge">Int</code> for integers, <code class="highlighter-rouge">Float</code> for floats, etc. These types act like |
| regular Python classes.</p> |
| |
| <p>Each parameter declaration takes one or two parameters. When given two |
| parameters (like <code class="highlighter-rouge">number_of_fires</code> above), the first parameter is the |
| <em>default value</em> for the parameter. In this case, if you instantiate a |
| <code class="highlighter-rouge">HelloObject</code> in your Python config file without specifying any value |
| for number_of_fires, it will take the default value of 1.</p> |
| |
| <p>The second parameter to the parameter declaration is a short description |
| of the parameter. This must be a Python string. If you only specify a |
| single parameter to the parameter declaration, it is the description (as |
| for <code class="highlighter-rouge">time_to_wait</code>).</p> |
| |
| <p>gem5 also supports many complex parameter types that are not just |
| builtin types. For instance, <code class="highlighter-rouge">time_to_wait</code> is a <code class="highlighter-rouge">Latency</code>. <code class="highlighter-rouge">Latency</code> |
| takes a value as a time value as a string and converts it into simulator |
| <strong>ticks</strong>. For instance, with a default tick rate of 1 picosecond |
| (10\^12 ticks per second or 1 THz), <code class="highlighter-rouge">"1ns"</code> is automatically converted |
| to 1000. There are other convenience parameters like <code class="highlighter-rouge">Percent</code>, |
| <code class="highlighter-rouge">Cycles</code>, <code class="highlighter-rouge">MemorySize</code> and many more.</p> |
| |
| <p>Once you have declared these parameters in the SimObject file, you need |
| to copy their values to your C++ class in its constructor. The following |
| code shows the changes to the <code class="highlighter-rouge">HelloObject</code> constructor.</p> |
| |
| <p>``` {.sourceCode .c++} |
| HelloObject::HelloObject(HelloObjectParams <em>params) : |
| SimObject(params), |
| event(</em>this), |
| myName(params->name), |
| latency(params->time_to_wait), |
| timesLeft(params->number_of_fires) |
| { |
| DPRINTF(Hello, “Created the hello object with the name %s\n”, myName); |
| }</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> |
| Here, we use the parameter's values for the default values of latency |
| and timesLeft. Additionally, we store the `name` from the parameter |
| object to use it later in the member variable `myName`. Each `params` |
| instantiation has a name which comes from the Python config file when it |
| is instantiated. |
| |
| However, assigning the name here is just an example of using the params |
| object. For all SimObjects, there is a `name()` function that always |
| returns the name. Thus, there is never a need to store the name like |
| above. |
| |
| To the HelloObject class declaration, add a member variable for the |
| name. |
| |
| ``` {.sourceCode .c++} |
| class HelloObject : public SimObject |
| { |
| private: |
| void processEvent(); |
| |
| EventWrapper<HelloObject, &HelloObject::processEvent> event; |
| |
| std::string myName; |
| |
| Tick latency; |
| |
| int timesLeft; |
| |
| public: |
| HelloObject(HelloObjectParams *p); |
| |
| void startup(); |
| }; |
| </code></pre></div></div> |
| |
| <p>When we run gem5 with the above, we get the following error:</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 14:46:36 |
| gem5 started Jan 4 2017 14:46:52 |
| gem5 executing on chinook, pid 3422 |
| command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py |
| |
| Global frequency set at 1000000000000 ticks per second |
| fatal: hello.time_to_wait without default or user set value |
| </code></pre></div></div> |
| |
| <p>This is because the <code class="highlighter-rouge">time_to_wait</code> parameter does not have a default |
| value. Therefore, we need to update the Python config file |
| (<code class="highlighter-rouge">run_hello.py</code>) to specify this value.</p> |
| |
| <p>``` {.sourceCode .python} |
| root.hello = HelloObject(time_to_wait = ‘2us’)</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> |
| Or, we can specify `time_to_wait` as a member variable. Either option is |
| exactly the same because the C++ objects are not created until |
| `m5.instantiate()` is called. |
| |
| ``` {.sourceCode .python} |
| root.hello = HelloObject() |
| root.hello.time_to_wait = '2us' |
| </code></pre></div></div> |
| |
| <p>The output of this simple script is the following when running the the |
| <code class="highlighter-rouge">Hello</code> debug flag.</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 14:46:36 |
| gem5 started Jan 4 2017 14:50:08 |
| gem5 executing on chinook, pid 3455 |
| 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 with the name hello |
| Beginning simulation! |
| info: Entering event queue @ 0. Starting simulation... |
| 2000000: hello: Hello world! Processing the event! 0 left |
| 2000000: hello: Done firing! |
| Exiting @ tick 18446744073709551615 because simulate() limit reached |
| </code></pre></div></div> |
| |
| <p>You can also modify the config script to fire the event multiple times.</p> |
| |
| <h2 id="other-simobjects-as-parameters">Other SimObjects as parameters</h2> |
| |
| <p>You can also specify other SimObjects as parameters. To demonstrate |
| this, we are going to create a new SimObject, <code class="highlighter-rouge">GoodbyeObject</code>. This |
| object is going to have a simple function that says “Goodbye” to another |
| SimObject. To make it a little more interesting, the <code class="highlighter-rouge">GoodbyeObject</code> is |
| going to have a buffer to write the message, and a limited bandwidth to |
| write the message.</p> |
| |
| <p>First, declare the SimObject in the SConscript file:</p> |
| |
| <p>``` {.sourceCode .python} |
| Import(‘*’)</p> |
| |
| <p>SimObject(‘HelloObject.py’) |
| Source(‘hello_object.cc’) |
| Source(‘goodbye_object.cc’)</p> |
| |
| <p>DebugFlag(‘Hello’)</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> |
| The new SConscript file can be downloaded |
| here \<../\_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 |
| will use the same file. You can add the following code to |
| `HelloObject.py`. |
| |
| This object has two parameters, both with default values. The first |
| parameter is the size of a buffer and is a `MemorySize` parameter. |
| Second is the `write_bandwidth` which specifies the speed to fill the |
| buffer. Once the buffer is full, the simulation will exit. |
| |
| ``` {.sourceCode .python} |
| class GoodbyeObject(SimObject): |
| type = 'GoodbyeObject' |
| cxx_header = "learning_gem5/goodbye_object.hh" |
| |
| buffer_size = Param.MemorySize('1kB', |
| "Size of buffer to fill with goodbye") |
| write_bandwidth = Param.MemoryBandwidth('100MB/s', "Bandwidth to fill " |
| "the buffer") |
| </code></pre></div></div> |
| |
| <p>The updated <code class="highlighter-rouge">HelloObject.py</code> file can be downloaded |
| here <../_static/scripts/part2/parameters/HelloObject.py></p> |
| |
| <p>Now, we need to implement the <code class="highlighter-rouge">GoodbyeObject</code>.</p> |
| |
| <p>``` {.sourceCode .c++} |
| #ifndef <strong>LEARNING_GEM5_GOODBYE_OBJECT_HH</strong> |
| #define <strong>LEARNING_GEM5_GOODBYE_OBJECT_HH</strong></p> |
| |
| <p>#include <string></string></p> |
| |
| <p>#include “params/GoodbyeObject.hh” |
| #include “sim/sim_object.hh”</p> |
| |
| <p>class GoodbyeObject : public SimObject |
| { |
| private: |
| void processEvent();</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/** |
| * Fills the buffer for one iteration. If the buffer isn't full, this |
| * function will enqueue another event to continue filling. |
| */ |
| void fillBuffer(); |
| |
| EventWrapper<GoodbyeObject, &GoodbyeObject::processEvent> event; |
| |
| /// The bytes processed per tick |
| float bandwidth; |
| |
| /// The size of the buffer we are going to fill |
| int bufferSize; |
| |
| /// The buffer we are putting our message in |
| char *buffer; |
| |
| /// The message to put into the buffer. |
| std::string message; |
| |
| /// The amount of the buffer we've used so far. |
| int bufferUsed; |
| </code></pre></div></div> |
| |
| <p>public: |
| GoodbyeObject(GoodbyeObjectParams *p); |
| ~GoodbyeObject();</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/** |
| * Called by an outside object. Starts off the events to fill the buffer |
| * with a goodbye message. |
| * |
| * @param name the name of the object we are saying goodbye to. |
| */ |
| void sayGoodbye(std::string name); }; |
| </code></pre></div></div> |
| |
| <p>#endif // <strong>LEARNING_GEM5_GOODBYE_OBJECT_HH</strong></p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> |
| ``` {.sourceCode .c++} |
| #include "learning_gem5/goodbye_object.hh" |
| |
| #include "debug/Hello.hh" |
| #include "sim/sim_exit.hh" |
| |
| GoodbyeObject::GoodbyeObject(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"); |
| } |
| |
| GoodbyeObject::~GoodbyeObject() |
| { |
| delete[] buffer; |
| } |
| |
| void |
| GoodbyeObject::processEvent() |
| { |
| DPRINTF(Hello, "Processing the event!\n"); |
| fillBuffer(); |
| } |
| |
| void |
| GoodbyeObject::sayGoodbye(std::string other_name) |
| { |
| DPRINTF(Hello, "Saying goodbye to %s\n", other_name); |
| |
| message = "Goodbye " + other_name + "!! "; |
| |
| fillBuffer(); |
| } |
| |
| void |
| GoodbyeObject::fillBuffer() |
| { |
| // There better be a message |
| assert(message.length() > 0); |
| |
| // Copy from the message to the buffer per byte. |
| int bytes_copied = 0; |
| for (auto it = message.begin(); |
| it < message.end() && bufferUsed < bufferSize - 1; |
| it++, bufferUsed++, bytes_copied++) { |
| // Copy the character into the buffer |
| buffer[bufferUsed] = *it; |
| } |
| |
| 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", |
| bandwidth * bytes_copied); |
| schedule(event, curTick() + bandwidth * bytes_copied); |
| } else { |
| DPRINTF(Hello, "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); |
| } |
| </code></pre></div></div> |
| |
| <p>The header file can be downloaded |
| here <../_static/scripts/part2/parameters/goodbye_object.hh> and the |
| implementation can be downloaded |
| here <../_static/scripts/part2/parameters/goodbye_object.cc></p> |
| |
| <p>The interface to this <code class="highlighter-rouge">GoodbyeObject</code> is simple a function <code class="highlighter-rouge">sayGoodbye</code> |
| which takes a string as a parameter. When this function is called, the |
| simulator builds the message and saves it in a member variable. Then, we |
| begin filling the buffer.</p> |
| |
| <p>To model the limited bandwidth, each time we write the message to the |
| buffer, we pause for the latency it takes to write the message. We use a |
| simple event to model this pause.</p> |
| |
| <p>Since we used a <code class="highlighter-rouge">MemoryBandwidth</code> parameter in the SimObject |
| declaration, the <code class="highlighter-rouge">bandwidth</code> variable is automatically converted into |
| ticks per byte, so calculating the latency is simply the bandwidth times |
| the bytes we want to write the buffer.</p> |
| |
| <p>Finally, when the buffer is full, we call the function <code class="highlighter-rouge">exitSimLoop</code>, |
| which will exit the simulation. This function takes three parameters, |
| the first is the message to return to the Python config script |
| (<code class="highlighter-rouge">exit_event.getCause()</code>), the second is the exit code, and the third is |
| when to exit.</p> |
| |
| <h3 id="adding-the-goodbyeobject-as-a-parameter-to-the-helloobject">Adding the GoodbyeObject as a parameter to the HelloObject</h3> |
| |
| <p>First, we will also add a <code class="highlighter-rouge">GoodbyeObject</code> as a parameter to the |
| <code class="highlighter-rouge">HelloObject</code>. To do this, you simply specify the SimObject class name |
| as the <code class="highlighter-rouge">TypeName</code> of the <code class="highlighter-rouge">Param</code>. You can have a default, or not, just |
| like a normal parameter.</p> |
| |
| <p>``` {.sourceCode .python} |
| class HelloObject(SimObject): |
| type = ‘HelloObject’ |
| cxx_header = “learning_gem5/hello_object.hh”</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>time_to_wait = Param.Latency("Time before firing the event") |
| number_of_fires = Param.Int(1, "Number of times to fire the event before " |
| "goodbye") |
| |
| goodbye_object = Param.GoodbyeObject("A goodbye object") ``` |
| </code></pre></div></div> |
| |
| <p>The updated <code class="highlighter-rouge">HelloObject.py</code> file can be downloaded |
| here <../_static/scripts/part2/parameters/HelloObject.py></p> |
| |
| <p>Second, we will add a reference to a <code class="highlighter-rouge">GoodbyeObject</code> to the |
| <code class="highlighter-rouge">HelloObject</code> class.</p> |
| |
| <p>``` {.sourceCode .c++} |
| class HelloObject : public SimObject |
| { |
| private: |
| void processEvent();</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EventWrapper<HelloObject, &HelloObject::processEvent> event; |
| |
| /// Pointer to the corresponding GoodbyeObject. Set via Python |
| const GoodbyeObject* goodbye; |
| |
| /// The name of this object in the Python config file |
| const std::string myName; |
| |
| /// Latency between calling the event (in ticks) |
| const Tick latency; |
| |
| /// Number of times left to fire the event before goodbye |
| int timesLeft; |
| </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>Then, we need to update the constructor and the process event function |
| of the <code class="highlighter-rouge">HelloObject</code>. We also add a check in the constructor to make |
| sure the <code class="highlighter-rouge">goodbye</code> pointer is valid. It is possible to pass a null |
| pointer as a SimObject via the parameters by using the <code class="highlighter-rouge">NULL</code> special |
| Python SimObject. We should <em>panic</em> when this happens since it is not a |
| case this object has been coded to accept.</p> |
| |
| <p>``` {.sourceCode .c++} |
| #include “learning_gem5/part2/hello_object.hh”</p> |
| |
| <p>#include “base/misc.hh” |
| #include “debug/Hello.hh”</p> |
| |
| <p>HelloObject::HelloObject(HelloObjectParams <em>params) : |
| SimObject(params), |
| event(</em>this), |
| goodbye(params->goodbye_object), |
| myName(params->name), |
| latency(params->time_to_wait), |
| timesLeft(params->number_of_fires) |
| { |
| DPRINTF(Hello, “Created the hello object with the name %s\n”, myName); |
| panic_if(!goodbye, “HelloObject must have a non-null GoodbyeObject”); |
| }</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> |
| Once we have processed the number of event specified by the parameter, |
| we should call the `sayGoodbye` function in the `GoodbyeObject`. |
| |
| ``` {.sourceCode .c++} |
| void |
| HelloObject::processEvent() |
| { |
| timesLeft--; |
| DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft); |
| |
| if (timesLeft <= 0) { |
| DPRINTF(Hello, "Done firing!\n"); |
| goodbye.sayGoodbye(myName); |
| } else { |
| schedule(event, curTick() + latency); |
| } |
| } |
| </code></pre></div></div> |
| |
| <p>You can find the updated header file |
| here <../_static/scripts/part2/parameters/hello_object.hh> and the |
| implementation file |
| here <../_static/scripts/part2/parameters/hello_object.cc>.</p> |
| |
| <h3 id="updating-the-config-script">Updating the config script</h3> |
| |
| <p>Lastly, we need to add the <code class="highlighter-rouge">GoodbyeObject</code> to the config script. Create |
| a new config script, <code class="highlighter-rouge">hello_goodbye.py</code> and instantiate both the hello |
| and the goodbye objects. For instance, one possible script is the |
| following.</p> |
| |
| <p>``` {.sourceCode .python} |
| import m5 |
| from m5.objects import *</p> |
| |
| <p>root = Root(full_system = False)</p> |
| |
| <p>root.hello = HelloObject(time_to_wait = ‘2us’, number_of_fires = 5) |
| root.hello.goodbye_object = GoodbyeObject(buffer_size=’100B’)</p> |
| |
| <p>m5.instantiate()</p> |
| |
| <p>print “Beginning simulation!” |
| exit_event = m5.simulate() |
| print ‘Exiting @ tick %i because %s’ % (m5.curTick(), exit_event.getCause()) |
| ```</p> |
| |
| <p>You can download this script |
| here <../_static/scripts/part2/parameters/hello_goodbye.py></p> |
| |
| <p>Running this script generates the following output.</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 15:17:14 |
| gem5 started Jan 4 2017 15:18:41 |
| gem5 executing on chinook, pid 3838 |
| command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/hello_goodbye.py |
| |
| Global frequency set at 1000000000000 ticks per second |
| 0: hello.goodbye_object: Created the goodbye object |
| 0: hello: Created the hello object |
| Beginning simulation! |
| info: Entering event queue @ 0. Starting simulation... |
| 2000000: hello: Hello world! Processing the event! 4 left |
| 4000000: hello: Hello world! Processing the event! 3 left |
| 6000000: hello: Hello world! Processing the event! 2 left |
| 8000000: hello: Hello world! Processing the event! 1 left |
| 10000000: hello: Hello world! Processing the event! 0 left |
| 10000000: hello: Done firing! |
| 10000000: hello.goodbye_object: Saying goodbye to hello |
| 10000000: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10152592: hello.goodbye_object: Processing the event! |
| 10152592: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10305184: hello.goodbye_object: Processing the event! |
| 10305184: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10457776: hello.goodbye_object: Processing the event! |
| 10457776: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10610368: hello.goodbye_object: Processing the event! |
| 10610368: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10762960: hello.goodbye_object: Processing the event! |
| 10762960: hello.goodbye_object: Scheduling another fillBuffer in 152592 ticks |
| 10915552: hello.goodbye_object: Processing the event! |
| 10915552: hello.goodbye_object: Goodbye done copying! |
| Exiting @ tick 10944163 because Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goodbye hello!! Goo |
| </code></pre></div></div> |
| |
| <p>You can modify the parameters to these two SimObjects and see how the |
| overall execution time (Exiting @ tick <strong>10944163</strong>) changes. To run |
| these tests, you may want to remove the debug flag so there is less |
| output to the terminal.</p> |
| |
| <p>In the next chapters, we will create a more complex and more useful |
| SimObject, culminating with a simple blocking uniprocessor cache |
| implementation.</p> |
| |
| <br> |
| |
| <!-- RETRIVE PREVIOUS PAGE LINK --> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <!-- RETRIEVE NEXT PAGE LINK --> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div class="navbuttons"> |
| |
| <a href="/events"><button type="button" class="btn btn-outline-primary">PREVIOUS</button></a> |
| |
| |
| |
| <a href="/memoryobject"><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> |