| <!DOCTYPE html> |
| <html> |
| <head> |
| <!-- Global site tag (gtag.js) - Google Analytics --> |
| <script async src="https://www.googletagmanager.com/gtag/js?id='UA-133422980-2"></script> |
| <script> |
| window.dataLayer = window.dataLayer || []; |
| function gtag(){dataLayer.push(arguments);} |
| gtag('js', new Date()); |
| |
| gtag('config', ''UA-133422980-2'); |
| </script> |
| |
| <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/simple-MI_example/"> |
| <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 " 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 " 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 show" 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 active" 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/part3/simple-MI_example.md">Edit this page</a></div> |
| <dl> |
| <dt>authors</dt> |
| <dd>Jason Lowe-Power</dd> |
| </dl> |
| |
| <h1 id="configuring-for-a-standard-protocol">Configuring for a standard protocol</h1> |
| |
| <p>You can easily adapt the simple example configurations from this part to |
| the other SLICC protocols in gem5. In this chapter, we will briefly look |
| at an example with <code class="highlighter-rouge">MI_example</code>, though this can be easily extended to |
| other protocols.</p> |
| |
| <p>However, these simple configuration files will only work in syscall |
| emulation mode. Full system mode adds some complications such as DMA |
| controllers. These scripts can be extended to full system.</p> |
| |
| <p>For <code class="highlighter-rouge">MI_example</code>, we can use exactly the same runscript as before |
| (<code class="highlighter-rouge">simple_ruby.py</code>), we just need to implement a different |
| <code class="highlighter-rouge">MyCacheSystem</code> (and import that file in <code class="highlighter-rouge">simple_ruby.py</code>). Below, is |
| the classes needed for <code class="highlighter-rouge">MI_example</code>. There are only a couple of changes |
| from <code class="highlighter-rouge">MSI</code>, mostly due to different naming schemes. You can download the |
| file |
| here <../_static/scripts/part3/configs/ruby_caches_MI_example.py></p> |
| |
| <p>``` {.sourceCode .python} |
| class MyCacheSystem(RubySystem):</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def __init__(self): |
| if buildEnv['PROTOCOL'] != 'MI_example': |
| fatal("This system assumes MI_example!") |
| |
| super(MyCacheSystem, self).__init__() |
| |
| def setup(self, system, cpus, mem_ctrls): |
| """Set up the Ruby cache subsystem. Note: This can't be done in the |
| constructor because many of these items require a pointer to the |
| ruby system (self). This causes infinite recursion in initialize() |
| if we do this in the __init__. |
| """ |
| # Ruby's global network. |
| self.network = MyNetwork(self) |
| |
| # MI example uses 5 virtual networks |
| self.number_of_virtual_networks = 5 |
| self.network.number_of_virtual_networks = 5 |
| |
| # There is a single global list of all of the controllers to make it |
| # easier to connect everything to the global network. This can be |
| # customized depending on the topology/network requirements. |
| # Create one controller for each L1 cache (and the cache mem obj.) |
| # Create a single directory controller (Really the memory cntrl) |
| self.controllers = \ |
| [L1Cache(system, self, cpu) for cpu in cpus] + \ |
| [DirController(self, system.mem_ranges, mem_ctrls)] |
| |
| # Create one sequencer per CPU. In many systems this is more |
| # complicated since you have to create sequencers for DMA controllers |
| # and other controllers, too. |
| self.sequencers = [RubySequencer(version = i, |
| # I/D cache is combined and grab from ctrl |
| icache = self.controllers[i].cacheMemory, |
| dcache = self.controllers[i].cacheMemory, |
| clk_domain = self.controllers[i].clk_domain, |
| ) for i in range(len(cpus))] |
| |
| for i,c in enumerate(self.controllers[0:len(cpus)]): |
| c.sequencer = self.sequencers[i] |
| |
| self.num_of_sequencers = len(self.sequencers) |
| |
| # Create the network and connect the controllers. |
| # NOTE: This is quite different if using Garnet! |
| self.network.connectControllers(self.controllers) |
| self.network.setup_buffers() |
| |
| # Set up a proxy port for the system_port. Used for load binaries and |
| # other functional-only things. |
| self.sys_port_proxy = RubyPortProxy() |
| system.system_port = self.sys_port_proxy.slave |
| |
| # Connect the cpu's cache, interrupt, and TLB ports to Ruby |
| for i,cpu in enumerate(cpus): |
| cpu.icache_port = self.sequencers[i].slave |
| cpu.dcache_port = self.sequencers[i].slave |
| isa = buildEnv['TARGET_ISA'] |
| if isa == 'x86': |
| cpu.interrupts[0].pio = self.sequencers[i].master |
| cpu.interrupts[0].int_master = self.sequencers[i].slave |
| cpu.interrupts[0].int_slave = self.sequencers[i].master |
| if isa == 'x86' or isa == 'arm': |
| cpu.itb.walker.port = self.sequencers[i].slave |
| cpu.dtb.walker.port = self.sequencers[i].slave |
| </code></pre></div></div> |
| |
| <p>class L1Cache(L1Cache_Controller):</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>_version = 0 |
| @classmethod |
| def versionCount(cls): |
| cls._version += 1 # Use count for this particular type |
| return cls._version - 1 |
| |
| def __init__(self, system, ruby_system, cpu): |
| """CPUs are needed to grab the clock domain and system is needed for |
| the cache block size. |
| """ |
| super(L1Cache, self).__init__() |
| |
| self.version = self.versionCount() |
| # This is the cache memory object that stores the cache data and tags |
| self.cacheMemory = RubyCache(size = '16kB', |
| assoc = 8, |
| start_index_bit = self.getBlockSizeBits(system)) |
| self.clk_domain = cpu.clk_domain |
| self.send_evictions = self.sendEvicts(cpu) |
| self.ruby_system = ruby_system |
| self.connectQueues(ruby_system) |
| |
| def getBlockSizeBits(self, system): |
| bits = int(math.log(system.cache_line_size, 2)) |
| if 2**bits != system.cache_line_size.value: |
| panic("Cache line size not a power of 2!") |
| return bits |
| |
| def sendEvicts(self, cpu): |
| """True if the CPU model or ISA requires sending evictions from caches |
| to the CPU. Two scenarios warrant forwarding evictions to the CPU: |
| 1. The O3 model must keep the LSQ coherent with the caches |
| 2. The x86 mwait instruction is built on top of coherence |
| 3. The local exclusive monitor in ARM systems |
| """ |
| if type(cpu) is DerivO3CPU or \ |
| buildEnv['TARGET_ISA'] in ('x86', 'arm'): |
| return True |
| return False |
| |
| def connectQueues(self, ruby_system): |
| """Connect all of the queues for this controller. |
| """ |
| self.mandatoryQueue = MessageBuffer() |
| self.requestFromCache = MessageBuffer(ordered = True) |
| self.requestFromCache.master = ruby_system.network.slave |
| self.responseFromCache = MessageBuffer(ordered = True) |
| self.responseFromCache.master = ruby_system.network.slave |
| self.forwardToCache = MessageBuffer(ordered = True) |
| self.forwardToCache.slave = ruby_system.network.master |
| self.responseToCache = MessageBuffer(ordered = True) |
| self.responseToCache.slave = ruby_system.network.master |
| </code></pre></div></div> |
| |
| <p>class DirController(Directory_Controller):</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>_version = 0 |
| @classmethod |
| def versionCount(cls): |
| cls._version += 1 # Use count for this particular type |
| return cls._version - 1 |
| |
| def __init__(self, ruby_system, ranges, mem_ctrls): |
| """ranges are the memory ranges assigned to this controller. |
| """ |
| if len(mem_ctrls) > 1: |
| panic("This cache system can only be connected to one mem ctrl") |
| super(DirController, self).__init__() |
| self.version = self.versionCount() |
| self.addr_ranges = ranges |
| self.ruby_system = ruby_system |
| self.directory = RubyDirectoryMemory() |
| # Connect this directory to the memory side. |
| self.memory = mem_ctrls[0].port |
| self.connectQueues(ruby_system) |
| |
| def connectQueues(self, ruby_system): |
| self.requestToDir = MessageBuffer(ordered = True) |
| self.requestToDir.slave = ruby_system.network.master |
| self.dmaRequestToDir = MessageBuffer(ordered = True) |
| self.dmaRequestToDir.slave = ruby_system.network.master |
| |
| self.responseFromDir = MessageBuffer() |
| self.responseFromDir.master = ruby_system.network.slave |
| self.dmaResponseFromDir = MessageBuffer(ordered = True) |
| self.dmaResponseFromDir.master = ruby_system.network.slave |
| self.forwardFromDir = MessageBuffer() |
| self.forwardFromDir.master = ruby_system.network.slave |
| self.responseFromMemory = MessageBuffer() |
| </code></pre></div></div> |
| |
| <p>class MyNetwork(SimpleNetwork): |
| “"”A simple point-to-point network. This doesn’t not use garnet. |
| “””</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def __init__(self, ruby_system): |
| super(MyNetwork, self).__init__() |
| self.netifs = [] |
| self.ruby_system = ruby_system |
| |
| def connectControllers(self, controllers): |
| """Connect all of the controllers to routers and connect the routers |
| together in a point-to-point network. |
| """ |
| # Create one router/switch per controller in the system |
| self.routers = [Switch(router_id = i) for i in range(len(controllers))] |
| |
| # Make a link from each controller to the router. The link goes |
| # externally to the network. |
| self.ext_links = [SimpleExtLink(link_id=i, ext_node=c, |
| int_node=self.routers[i]) |
| for i, c in enumerate(controllers)] |
| |
| # Make an "internal" link (internal to the network) between every pair |
| # of routers. |
| link_count = 0 |
| self.int_links = [] |
| for ri in self.routers: |
| for rj in self.routers: |
| if ri == rj: continue # Don't connect a router to itself! |
| link_count += 1 |
| self.int_links.append(SimpleIntLink(link_id = link_count, |
| src_node = ri, |
| dst_node = rj)) ``` |
| </code></pre></div></div> |
| |
| <br> |
| |
| <!-- RETRIVE PREVIOUS PAGE LINK --> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <!-- RETRIEVE NEXT PAGE LINK --> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div class="navbuttons"> |
| |
| <a href="/MSIdebugging"><button type="button" class="btn btn-outline-primary">PREVIOUS</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 src="https://unpkg.com/commentbox.io/dist/commentBox.min.js"></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; |
| } |
| |
| import commentBox from 'commentbox.io'; |
| // or |
| const commentBox = require('commentbox.io'); |
| // or if using the CDN, it will be available as a global "commentBox" variable. |
| |
| commentBox('my-project-id'); |
| |
| </script> |
| |
| </body> |
| |
| |
| </html> |