Jekyll2024-02-09T11:39:03-05:00https://amutheezan.com/feed.xmlHomeAmutheezanamutheezan@psu.eduIntroduction to Murphi3.1 - V2021-06-08T00:00:00-04:002021-06-08T00:00:00-04:00https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-5<p>The model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states.
Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system
Murphi3.1.</p>
<p>This is the continuation of <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-4/">previous post</a>
which provides a small extension to toy example in Murphi3.1.</p>
<p>In this post, I will go through full extension toy example using murphi3.1, based on what I have discussed in earlier
posts.</p>
<h3 id="fully-extended-toy-example---simple-file-management-system">FULLY EXTENDED TOY-EXAMPLE - Simple File Management System</h3>
<p>This example is adapted from <a href="https://en.wikipedia.org/wiki/MESI_protocol">MESI Protocol</a>.</p>
<p>We further extend the File Management System which we explain in the previous post, to support either exclusive access
to read and write when only one person read or write, and avoid unwanted bus transactions. We define this model by a
simple Finite state machine with following states,</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">Unused</code> - No one uses the files</li>
<li><code class="language-plaintext highlighter-rouge">Shared</code> - File is read by more than persons</li>
<li><code class="language-plaintext highlighter-rouge">Exclusive</code> - File is read by only one person</li>
<li><code class="language-plaintext highlighter-rouge">Modified</code> - File is modified by one of the person</li>
</ol>
<p>In this model, we split the <code class="language-plaintext highlighter-rouge">Shared</code> states to two states <code class="language-plaintext highlighter-rouge">Shared</code> and <code class="language-plaintext highlighter-rouge">Exclusive</code>.</p>
<p>Next we define, how the communication are happen,
The file (or data) in main-memory and it will loaded into virtual/private memory of individual users when they call
a <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command. The communication happen through a bus which connects all the users and main-memory
and when ever some user send either <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command, it will communicate to the main memory and
obtain the copy and use it.</p>
<p>Detailed State Diagram.</p>
<p><img src="https://amutheezan.com/images/4states.png" alt="image" /></p>
<p>Now we look into how we simply convert this state diagram into murphi verification code.</p>
<p>Consider there is only one file and 3 people have access to the file. Those three people can either <code class="language-plaintext highlighter-rouge">Read</code>
or <code class="language-plaintext highlighter-rouge">Write</code> the file.</p>
<p>First we define the constants, types and variables required to define the simple file system,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span>
<span class="n">person_count</span><span class="o">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">file_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">type</span>
<span class="n">Proc</span> <span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">person_count</span><span class="p">);</span>
<span class="n">Value</span><span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">file_count</span><span class="p">);</span>
<span class="n">ProcState</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">state</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">FS_UNUSED</span><span class="p">,</span>
<span class="n">FS_SHARED</span><span class="p">,</span>
<span class="n">FS_MODIFIED</span><span class="p">,</span>
<span class="n">FS_EXCLUSIVE</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">MessageType</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">Invalidate</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">Message</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">mtype</span><span class="o">:</span> <span class="n">MessageType</span><span class="p">;</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">var</span>
<span class="n">proc_state</span><span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">Proc</span><span class="p">]</span> <span class="n">of</span> <span class="n">ProcState</span><span class="p">;</span>
<span class="n">last_write</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">send_msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span>
<span class="n">transaction_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
</code></pre></div></div>
<p>In above description, we add additional variable <code class="language-plaintext highlighter-rouge">transaction_flag</code> which used to define whether one process is
already reading the file or not. Depending on the <code class="language-plaintext highlighter-rouge">transaction_flag</code>, when a person call <code class="language-plaintext highlighter-rouge">Read</code> command the
person will go to <code class="language-plaintext highlighter-rouge">Exclusive</code> (if <code class="language-plaintext highlighter-rouge">transaction_flag := false</code>) or <code class="language-plaintext highlighter-rouge">Shared</code> (
if <code class="language-plaintext highlighter-rouge">transaction_flag := true</code>).</p>
<p>Next we define the method <code class="language-plaintext highlighter-rouge">SendMessage</code> to send messages through bus to other person, when ever someone starts
writing. This function will invalidate and move to the state <code class="language-plaintext highlighter-rouge">Unused</code>, when ever some one write. Also this function
will make the exclusive access to shared access when more than one person actually starts read the file.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">SendMessage</span><span class="p">(</span><span class="n">msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span><span class="p">);</span>
<span class="n">begin</span>
<span class="k">switch</span> <span class="n">msg</span><span class="p">.</span><span class="n">mtype</span>
<span class="k">case</span> <span class="n">ReadShared</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_EXCLUSIVE</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_SHARED</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">case</span> <span class="n">ReadModified</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="k">case</span> <span class="n">Invalidate</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">endswitch</span><span class="p">;</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">msg</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<p>Thereafter we have two define the rulesets for <code class="language-plaintext highlighter-rouge">Read</code> and <code class="language-plaintext highlighter-rouge">Write</code> commands as shown below.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ruleset</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">alias</span> <span class="n">p</span><span class="o">:</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">do</span>
<span class="n">ruleset</span> <span class="n">v</span><span class="o">:</span> <span class="n">Value</span> <span class="k">do</span>
<span class="n">rule</span> <span class="s">"Write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_SHARED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_MODIFIED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span><span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">Invalidate</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read Exclusive data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_SHARED</span> <span class="o">|</span> <span class="o">~</span><span class="n">transaction_flag</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_EXCLUSIVE</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read Shared data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_SHARED</span> <span class="o">|</span> <span class="n">transaction_flag</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_SHARED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<p>After that, we define the start states as follows,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="k">for</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">send_msg</span><span class="p">;</span>
<span class="n">endstartstate</span><span class="p">;</span>
</code></pre></div></div>
<p>At the beginning all the person systems in <code class="language-plaintext highlighter-rouge">Unused</code> state for the particular file, file is in <code class="language-plaintext highlighter-rouge">Undefined</code> and at
the start since no one is actually using the file the <code class="language-plaintext highlighter-rouge">transaction_flag</code> is set to <code class="language-plaintext highlighter-rouge">false</code>.</p>
<p>As a last step we add one additional thing that is <strong>Invariant</strong>.
Invariant describes how valid system should be,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Invariant</span> <span class="s">"only one person in Modified state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"only one person in Exclusive state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_EXCLUSIVE</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_EXCLUSIVE</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"values in valid state match last write"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_SHARED</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_EXCLUSIVE</span>
<span class="o">-></span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span> <span class="o">=</span> <span class="n">last_write</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"value is undefined while invalid"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span>
<span class="o">-></span>
<span class="n">IsUndefined</span><span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span><span class="p">)</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>Finally, we need to work on how to actually compile this and verify the system.</p>
<ol>
<li>First combine the entire codes and make a murphi file.</li>
<li>Then generate <code class="language-plaintext highlighter-rouge">.C</code> file using the murphi file.</li>
<li>Then produce the executable file using <code class="language-plaintext highlighter-rouge">make</code> command and run.</li>
</ol>
<p>For more complex models look at my previous post which is based on Futurebus+ protocol.</p>
<ol>
<li><a href="https://amutheezan.com/computer%20architecture/futurebus+/">Futurebus+ Protocol</a></li>
<li><a href="https://amutheezan.com/computer%20architecture/fixfuturebus+/">Fix on Futurebus+ Protocol</a></li>
</ol>
<p>Hope you enjoyed this post.</p>Amutheezan SivagnanamThe model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states. Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system Murphi3.1.Introduction to Murphi3.1 - IV2021-06-07T00:00:00-04:002021-06-07T00:00:00-04:00https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-4<p>The model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states.
Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system
Murphi3.1.</p>
<p>This is the continuation of <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-3/">previous post</a>
which provides a toy example in Murphi3.1.</p>
<p>In this post, I will go through small extension to toy example using murphi3.1, based on what I have discussed in
earlier posts.</p>
<h3 id="small-extension-toy-example---simple-file-management-system">SMALL EXTENSION TOY-EXAMPLE - Simple File Management System</h3>
<p>This example is adapted from <a href="https://en.wikipedia.org/wiki/MSI_protocol">MSI Protocol</a>.</p>
<p>We extend the File Management System which we explain in the previous post, to support either multiple readers can read
the file or only one writer can write the file with less bus transactions. We define this model by a simple Finite state
machine with following states,</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">Unused</code> - No one uses the files</li>
<li><code class="language-plaintext highlighter-rouge">Shared</code> - File is read by one or more people</li>
<li><code class="language-plaintext highlighter-rouge">Modified</code> - File is modified by one of the person</li>
</ol>
<p>In this model, we split the <code class="language-plaintext highlighter-rouge">Used</code> states to two states <code class="language-plaintext highlighter-rouge">Shared</code> and <code class="language-plaintext highlighter-rouge">Modified</code>.</p>
<p>Next we define, how the communication are happen,
The file (or data) in main-memory and it will loaded into virtual/private memory of individual users when they call
a <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command. The communication happen through a bus which connects all the users and main-memory
and when ever some user send either <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command, it will communicate to the main memory and
obtain the copy and use it.</p>
<p>Detailed State Diagram.</p>
<p><img src="https://amutheezan.com/images/3states.png" alt="image" /></p>
<p>Now we look into how we simply convert this state diagram into murphi verification code.</p>
<p>Consider there is only one file and 3 people have access to the file. Those three people can either <code class="language-plaintext highlighter-rouge">Read</code>
or <code class="language-plaintext highlighter-rouge">Write</code> the file.</p>
<p>First we define the constants, types and variables required to define the simple file system,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span>
<span class="n">person_count</span><span class="o">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">file_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">type</span>
<span class="n">Proc</span> <span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">person_count</span><span class="p">);</span>
<span class="n">Value</span><span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">file_count</span><span class="p">);</span>
<span class="n">ProcState</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">state</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">FS_UNUSED</span><span class="p">,</span>
<span class="n">FS_SHARED</span><span class="p">,</span>
<span class="n">FS_MODIFIED</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">MessageType</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">Invalidate</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">Message</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">mtype</span><span class="o">:</span> <span class="n">MessageType</span><span class="p">;</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">var</span>
<span class="n">proc_state</span><span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">Proc</span><span class="p">]</span> <span class="n">of</span> <span class="n">ProcState</span><span class="p">;</span>
<span class="n">last_write</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">send_msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span>
</code></pre></div></div>
<p>Next we define the method <code class="language-plaintext highlighter-rouge">SendMessage</code> to send messages through bus to other person, when ever someone starts
writing. This function will invalidate and move to the state <code class="language-plaintext highlighter-rouge">Unused</code>, when ever some one write.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">SendMessage</span><span class="p">(</span><span class="n">msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span><span class="p">);</span>
<span class="n">begin</span>
<span class="k">switch</span> <span class="n">msg</span><span class="p">.</span><span class="n">mtype</span>
<span class="k">case</span> <span class="n">Invalidate</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">endswitch</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<p>Thereafter we have two define the rulesets for <code class="language-plaintext highlighter-rouge">Read</code> and <code class="language-plaintext highlighter-rouge">Write</code> commands as shown below.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ruleset</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">alias</span> <span class="n">p</span><span class="o">:</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">do</span>
<span class="n">ruleset</span> <span class="n">v</span><span class="o">:</span> <span class="n">Value</span> <span class="k">do</span>
<span class="n">rule</span> <span class="s">"Write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_USED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span><span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">Invalidate</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_USED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<p>After that, we define the start states as follows,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="k">for</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">send_msg</span><span class="p">;</span>
<span class="n">endstartstate</span><span class="p">;</span>
</code></pre></div></div>
<p>At the beginning all the person systems in <code class="language-plaintext highlighter-rouge">Unused</code> state for the particular file and file is in <code class="language-plaintext highlighter-rouge">Undefined</code>.</p>
<p>As a last step we add one additional thing that is <strong>Invariant</strong>.
Invariant describes how valid system should be,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Invariant</span> <span class="s">"only one person in Write state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"values in valid state match last write"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_MODIFIED</span>
<span class="o">-></span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span> <span class="o">=</span> <span class="n">last_write</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"value is undefined while invalid"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span>
<span class="o">-></span>
<span class="n">IsUndefined</span><span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span><span class="p">)</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>Finally, we need to work on how to actually compile this and verify the system.</p>
<ol>
<li>First combine the entire codes and make a murphi file.</li>
<li>Then generate <code class="language-plaintext highlighter-rouge">.C</code> file using the murphi file.</li>
<li>Then produce the executable file using <code class="language-plaintext highlighter-rouge">make</code> command and run.</li>
</ol>
<p>In the <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-5/">next post</a>, I will talk about how to
fully extend this this extended file system.</p>
<p>Hope you enjoyed this post.</p>Amutheezan SivagnanamThe model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states. Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system Murphi3.1.Introduction to Murphi3.1 - III2021-06-06T00:00:00-04:002021-06-06T00:00:00-04:00https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-3<p>The model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states.
Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system
Murphi3.1.</p>
<p>This is the continuation of <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-2/">previous post</a>
which provides remaining introduction to Murphi3.1.</p>
<p>In this post, I will go through some toy example using murphi3.1, based on what I have discussed in earlier posts.</p>
<h3 id="toy-example---simple-file-management-system">TOY-EXAMPLE - Simple File Management System</h3>
<p>Define a File Management System, in simple form either multiple readers can read the file or only one writer can write
the file. We define this model by a simple Finite state machine with following states,</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">Unused</code> - No one uses the files</li>
<li><code class="language-plaintext highlighter-rouge">Used</code> - File is read by one or more people, or modified by one person</li>
</ol>
<p>Next we define, how the communication are happen,
The file (or data) in main-memory and it will loaded into virtual/private memory of individual users when they call
a <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command. The communication happen through a bus which connects all the users and main-memory
and when ever some user send either <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> command, it will communicate to the main memory and
obtain the copy and use it.</p>
<p>When ever one person tries to access the file using <code class="language-plaintext highlighter-rouge">Write</code> command, the Write Command will send through the process
to update other person opening the file (in either <code class="language-plaintext highlighter-rouge">Read</code> or <code class="language-plaintext highlighter-rouge">Write</code> mode)</p>
<p>Detailed State Diagram.</p>
<p><img src="https://amutheezan.com/images/2states.png" alt="image" /></p>
<p>Now we look into how we simply convert this state diagram into murphi verification code.</p>
<p>Consider there is only one file and 3 people have access to the file. Those three people can either <code class="language-plaintext highlighter-rouge">Read</code>
or <code class="language-plaintext highlighter-rouge">Write</code> the file.</p>
<p>First we define the constants, types and variables required to define the simple file system,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span>
<span class="n">person_count</span><span class="o">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">file_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">type</span>
<span class="n">Proc</span> <span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">person_count</span><span class="p">);</span>
<span class="n">Value</span><span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">file_count</span><span class="p">);</span>
<span class="n">ProcState</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">state</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">FS_UNUSED</span><span class="p">,</span>
<span class="n">FS_USED</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">MessageType</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">Invalidate</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">Message</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">mtype</span><span class="o">:</span> <span class="n">MessageType</span><span class="p">;</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">var</span>
<span class="n">proc_state</span><span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">Proc</span><span class="p">]</span> <span class="n">of</span> <span class="n">ProcState</span><span class="p">;</span>
<span class="n">last_write</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">send_msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span>
</code></pre></div></div>
<p>Next we define the method <code class="language-plaintext highlighter-rouge">SendMessage</code> to send messages through bus to other person, when ever someone starts
writing. This function will invalidate and move to the state <code class="language-plaintext highlighter-rouge">Unused</code>, when ever some one write.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">SendMessage</span><span class="p">(</span><span class="n">msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span><span class="p">);</span>
<span class="n">begin</span>
<span class="k">switch</span> <span class="n">msg</span><span class="p">.</span><span class="n">mtype</span>
<span class="k">case</span> <span class="n">Invalidate</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">endswitch</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<p>Thereafter we have two define the rulesets for <code class="language-plaintext highlighter-rouge">Read</code> and <code class="language-plaintext highlighter-rouge">Write</code> commands as shown below.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ruleset</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">alias</span> <span class="n">p</span><span class="o">:</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">do</span>
<span class="n">ruleset</span> <span class="n">v</span><span class="o">:</span> <span class="n">Value</span> <span class="k">do</span>
<span class="n">rule</span> <span class="s">"Write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_USED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span><span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">Invalidate</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_USED</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<p>After that, we define the start states as follows,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="k">for</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FS_UNUSED</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">send_msg</span><span class="p">;</span>
<span class="n">endstartstate</span><span class="p">;</span>
</code></pre></div></div>
<p>At the beginning all the person systems in <code class="language-plaintext highlighter-rouge">Unused</code> state for the particular file and file is in <code class="language-plaintext highlighter-rouge">Undefined</code>.</p>
<p>As a last step we add one additional thing that is <strong>Invariant</strong>.
Invariant describes how valid system should be,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Invariant</span> <span class="s">"values in valid state match last write"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_USED</span>
<span class="o">-></span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span> <span class="o">=</span> <span class="n">last_write</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"value is undefined while invalid"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FS_UNUSED</span>
<span class="o">-></span>
<span class="n">IsUndefined</span><span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span><span class="p">)</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>Finally, we need to work on how to actually compile this and verify the system.</p>
<ol>
<li>First combine the entire codes and make a murphi file.</li>
<li>Then generate <code class="language-plaintext highlighter-rouge">.C</code> file using the murphi file.</li>
<li>Then produce the executable file using <code class="language-plaintext highlighter-rouge">make</code> command and run.</li>
</ol>
<p>In the <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-4/">next post</a>, I will talk about how to
extend this simple file system.</p>
<p>Hope you enjoyed this post.</p>Amutheezan SivagnanamThe model I describe in the toy example is not fully specified. So in the real -world, it can reach a failure states. Thise purpose of these series of posts aims to get into hands with how to implement verification from specified system Murphi3.1.Introduction to Murphi3.1 - II2021-06-05T00:00:00-04:002021-06-05T00:00:00-04:00https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-2<p>This is the continuation of <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-1/">previous post</a>
which provides an basic introduction to Murphi3.1.</p>
<h4 id="defining-rulesets">Defining Rulesets</h4>
<p>Rulesets defines the flow of the systems defined by the finite state machine, (I will discuss on another post in detail
about automata and finite state machines). Also ruleset can be used to provide communication using functions.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ruleset</span> <span class="o"><</span><span class="n">val</span><span class="o">>:</span> <span class="o"><</span><span class="n">Values</span><span class="o">></span><span class="k">do</span>
<span class="n">rule</span> <span class="s">"<name of rule>"</span>
<span class="n">preconditions</span>
<span class="o">==></span>
<span class="n">change</span> <span class="n">in</span> <span class="n">states</span>
<span class="n">function</span> <span class="n">calls</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<p>The preconditions can contain single or multiple condition combined using and (<code class="language-plaintext highlighter-rouge">&</code>) , or (<code class="language-plaintext highlighter-rouge">|</code>).</p>
<p>The change in states, will provide the change of variables</p>
<p>The function calls, will provide communication between other components.
(this can be optional)</p>
<h4 id="defining-startstate">Defining StartState</h4>
<p>Defines the start state of system, probably contains the initial values for the all the global variables.
sample statestate definition can be</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="o"><</span><span class="n">variable_name</span><span class="o">></span> <span class="o">:</span> <span class="o"><</span><span class="n">initial_value</span><span class="o">></span>
<span class="n">or</span>
<span class="n">undefined</span><span class="o">:</span> <span class="o"><</span><span class="n">varibale_name</span><span class="o">></span>
<span class="n">endstartstate</span>
</code></pre></div></div>
<h4 id="defining-invariants">Defining Invariants</h4>
<p>Invariants use to identify the loopholes in the implementation, in every system we may be aware of system states which
is not practically possible. By placing an invariant we can check whether the system reach such a state or not. In case
if the system reach the particular invariant state, then the implementation of system has flaws and need to be fixed.</p>
<p>Sample syntax for invariants</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">invariant</span> <span class="s">"<name of the invariant"</span>
<span class="n">ForAll</span> <span class="o"><</span><span class="n">val</span><span class="o">></span> <span class="o">:</span> <span class="o"><</span><span class="n">Values</span><span class="o">></span> <span class="n">Do</span>
<span class="k">if</span> <span class="n">condition</span>
<span class="o">-></span>
<span class="n">expected</span> <span class="n">implication</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>if condition, used to check whether the system in particular states and expected implication used to check whether
system in correct state based on the given finite state machine.</p>
<p>Simply speaking, we can define the invariants
<code class="language-plaintext highlighter-rouge">p => q</code>, if the condition <code class="language-plaintext highlighter-rouge">p</code> becomes true, the invariant check whether <code class="language-plaintext highlighter-rouge">q</code> is satisfied or not.</p>
<p>In the <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-3/">next post</a> I will discuss on simple
examples using the Murphi3.1.</p>
<p>Hope you enjoyed this post.</p>Amutheezan SivagnanamThis is the continuation of previous post which provides an basic introduction to Murphi3.1.Introduction to Murphi3.1 - I2021-06-04T00:00:00-04:002021-06-04T00:00:00-04:00https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-1<p>In software engineering, we have to go through three main stages, formal specification (i.e., that is fully specifies
how the models works including all possible exceptions and errors), verification (i.e., verify the specified model,
against different inputs and make sure the model works correctly), implementation (i.e., implementing the actual model
which is already specified and verified). For detailed understanding click
this <a href="https://users.ece.cmu.edu/~koopman/des_s99/formal_methods/">link</a>.</p>
<h3 id="murphi31">Murphi3.1</h3>
<p>Murphi is a tool that developed to verify whether the specfied model work without any failure (note, this different from
error and exception, this is some thing that let the system to unrealistic states. e.g. In a master-slave model, having
two master is unrealistic).</p>
<h3 id="basic-tutorials">Basic Tutorials</h3>
<p>In this first post, I mainly focus on providing a basic introduction how to work with murphi3.1, like setting constants,
types and variables, and incoming up posts I will go in deep with murphi3.1.</p>
<h4 id="setting-constants">Setting Constants</h4>
<p>Constants are analogs to the constants we define in normal programming languages. We use constants to define some strict
parameters or limitations in the systems.
e.g. Number of Slaves (in master-slave model)</p>
<p>We can set simple constants using following
syntax in Murphi,</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>const
<constant_name>: <const_value>;
</code></pre></div></div>
<h4 id="defining-variables">Defining Variables</h4>
<p>Again, variables are used to keep track of varying values in the system. We can use either simple variables with exist
variable types such as <code class="language-plaintext highlighter-rouge">boolean</code> or we can define a custom variables by defining the type in type definition (in
that case type definition should presents before defining the variables other wise compilation error would occurs). You
can also define the variable as array of varriable by using<code class="language-plaintext highlighter-rouge">array</code> key word.</p>
<p>Variable can be defined in the following format</p>
<p>Simple definition,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">var</span>
<span class="o"><</span><span class="n">variable_name</span><span class="o">>:</span> <span class="o"><</span><span class="n">type</span><span class="o">></span><span class="p">;</span>
</code></pre></div></div>
<p>Using array definition,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">var</span>
<span class="o"><</span><span class="n">variable_name</span><span class="o">>:</span> <span class="n">array</span><span class="p">[</span><span class="o"><</span><span class="n">type_name_1</span><span class="o">></span><span class="p">]</span> <span class="n">of</span> <span class="o"><</span><span class="n">type_name_2</span><span class="o">></span><span class="p">;</span>
</code></pre></div></div>
<p>where <code class="language-plaintext highlighter-rouge">type_name_1</code> is mostly from the type defined upon <code class="language-plaintext highlighter-rouge">scalerset</code> or <code class="language-plaintext highlighter-rouge">multiset</code>, where
as <code class="language-plaintext highlighter-rouge">type_name_2</code> can be from simple complex structured type as well as simple types. I will discuss more about types
in the next paragraph.</p>
<h4 id="defining-types">Defining Types</h4>
<p>Next, we look into how to define a type. It can go through either simple steps using predefine structures on top of
existing types like <code class="language-plaintext highlighter-rouge">scalarset</code> or <code class="language-plaintext highlighter-rouge">multiset</code>, or define with enumeration <code class="language-plaintext highlighter-rouge">enum</code>. In more complex cases one
or more type can be provided as the attributes of the type.</p>
<p>Types can be defined in the following format</p>
<p>Simple Definition:
Here the type is define on top of the <code class="language-plaintext highlighter-rouge">scalerset</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">type</span>
<span class="o"><</span><span class="n">type_name</span><span class="o">>:</span> <span class="n">scalarset</span><span class="p">(</span><span class="o"><</span><span class="n">integer_value</span><span class="o">></span><span class="p">);</span>
</code></pre></div></div>
<p>Complex Structure:</p>
<p>In complex structure, we can combine on or more simple types and complex ones as well. Also we can provides enumerations
as attributes. Types can be resembles the object of the general programming. In the below examples we can observe that
there are two attributes inside the main type (<code class="language-plaintext highlighter-rouge">record</code>) such as <code class="language-plaintext highlighter-rouge">enum</code> and another one, it can be either
another <code class="language-plaintext highlighter-rouge">type</code> we defined or predefined types.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">type</span>
<span class="o"><</span><span class="n">type_name</span><span class="o">>:</span> <span class="n">record</span>
<span class="o"><</span><span class="n">attribute_1</span><span class="o">>:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">ENUM_VAL_1</span><span class="p">,</span>
<span class="n">ENUM_VAL_2</span>
<span class="p">};</span>
<span class="o"><</span><span class="n">attribute_2</span><span class="o">>:</span> <span class="o"><</span><span class="n">type_name</span><span class="o">></span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<h4 id="defining-functions-or-procedures">Defining Functions or Procedures.</h4>
<p>We can defines functions or procedures based on the following syntax,</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">NameOfProcedure</span><span class="p">(</span><span class="o"><</span><span class="n">arg_name</span><span class="o">>:</span> <span class="o"><</span><span class="n">arg_type</span><span class="o">></span><span class="p">;...);</span>
<span class="n">begin</span>
<span class="p">....</span>
<span class="n">end</span>
</code></pre></div></div>
<p>You can define input mutliple input arguments by seperating each argument definition using <code class="language-plaintext highlighter-rouge">;</code>.</p>
<p>In the <a href="https://amutheezan.com/formal%20methods%20and%20verification/murphi3.1-2">next post</a>, I will discuss on how to
define the rulesets, startstate and invariants.</p>
<p>Hope you enjoy this post.</p>Amutheezan SivagnanamIn software engineering, we have to go through three main stages, formal specification (i.e., that is fully specifies how the models works including all possible exceptions and errors), verification (i.e., verify the specified model, against different inputs and make sure the model works correctly), implementation (i.e., implementing the actual model which is already specified and verified). For detailed understanding click this link.Simple Fix on Futurebus+ Cache Coherence Protocol2021-05-31T00:00:00-04:002021-05-31T00:00:00-04:00https://amutheezan.com/computer%20architecture/fixfuturebus+<p>I have implemented a simple fixing for Futurebus+ cache coherence protocol which I explained in
my <a href="https://amutheezan.com/computer%20architecture/futurebus+/">previous post</a>.</p>
<h3 id="initial-setup--steps">Initial Setup & Steps</h3>
<p>Initially clone the <a href="https://github.com/Amutheezan/futurebus">repository</a> and go to the code <code class="language-plaintext highlighter-rouge">main</code> directory and
execute the following two command to start the docker instances (make sure docker is already installed in your computer
and started; check here for installation steps of <a href="https://docs.docker.com/get-docker/">docker</a>.</p>
<p><code class="language-plaintext highlighter-rouge">docker-compose build</code></p>
<p><code class="language-plaintext highlighter-rouge">docker-compose run ubuntu bash</code></p>
<p><strong>Note</strong>: the docker implementation and murphi3.1 integration obtained from the
following <a href="https://github.com/adnaneGdihi/fixed_murphi3.1">repository</a>.</p>
<p>After that you will get into the bash follow the steps shown below in the ubuntu bash,</p>
<ul>
<li>First go to the directory <code class="language-plaintext highlighter-rouge">Murphi3.1/src</code> and compile the Murphi using <code class="language-plaintext highlighter-rouge">make</code> command (if it not already
generated). And optionally make the executable access using the command <code class="language-plaintext highlighter-rouge">chmod +x Murphi3.1/src/mu</code>, if you in the
home directory.</li>
<li>Then go to the directory <code class="language-plaintext highlighter-rouge">verification</code> and obtain the C file for the Futurebus+ verification
using <code class="language-plaintext highlighter-rouge">./../Murphi3.1/src/mu futurebus.m</code> command (if it not already generated). This will generate the C
file <code class="language-plaintext highlighter-rouge">futurebus.C</code>.</li>
<li>Thereafter compile the generate file using the command <code class="language-plaintext highlighter-rouge">make futurebus</code>, this eventually generate the executable
program.</li>
<li>Finally run the executable using the following command <code class="language-plaintext highlighter-rouge">./futurebus</code></li>
</ul>
<h3 id="or">OR</h3>
<p>you can perform these entire steps by simply go to the <code class="language-plaintext highlighter-rouge">verification</code> directory and run the command <code class="language-plaintext highlighter-rouge">sh run.sh</code>.</p>
<h2 id="verification-using-murphi31">Verification using Murphi3.1</h2>
<p>Please note that Murphi3.1 come installed with docker image so no need to worry about downloading and setting up.</p>
<p>I followed the same code structure as previous post.</p>
<ul>
<li>constants - to define constants such as number of processor, number of values</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span>
<span class="n">processor_count</span><span class="o">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">value_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>define types such as processor states (<code class="language-plaintext highlighter-rouge">ProcState</code>) using enumeration which represents all the states in
Futurebus+ protocol, message types (<code class="language-plaintext highlighter-rouge">MessageType</code>) as enumeration which includes different message used to send
between the states either bus or cpu call, finally define the message type (<code class="language-plaintext highlighter-rouge">Message</code>) .</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">type</span>
<span class="n">Proc</span> <span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">processor_count</span><span class="p">);</span>
<span class="n">Value</span><span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">value_count</span><span class="p">);</span>
<span class="n">ProcState</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">state</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">FB_I</span><span class="p">,</span>
<span class="n">FB_EU</span><span class="p">,</span>
<span class="n">FB_EM</span><span class="p">,</span>
<span class="n">FB_SU</span><span class="p">,</span>
<span class="n">FB_PR</span><span class="p">,</span>
<span class="n">FB_PEMR</span><span class="p">,</span>
<span class="n">FB_PSU</span><span class="p">,</span>
<span class="n">FB_PW</span><span class="p">,</span>
<span class="n">FB_PEMW</span>
<span class="p">};</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">MessageType</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">ReadShared</span><span class="p">,</span>
<span class="n">ReadModified</span><span class="p">,</span>
<span class="n">Invalidate</span>
<span class="p">};</span>
<span class="n">Message</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">mtype</span><span class="o">:</span> <span class="n">MessageType</span><span class="p">;</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>variables - the global variables represents the system.</li>
</ul>
<p>I have added <code class="language-plaintext highlighter-rouge">pending_write</code> variable to identify whether there are multiple processor with pending writes and avoid
to processor to reach exclusive state due to error in Futurebus+ cache coherence protocol.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">var</span>
<span class="n">proc_state</span><span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">Proc</span><span class="p">]</span> <span class="n">of</span> <span class="n">ProcState</span><span class="p">;</span>
<span class="n">transaction_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">last_write</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">one_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">more_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">pending_write</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">send_msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>procedures - contains the function used by the verification. I have update the functions to make sure the processor to
update the variable <code class="language-plaintext highlighter-rouge">pending_write</code>.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">SendMessage</span><span class="p">(</span><span class="n">msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span><span class="p">);</span>
<span class="n">begin</span>
<span class="k">switch</span> <span class="n">msg</span><span class="p">.</span><span class="n">mtype</span>
<span class="k">case</span> <span class="n">ReadShared</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">case</span> <span class="n">ReadModified</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">case</span> <span class="n">Invalidate</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endswitch</span><span class="p">;</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">msg</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">procedure</span> <span class="nf">UpdateSignals</span><span class="p">();</span>
<span class="n">begin</span>
<span class="k">for</span> <span class="n">m</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span> <span class="n">then</span>
<span class="n">pending_write</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="k">for</span> <span class="n">m</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="n">then</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="k">for</span> <span class="n">m</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="n">then</span>
<span class="k">if</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">true</span> <span class="n">then</span>
<span class="n">more_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">if</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="n">then</span>
<span class="n">one_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>ruleset - define the set of rules that can be used to model the systems. Update the ruleset to avoid two processor
reach the exclusive state.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">ruleset</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">alias</span> <span class="n">p</span><span class="o">:</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">do</span>
<span class="n">ruleset</span> <span class="n">v</span><span class="o">:</span> <span class="n">Value</span> <span class="k">do</span>
<span class="n">rule</span> <span class="s">"Write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span><span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">Invalidate</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PEMW</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Invalidate, on DACKemw"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Write data, on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadModified</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Write data, on DACKemw"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadModified</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PW</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data (pending)"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span> <span class="o">&</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PW</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to read data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to read data (pending)"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Moved to shared state from EMR on DACKem"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read shared data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data from EM"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PEMR</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Pending Shared state"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PSU</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">more_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACKem"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">more_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Exclusive state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data from Exclusive states"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>start-state - define the start state of the system.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="k">for</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">one_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">more_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">send_msg</span><span class="p">;</span>
<span class="n">endstartstate</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>invariants - define the cases which determine the correct states of the system, or checking the validity of the
system. We don’t need to change the invariants from initial verification, we can still use the same invariants, and
check whether any of these invariants failed or not.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">Invariant</span> <span class="s">"only one processor in EM state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"only one processor in EU state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">invariant</span> <span class="s">"values in valid state match last write"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span>
<span class="o">-></span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span> <span class="o">=</span> <span class="n">last_write</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">invariant</span> <span class="s">"value is undefined while invalid"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span>
<span class="o">-></span>
<span class="n">IsUndefined</span><span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span><span class="p">)</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>Output of verification of Futurebus+ cache coherence protocol, this provides a brief summary whether any errors or
issues found and other statistics. And we observe no outputs.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus_fix
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 104 bits (rounded up to 16 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 392159 states.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 39215 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
Warning: No trace will not be printed in the case of protocol errors!
Check the options if you want to have error traces.
Status:
No error found.
State Space Explored:
476 states, 3233 rules fired in 0.10s.
Analysis of State Space:
There are rules that are never fired.
If you are running with symmetry, this may be why. Otherwise,
please run this program with "-pr" for the rules information.
</code></pre></div></div>
<p>Next I provides the output of error traces of Futurebus+ traces of cache coherence protocol using the command
suffix <code class="language-plaintext highlighter-rouge">-tv</code>. This provides the the reasons why the error happen.l And you observe that now the error doesn’t
occurs.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus_fix
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 104 bits (rounded up to 16 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 392159 states.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 39215 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
Status:
No error found.
State Space Explored:
476 states, 3233 rules fired in 0.10s.
Analysis of State Space:
There are rules that are never fired.
If you are running with symmetry, this may be why. Otherwise,
please run this program with "-pr" for the rules information.
</code></pre></div></div>
<p>Finally, to observe what are rule fired, I obtain the output of rule firing of Futurebus+ traces of cache coherence
protocol using the command suffix <code class="language-plaintext highlighter-rouge">-pr</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus_fix
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 104 bits (rounded up to 16 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 392159 states.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 39215 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
Warning: No trace will not be printed in the case of protocol errors!
Check the options if you want to have error traces.
Status:
No error found.
State Space Explored:
476 states, 3233 rules fired in 0.10s.
Rules Information:
Fired 35 times - Rule "Read data from Exclusive states, i:Proc_1"
Fired 19 times - Rule "Read data from Exclusive states, i:Proc_2"
Fired 9 times - Rule "Read data from Exclusive states, i:Proc_3"
Fired 4 times - Rule "Go to Exclusive state on DACK, i:Proc_1"
Fired 5 times - Rule "Go to Exclusive state on DACK, i:Proc_2"
Fired 3 times - Rule "Go to Exclusive state on DACK, i:Proc_3"
Fired 3 times - Rule "Go to Shared state on DACKem, i:Proc_1"
Fired 4 times - Rule "Go to Shared state on DACKem, i:Proc_2"
Fired 2 times - Rule "Go to Shared state on DACKem, i:Proc_3"
Fired 3 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 4 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 2 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 97 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 141 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 72 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 21 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 61 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 81 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 116 times - Rule "Go to Pending Shared state, i:Proc_1"
Fired 120 times - Rule "Go to Pending Shared state, i:Proc_2"
Fired 98 times - Rule "Go to Pending Shared state, i:Proc_3"
Fired 50 times - Rule "Read data from EM, i:Proc_1"
Fired 51 times - Rule "Read data from EM, i:Proc_2"
Fired 44 times - Rule "Read data from EM, i:Proc_3"
Fired 91 times - Rule "Read shared data, i:Proc_1"
Fired 56 times - Rule "Read shared data, i:Proc_2"
Fired 16 times - Rule "Read shared data, i:Proc_3"
Fired 19 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_1"
Fired 35 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_2"
Fired 36 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_3"
Fired 101 times - Rule "Trying to read data (pending), i:Proc_1"
Fired 146 times - Rule "Trying to read data (pending), i:Proc_2"
Fired 75 times - Rule "Trying to read data (pending), i:Proc_3"
Fired 190 times - Rule "Trying to read data, i:Proc_1"
Fired 61 times - Rule "Trying to read data, i:Proc_2"
Fired 9 times - Rule "Trying to read data, i:Proc_3"
Fired 6 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_1"
Fired 26 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_2"
Fired 46 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_3"
Fired 190 times - Rule "Trying to write data, v:Value_1, i:Proc_1"
Fired 61 times - Rule "Trying to write data, v:Value_1, i:Proc_2"
Fired 9 times - Rule "Trying to write data, v:Value_1, i:Proc_3"
Fired 16 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_1"
Fired 73 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_2"
Fired 124 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_3"
Fired 16 times - Rule "Write data, on DACK, v:Value_1, i:Proc_1"
Fired 73 times - Rule "Write data, on DACK, v:Value_1, i:Proc_2"
Fired 124 times - Rule "Write data, on DACK, v:Value_1, i:Proc_3"
Fired 3 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_1"
Fired 25 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_2"
Fired 126 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_3"
Fired 34 times - Rule "Trying to write data, v:Value_1, i:Proc_1"
Fired 41 times - Rule "Trying to write data, v:Value_1, i:Proc_2"
Fired 134 times - Rule "Trying to write data, v:Value_1, i:Proc_3"
Fired 126 times - Rule "Write data, v:Value_1, i:Proc_1"
Fired 75 times - Rule "Write data, v:Value_1, i:Proc_2"
Fired 25 times - Rule "Write data, v:Value_1, i:Proc_3"
</code></pre></div></div>
<p>Verification of Futurebus+ Cache Coherence Protocol can be found
in <a href="https://amutheezan.com/computer%20architecture/futurebus+">previous post</a>.</p>Amutheezan SivagnanamI have implemented a simple fixing for Futurebus+ cache coherence protocol which I explained in my previous post.Verification of Futurebus+ Cache Coherence Protocol2021-05-30T00:00:00-04:002021-05-30T00:00:00-04:00https://amutheezan.com/computer%20architecture/futurebus+<p>In this post, I share a simple verification for the Futurebus+ cache coherence protocol as part of an assignment for the
<strong>COSC 6385</strong> course at the University of Houston.</p>
<h2 id="initial-setup--steps">Initial Setup & Steps</h2>
<p>Initially clone the <a href="https://github.com/Amutheezan/futurebus">repository</a> and go to the code <code class="language-plaintext highlighter-rouge">main</code> directory and
execute the following two command to start the docker instances (make sure docker is already installed in your computer
and started; check here for installation steps of <a href="https://docs.docker.com/get-docker/">docker</a>.</p>
<p><code class="language-plaintext highlighter-rouge">docker-compose build</code></p>
<p><code class="language-plaintext highlighter-rouge">docker-compose run ubuntu bash</code></p>
<p><strong>Note</strong>: the docker implementation and murphi3.1 integration obtained from the
following <a href="https://github.com/adnaneGdihi/fixed_murphi3.1">repository</a>.</p>
<p>After that you will get into the bash, follow the steps shown below in the ubuntu bash,</p>
<ul>
<li>First go to the directory <code class="language-plaintext highlighter-rouge">Murphi3.1/src</code> and compile the Murphi using <code class="language-plaintext highlighter-rouge">make</code> command (if it not already
generated). And optionally make the executable access using the command <code class="language-plaintext highlighter-rouge">chmod +x Murphi3.1/src/mu</code>, if you in the
home directory.</li>
<li>Then go to the directory <code class="language-plaintext highlighter-rouge">verification</code> and obtain the C file for the Futurebus+ verification
using <code class="language-plaintext highlighter-rouge">./../Murphi3.1/src/mu futurebus.m</code> command (if it not already generated). This will generate the C
file <code class="language-plaintext highlighter-rouge">futurebus.C</code>.</li>
<li>Thereafter, compile the generate file using the command <code class="language-plaintext highlighter-rouge">make futurebus</code>, this eventually generate the executable
program.</li>
<li>Finally, run the executable using the following command <code class="language-plaintext highlighter-rouge">./futurebus</code></li>
</ul>
<h3 id="or">OR</h3>
<p>you can perform these entire steps by simply go to the <code class="language-plaintext highlighter-rouge">verification</code> directory and run the command <code class="language-plaintext highlighter-rouge">sh run.sh</code>.</p>
<h2 id="verification-using-murphi31">Verification using Murphi3.1</h2>
<p>Please note that Murphi3.1 come installed with docker image so no need to worry about downloading and setting up.</p>
<p>I structure the code as follows,</p>
<ul>
<li>constants - to define constants such as number of processor, number of values</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span>
<span class="n">processor_count</span><span class="o">:</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">value_count</span><span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>define types such as processor states (<code class="language-plaintext highlighter-rouge">ProcState</code>) using enumeration which represents all the states in
Futurebus+ protocol, message types (<code class="language-plaintext highlighter-rouge">MessageType</code>) as enumeration which includes different message used to send
between the states either bus or cpu call, finally define the message type (<code class="language-plaintext highlighter-rouge">Message</code>) .</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">type</span>
<span class="n">Proc</span> <span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">processor_count</span><span class="p">);</span>
<span class="n">Value</span><span class="o">:</span> <span class="n">scalarset</span><span class="p">(</span><span class="n">value_count</span><span class="p">);</span>
<span class="n">ProcState</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">state</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">FB_I</span><span class="p">,</span>
<span class="n">FB_EU</span><span class="p">,</span>
<span class="n">FB_EM</span><span class="p">,</span>
<span class="n">FB_SU</span><span class="p">,</span>
<span class="n">FB_PR</span><span class="p">,</span>
<span class="n">FB_PEMR</span><span class="p">,</span>
<span class="n">FB_PSU</span><span class="p">,</span>
<span class="n">FB_PW</span><span class="p">,</span>
<span class="n">FB_PEMW</span>
<span class="p">};</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">MessageType</span><span class="o">:</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">ReadShared</span><span class="p">,</span>
<span class="n">ReadModified</span><span class="p">,</span>
<span class="n">Invalidate</span>
<span class="p">};</span>
<span class="n">Message</span><span class="o">:</span>
<span class="n">record</span>
<span class="n">mtype</span><span class="o">:</span> <span class="n">MessageType</span><span class="p">;</span>
<span class="n">value</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>variables - the global variables represents the system.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">var</span>
<span class="n">proc_state</span><span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">Proc</span><span class="p">]</span> <span class="n">of</span> <span class="n">ProcState</span><span class="p">;</span>
<span class="n">transaction_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">last_write</span><span class="o">:</span> <span class="n">Value</span><span class="p">;</span>
<span class="n">one_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">more_flag</span><span class="o">:</span> <span class="n">boolean</span><span class="p">;</span>
<span class="n">send_msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>procedures - contains the function used by the verification.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">procedure</span> <span class="n">SendMessage</span><span class="p">(</span><span class="n">msg</span><span class="o">:</span> <span class="n">Message</span><span class="p">;</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span><span class="p">);</span>
<span class="n">begin</span>
<span class="k">switch</span> <span class="n">msg</span><span class="p">.</span><span class="n">mtype</span>
<span class="k">case</span> <span class="n">ReadShared</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">case</span> <span class="n">ReadModified</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">case</span> <span class="n">Invalidate</span><span class="p">:</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endswitch</span><span class="p">;</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">msg</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span> <span class="n">then</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
<span class="n">procedure</span> <span class="nf">UpdateSignals</span><span class="p">();</span>
<span class="n">begin</span>
<span class="k">for</span> <span class="n">m</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="n">then</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="k">for</span> <span class="n">m</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">m</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="n">then</span>
<span class="k">if</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">true</span> <span class="n">then</span>
<span class="n">more_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="k">if</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="n">then</span>
<span class="n">one_flag</span> <span class="o">:=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">end</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>ruleset - define the set of rules that can be used to model the systems.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">ruleset</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">alias</span> <span class="n">p</span><span class="o">:</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">do</span>
<span class="n">ruleset</span> <span class="n">v</span><span class="o">:</span> <span class="n">Value</span> <span class="k">do</span>
<span class="n">rule</span> <span class="s">"Write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span><span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">Invalidate</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PEMW</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Invalidate, on DACKemw"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">undefined</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Write data, on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadModified</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Write data, on DACKemw"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EM</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">last_write</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadModified</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">v</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PW</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to write data (pending)"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PW</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PW</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to read data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Trying to read data (pending)"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PR</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Moved to shared state from EMR on DACKem"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read shared data"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data from EM"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PEMR</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PEMR</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Pending Shared state"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_PSU</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PSU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">more_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Shared state on DACKem"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">more_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_SU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Go to Exclusive state on DACK"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_PR</span> <span class="o">&</span> <span class="n">transaction_flag</span> <span class="o">=</span> <span class="nb">false</span> <span class="o">&</span> <span class="n">one_flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_EU</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="k">for</span> <span class="n">k</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">k</span> <span class="n">then</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">mtype</span> <span class="o">:=</span> <span class="n">ReadShared</span><span class="p">;</span>
<span class="n">send_msg</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">SendMessage</span><span class="p">(</span><span class="n">send_msg</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="n">endif</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">rule</span> <span class="s">"Read data from Exclusive states"</span>
<span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">p</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span><span class="p">)</span>
<span class="o">==></span>
<span class="n">p</span><span class="p">.</span><span class="n">value</span> <span class="o">:=</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">UpdateSignals</span><span class="p">();</span>
<span class="n">endrule</span><span class="p">;</span>
<span class="n">endalias</span><span class="p">;</span>
<span class="n">endruleset</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>start-state - define the start state of the system.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">startstate</span>
<span class="k">for</span> <span class="n">i</span><span class="o">:</span> <span class="n">Proc</span> <span class="k">do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">state</span> <span class="o">:=</span> <span class="n">FB_I</span><span class="p">;</span>
<span class="n">endfor</span><span class="p">;</span>
<span class="n">transaction_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">one_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">more_flag</span> <span class="o">:=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">last_write</span><span class="p">;</span>
<span class="n">undefine</span> <span class="n">send_msg</span><span class="p">;</span>
<span class="n">endstartstate</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>invariants - define the cases which determine the correct states of the system, or checking the validity of the
system.</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">Invariant</span> <span class="s">"only one processor in EM state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">Invariant</span> <span class="s">"only one processor in EU state"</span>
<span class="n">ForAll</span> <span class="n">p1</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">ForAll</span> <span class="n">p2</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">p1</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span> <span class="o">&</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">p2</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span>
<span class="o">-></span>
<span class="n">p1</span> <span class="o">=</span> <span class="n">p2</span>
<span class="n">End</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">invariant</span> <span class="s">"values in valid state match last write"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_SU</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EM</span> <span class="o">|</span> <span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_EU</span>
<span class="o">-></span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span> <span class="o">=</span> <span class="n">last_write</span>
<span class="n">End</span><span class="p">;</span>
<span class="n">invariant</span> <span class="s">"value is undefined while invalid"</span>
<span class="n">ForAll</span> <span class="n">n</span> <span class="o">:</span> <span class="n">Proc</span> <span class="n">Do</span>
<span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">state</span> <span class="o">=</span> <span class="n">FB_I</span>
<span class="o">-></span>
<span class="n">IsUndefined</span><span class="p">(</span><span class="n">proc_state</span><span class="p">[</span><span class="n">n</span><span class="p">].</span><span class="n">value</span><span class="p">)</span>
<span class="n">End</span><span class="p">;</span>
</code></pre></div></div>
<p>Output of verification of Futurebus+ cache coherence protocol, this provides a brief summary whether any errors or
issues found and other statistics.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 96 bits (rounded up to 12 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 487811 statesn the above code, I structure code in the following structure,
\begin{itemize}
\item constants - to define constants such as number of processor, number of values
\item type - define types such as processor states using enumeration which represents all the states in Futurebus+ proctcol, message types as enumeration which includes different message used to send between the states either bus or cpu call, finally the message type.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 48781 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
Warning: No trace will not be printed in the case of protocol errors!
Check the options if you want to have error traces.
Result:
Invariant "only one processor in EM state" failed.
State Space Explored:
56 states, 184 rules fired in 0.10s.
Analysis of State Space:
There are rules that are never fired.
If you are running with symmetry, this may be why. Otherwise,
please run this program with "-pr" for the rules information.
</code></pre></div></div>
<p>Next I provides the output of error traces of Futurebus+ traces of cache coherence protocol using the command
suffix <code class="language-plaintext highlighter-rouge">-tv</code>. This provides the the reasons why the error happen (i.e two processors go to the exclusive states).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 96 bits (rounded up to 12 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 487811 states \item variables - the global variables represents the system.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 48781 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
The following is the error trace for the error:
Invariant "only one processor in EM state" failed.
Startstate Startstate 0 fired.
proc_state[Proc_1].state:FB_I
proc_state[Proc_1].value:Undefined
proc_state[Proc_2].state:FB_I
proc_state[Proc_2].value:Undefined
proc_state[Proc_3].state:FB_I
proc_state[Proc_3].value:Undefined
transaction_flag:false
last_write:Undefined
one_flag:false
more_flag:false
send_msg.mtype:Undefined
send_msg.value:Undefined
Rule Trying to write data, v:Value_1, i:Proc_1 fired.
proc_state[Proc_1].state:FB_PW
Rule Trying to write data, v:Value_1, i:Proc_2 fired.
proc_state[Proc_2].state:FB_PW
Rule Write data, on DACKemw, v:Value_1, i:Proc_1 fired.
proc_state[Proc_1].state:FB_EM
proc_state[Proc_1].value:Value_1
proc_state[Proc_2].value:Value_1
transaction_flag:true
last_write:Value_1
send_msg.mtype:ReadModified
send_msg.value:Value_1
Rule Write data, on DACKemw, v:Value_1, i:Proc_2 fired.
The last state of the trace (in full) is:
proc_state[Proc_1].state:FB_EM
proc_state[Proc_1].value:Value_1
proc_state[Proc_2].state:FB_EM
proc_state[Proc_2].value:Value_1
proc_state[Proc_3].state:FB_I
proc_state[Proc_3].value:Undefined
transaction_flag:true
last_write:Value_1
one_flag:false
more_flag:false
send_msg.mtype:ReadModified
send_msg.value:Value_1
End of the error trace.
Result:
Invariant "only one processor in EM state" failed.
State Space Explored:
56 states, 184 rules fired in 0.10s.
Analysis of State Space:
There are rules that are never fired.
If you are running with symmetry, this may be why. Otherwise,
p \item procedures - contains the function used by the verification.
\item rulease run this program with "-pr" for the rules information.
</code></pre></div></div>
<p>Finally, to observe what are rule fired, I obtain the output of rule firing of Futurebus+ traces of cache coherence
protocol using the command suffix <code class="language-plaintext highlighter-rouge">-pr</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Protocol: futurebus
Algorithm:
Verification by breadth first search.
with symmetry algorithm 3 -- Heuristic Small Memory Normalization
with permutation trial limit 10.
Memory usage:
* The size of each state is 96 bits (rounded up to 12 bytes).
* The memory allocated for the hash table and state queue is
8 Mbytes.
With two words of overhead per state, the maximum size of
the state space is 487811 statet - define the set of rules that can be used to model the systems.
* Use option "-k" or "-m" to increase this, if necessary.
* Capacity in queue for breadth-first search: 48781 states.
* Change the constant gPercentActiveStates in mu_prolog.inc
to increase this, if necessary.
Warning: No trace will not be printed in the case of protocol errors!
Check the options if you want to have error traces.
Result:
Invariant "only one processor in EM state" failed.
State Space Explored:
56 states, 184 rules fired in 0.10s.
Rules Information:
Fired 0 times - Rule "Read data from Exclusive states, i:Proc_1"
Fired 4 times - Rule "Read data from Exclusive states, i:Proc_2"
Fired 4 times - Rule "Read data from Exclusive states, i:Proc_3"
Fired 4 times - Rule "Go to Exclusive state on DACK, i:Proc_1"
Fired 5 times - Rule "Go to Exclusive state on DACK, i:Proc_2"
Fired 3 times - Rule "Go to Exclusive state on DACK, i:Proc_3"
Fired 3 times - Rule "Go to Shared state on DACKem, i:Proc_1"
Fired 4 times - Rule "Go to Shared state on DACKem, i:Proc_2"
Fired 2 times - Rule "Go to Shared state on DACKem, i:Proc_3"
Fired 3 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 4 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 2 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 0 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 0 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 2 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 0 times - Rule "Go to Shared state on DACK, i:Proc_1"
Fired 0 times - Rule "Go to Shared state on DACK, i:Proc_2"
Fired 1 times - Rule "Go to Shared state on DACK, i:Proc_3"
Fired 0 times - Rule "Go to Pending Shared state, i:Proc_1"
Fired 5 times - Rule "Go to Pending Shared state, i:Proc_2"
Fired 2 times - Rule "Go to Pending Shared state, i:Proc_3"
Fired 0 times - Rule "Read data from EM, i:Proc_1"
Fired 1 times - Rule "Read data from EM, i:Proc_2"
Fired 3 times - Rule "Read data from EM, i:Proc_3"
Fired 0 times - Rule "Read shared data, i:Proc_1"
Fired 2 times - Rule "Read shared data, i:Proc_2"
Fired 0 times - Rule "Read shared data, i:Proc_3"
Fired 0 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_1"
Fired 0 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_2"
Fired 0 times - Rule "Moved to shared state from EMR on DACKem, i:Proc_3"
Fired 4 times - Rule "Trying to read data (pending), i:Proc_1"
Fired 5 times - Rule "Trying to read data (pending), i:Proc_2"
Fired 5 times - Rule "Trying to read data (pending), i:Proc_3"
Fired 18 times - Rule "Trying to read data, i:Proc_1"
Fired 8 times - Rule "Trying to read data, i:Proc_2"
Fired 1 times - Rule "Trying to read data, i:Proc_3"
Fired 1 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_1"
Fired 4 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_2"
Fired 12 times - Rule "Trying to write data (pending), v:Value_1, i:Proc_3"
Fired 18 times - Rule "Trying to write data, v:Value_1, i:Proc_1"
Fired 8 times - Rule "Trying to write data, v:Value_1, i:Proc_2"
Fired 1 times - Rule "Trying to write data, v:Value_1, i:Proc_3"
Fired 1 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_1"
Fired 4 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_2"
Fired 12 times - Rule "Write data, on DACKemw, v:Value_1, i:Proc_3"
Fired 1 times - Rule "Write data, on DACK, v:Value_1, i:Proc_1"
Fired 4 times - Rule "Write data, on DACK, v:Value_1, i:Proc_2"
Fired 11 times - Rule "Write data, on DACK, v:Value_1, i:Proc_3"
Fired 0 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_1"
Fired 0 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_2"
Fired 0 times - Rule "Invalidate, on DACKemw, v:Value_1, i:Proc_3"
Fired 0 times - Rule "Trying to write data, v:Value_1, i:Proc_1"
Fired 0 times - Rule "Trying to write data, v:Value_1, i:Proc_2"
Fired 3 times - Rule "Trying to write data, v:Value_1, i:Proc_3"
Fired 0 times - Rule "Write data, v:Value_1, i:Proc_1"
Fired 5 times - Rule "Write data, v:Value_1, i:Proc_2"
Fired 4 times - Rule "Write data, v:Value_1, i:Proc_3"
</code></pre></div></div>
<p>In the <a href="https://amutheezan.com/computer%20architecture/fixfuturebus+/">next post</a>, I will write about how to apply a
simple fix for Futurebus+ protocol to avoid multiple processers get into exclusive state.</p>Amutheezan SivagnanamIn this post, I share a simple verification for the Futurebus+ cache coherence protocol as part of an assignment for the COSC 6385 course at the University of Houston.CPU/GPU/TPU Performance Comparison2021-05-29T00:00:00-04:002021-05-29T00:00:00-04:00https://amutheezan.com/computer%20architecture/gpuvstpu<p>I have implemented following simple comparison ofn performance on Google Colab CPU, GPU, and TPU as a part of an
assignment for <strong>COSC 6385</strong> course in University of Houston.</p>
<p>Sample Implementation can be found in the following <a href="https://github.com/Amutheezan/GPUvsTPU">repository</a>.</p>
<p>I follow the basic step by step guide in <a href="https://petamind.com/quick-benchmark-colab-cpu-gpu-tpu-xla-cpu/">1</a>.
Also, I follow the instructions to work on TPU
using <a href="https://heartbeat.fritz.ai/step-by-step-use-of-google-colab-free-tpu-75f8629492b3">2</a>.</p>
<p>First we need to import the following libraries, set the configuration to log the information and filter out the
warnings.</p>
<ul>
<li>tensorflow - for computations with matrices.</li>
<li>timeit - to compute the time taken</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">tensorflow</span> <span class="k">as</span> <span class="n">tf</span>
<span class="kn">import</span> <span class="nn">timeit</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="n">warnings</span><span class="p">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s">'ignore'</span><span class="p">)</span>
<span class="n">tf</span><span class="p">.</span><span class="n">get_logger</span><span class="p">().</span><span class="n">setLevel</span><span class="p">(</span><span class="s">'INFO'</span><span class="p">)</span>
</code></pre></div></div>
<h2 id="simple-implementation">SIMPLE IMPLEMENTATION</h2>
<h3 id="cpu-version">CPU-Version</h3>
<p>The code below show the version of code that can be executed in CPU</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">list_physical_devices</span><span class="p">(</span><span class="s">'CPU'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Selected CPU: </span><span class="si">{</span><span class="n">cpu</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">testcpu</span> <span class="o">=</span> <span class="s">"""
import tensorflow as tf
with tf.device('/cpu:0'):
random_image_cpu = tf.random.normal((100, 100, 100, 3))
net_cpu = tf.compat.v1.layers.conv2d(random_image_cpu, 32, 7)
net_cpu = tf.math.reduce_sum(net_cpu)
"""</span>
<span class="n">cpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testcpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images </span><span class="se">\n</span><span class="s">'</span>
<span class="sa">f</span><span class="s">'(batch x height x width x channel). Sum of ten runs: </span><span class="si">{</span><span class="n">cpu_time</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>While running on <a href="https://colab.research.google.com/notebooks">google colab</a> in CPU mode make sure the following
configuration</p>
<p><img src="https://amutheezan.com/images/CPU_Configuration.png" alt="image" /></p>
<p>And you can obtain the following outputs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Selected CPU: PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU')
Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images
(batch x height x width x channel). Sum of ten runs: 3.8407666499999777
</code></pre></div></div>
<h3 id="gpu-version">GPU-Version</h3>
<p>The code below show the version of code that can be executed in GPU</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">list_physical_devices</span><span class="p">(</span><span class="s">'GPU'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Selected GPU: </span><span class="si">{</span><span class="n">gpu</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">testgpu</span> <span class="o">=</span> <span class="s">"""
import tensorflow as tf
with tf.device('/device:GPU:0'):
random_image_gpu = tf.random.normal((100, 100, 100, 3))
net_gpu = tf.compat.v1.layers.conv2d(random_image_gpu, 32, 7)
net_gpu = tf.math.reduce_sum(net_gpu)
"""</span>
<span class="n">gpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testgpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images </span><span class="se">\n</span><span class="s">'</span>
<span class="sa">f</span><span class="s">'(batch x height x width x channel). Sum of ten runs. </span><span class="si">{</span><span class="n">gpu_time</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'GPU speedup over CPU: </span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">cpu_time</span><span class="o">/</span><span class="n">gpu_time</span><span class="p">)</span><span class="si">}</span><span class="s">x'</span><span class="p">)</span>
</code></pre></div></div>
<p>While running on google colab in GPU mode make sure the following configuration.</p>
<p><img src="https://amutheezan.com/images/GPU_Configuration.png" alt="image" /></p>
<p>And you can obtain the following outputs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Selected GPU: PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')
Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images
(batch x height x width x channel). Sum of ten runs. 0.056331392000004143
GPU speedup over CPU: 51x
</code></pre></div></div>
<h3 id="tpu-version">TPU-Version</h3>
<p>I was able to run the CPU version as well as GPU version, but TPU version doesn’t work. Following codes shows the
initial TPU version of code that doesn’t work, as mentioned in the tutorial,</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">tpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">list_physical_devices</span><span class="p">(</span><span class="s">'XLA_CPU'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Selected TPU: </span><span class="si">{</span><span class="n">tpu</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">testtpu</span> <span class="o">=</span> <span class="s">"""
import tensorflow as tf
with tf.device('/device:XLA_CPU:0'):
random_image_tpu = tf.random.normal((100, 100, 100, 3))
net_tpu = tf.compat.v1.layers.conv2d(random_image_tpu, 32, 7)
net_tpu = tf.math.reduce_sum(net_tpu)
"""</span>
<span class="n">tpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testtpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images </span><span class="se">\n</span><span class="s">'</span>
<span class="sa">f</span><span class="s">'(batch x height x width x channel). Sum of ten runs. </span><span class="si">{</span><span class="n">tpu_time</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'TPU speedup over CPU: </span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">cpu_time</span><span class="o">/</span><span class="n">tpu_time</span><span class="p">)</span><span class="si">}</span><span class="s">x'</span><span class="p">)</span>
</code></pre></div></div>
<p>And obtain the following error message</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">---------------------------------------------------------------------------</span>
<span class="nb">IndexError</span> <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
<span class="o"><</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">3</span><span class="o">-</span><span class="mi">77</span><span class="n">bc147ae849</span><span class="o">></span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span><span class="p">()</span>
<span class="o">----></span> <span class="mi">1</span> <span class="n">tpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">list_physical_devices</span><span class="p">(</span><span class="s">'XLA_CPU'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">2</span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Selected TPU: </span><span class="si">{</span><span class="n">tpu</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="mi">3</span>
<span class="mi">4</span> <span class="n">testtpu</span> <span class="o">=</span> <span class="s">"""
5 import tensorflow as tf
IndexError: list index out of range
</span></code></pre></div></div>
<p>To solve the TPU version, I go through the solution provided in
the <a href="https://heartbeat.fritz.ai/step-by-step-use-of-google-colab-free-tpu-75f8629492b3">2</a>, <a href="https://colab.research.google.com/notebooks/tpu.ipynb#scrollTo=FpvUOuC3j27n">3</a>
and fixed the issues.
Finally, the code below show the version of code that can be executed in TPU.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span><span class="p">:</span>
<span class="n">tpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">distribute</span><span class="p">.</span><span class="n">cluster_resolver</span><span class="p">.</span><span class="n">TPUClusterResolver</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Running on TPU '</span><span class="p">,</span> <span class="n">tpu</span><span class="p">.</span><span class="n">cluster_spec</span><span class="p">().</span><span class="n">as_dict</span><span class="p">()[</span><span class="s">'worker'</span><span class="p">])</span>
<span class="k">except</span> <span class="nb">ValueError</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">BaseException</span><span class="p">(</span><span class="s">'ERROR: Not connected to a TPU runtime; '</span>
<span class="s">'please see the previous cell in this notebook for instructions!'</span><span class="p">)</span>
<span class="n">testtpu</span> <span class="o">=</span> <span class="s">"""
import tensorflow as tf
with tf.device('/device:XLA_CPU:0'):
random_image_tpu = tf.random.normal((100, 100, 100, 3))
net_tpu = tf.compat.v1.layers.conv2d(random_image_tpu, 32, 7)
net_tpu = tf.math.reduce_sum(net_tpu)
"""</span>
<span class="n">tpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testtpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images '</span>
<span class="sa">f</span><span class="s">'(batch x height x width x channel). Sum of ten runs. </span><span class="si">{</span><span class="n">tpu_time</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'TPU speedup over CPU: </span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">cpu_time</span><span class="o">/</span><span class="n">tpu_time</span><span class="p">)</span><span class="si">}</span><span class="s">x'</span><span class="p">)</span>
</code></pre></div></div>
<p>While running on google colab in TPU mode make sure the following configuration is set as shown in the following image,</p>
<p><img src="https://amutheezan.com/images/TPU_Configuration.png" alt="image" /></p>
<p>And you can obtain the following outputs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Running on TPU ['10.61.126.18:8470']
Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images (batch x height x width x channel). Sum of ten runs. 3.5220498910000515
TPU speedup over CPU: 1x
</code></pre></div></div>
<h4 id="summary">Summary:</h4>
<p>Based on the results the CPU and TPU performs nearly same, but GPU performs more than <strong>50</strong> times than CPU and TPU</p>
<h2 id="a-basic-convolutional-neural-network-cnn-implementation">A Basic Convolutional Neural Network (CNN) Implementation</h2>
<p>The code below show the version of code that contain sample CNN network example.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="p">(</span><span class="n">x_train</span><span class="p">,</span> <span class="n">y_train</span><span class="p">),</span> <span class="p">(</span><span class="n">x_test</span><span class="p">,</span> <span class="n">y_test</span><span class="p">)</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">datasets</span><span class="p">.</span><span class="n">fashion_mnist</span><span class="p">.</span><span class="n">load_data</span><span class="p">()</span>
<span class="n">x_train</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">expand_dims</span><span class="p">(</span><span class="n">x_train</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">x_test</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">expand_dims</span><span class="p">(</span><span class="n">x_test</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">sss</span> <span class="o">=</span> <span class="n">StratifiedShuffleSplit</span><span class="p">(</span><span class="n">n_splits</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">test_size</span><span class="o">=</span><span class="mi">1</span> <span class="o">/</span> <span class="mi">6</span><span class="p">)</span>
<span class="n">train_index</span><span class="p">,</span> <span class="n">valid_index</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">sss</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="n">x_train</span><span class="p">,</span> <span class="n">y_train</span><span class="p">))</span>
<span class="n">x_valid</span><span class="p">,</span> <span class="n">y_valid</span> <span class="o">=</span> <span class="n">x_train</span><span class="p">[</span><span class="n">valid_index</span><span class="p">],</span> <span class="n">y_train</span><span class="p">[</span><span class="n">valid_index</span><span class="p">]</span>
<span class="n">x_train</span><span class="p">,</span> <span class="n">y_train</span> <span class="o">=</span> <span class="n">x_train</span><span class="p">[</span><span class="n">train_index</span><span class="p">],</span> <span class="n">y_train</span><span class="p">[</span><span class="n">train_index</span><span class="p">]</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">models</span><span class="p">.</span><span class="n">Sequential</span><span class="p">()</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">BatchNormalization</span><span class="p">(</span><span class="n">input_shape</span><span class="o">=</span><span class="n">x_train</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">:]))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Conv2D</span><span class="p">(</span><span class="mi">64</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="n">padding</span><span class="o">=</span><span class="s">'same'</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s">'elu'</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">MaxPooling2D</span><span class="p">(</span><span class="n">pool_size</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">strides</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.25</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">BatchNormalization</span><span class="p">(</span><span class="n">input_shape</span><span class="o">=</span><span class="n">x_train</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">:]))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Conv2D</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="n">padding</span><span class="o">=</span><span class="s">'same'</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s">'elu'</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">MaxPooling2D</span><span class="p">(</span><span class="n">pool_size</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.25</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">BatchNormalization</span><span class="p">(</span><span class="n">input_shape</span><span class="o">=</span><span class="n">x_train</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">:]))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Conv2D</span><span class="p">(</span><span class="mi">256</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="n">padding</span><span class="o">=</span><span class="s">'same'</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s">'elu'</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">MaxPooling2D</span><span class="p">(</span><span class="n">pool_size</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">strides</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.25</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Flatten</span><span class="p">())</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dense</span><span class="p">(</span><span class="mi">256</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Activation</span><span class="p">(</span><span class="s">'elu'</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.5</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Dense</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">layers</span><span class="p">.</span><span class="n">Activation</span><span class="p">(</span><span class="s">'softmax'</span><span class="p">))</span>
<span class="n">model</span><span class="p">.</span><span class="n">summary</span><span class="p">()</span>
<span class="n">model</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span>
<span class="n">optimizer</span><span class="o">=</span><span class="n">tf</span><span class="p">.</span><span class="n">optimizers</span><span class="p">.</span><span class="n">Adam</span><span class="p">(</span><span class="n">learning_rate</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">,</span> <span class="p">),</span>
<span class="n">loss</span><span class="o">=</span><span class="n">tf</span><span class="p">.</span><span class="n">keras</span><span class="p">.</span><span class="n">losses</span><span class="p">.</span><span class="n">sparse_categorical_crossentropy</span><span class="p">,</span>
<span class="n">metrics</span><span class="o">=</span><span class="p">[</span><span class="s">'sparse_categorical_accuracy'</span><span class="p">]</span>
<span class="p">)</span>
</code></pre></div></div>
<p>The code below show the version of code that can be executed in GPU</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">tensorflow</span> <span class="k">as</span> <span class="n">tf</span>
<span class="kn">import</span> <span class="nn">timeit</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="n">warnings</span><span class="p">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s">'ignore'</span><span class="p">)</span>
<span class="n">tf</span><span class="p">.</span><span class="n">get_logger</span><span class="p">().</span><span class="n">setLevel</span><span class="p">(</span><span class="s">'INFO'</span><span class="p">)</span>
<span class="n">gpus</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">list_physical_devices</span><span class="p">(</span><span class="s">'GPU'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Selected GPU: </span><span class="si">{</span><span class="n">gpu</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">tf</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">experimental</span><span class="p">.</span><span class="n">set_memory_growth</span><span class="p">(</span><span class="n">gpu</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
<span class="n">testgpu</span> <span class="o">=</span> <span class="s">"""
import os
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit
with tf.device('/device:GPU:0'):
<SAMPLE CNN CODE>
"""</span>
<span class="n">gpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testgpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'GPU time taken (seconds):'</span><span class="p">,</span> <span class="n">gpu_time</span><span class="p">)</span>
</code></pre></div></div>
<p>Same as previous section, while running on google colab in GPU mode make sure the following configuration is set as
shown already. And you can obtain the following outputs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')
GPU (s):
PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
batch_normalization (BatchNo (None, 28, 28, 1) 4
_________________________________________________________________
conv2d (Conv2D) (None, 28, 28, 64) 1664
_________________________________________________________________
.....
.....
.....
dense_18 (Dense) (None, 256) 590080
_________________________________________________________________
activation_18 (Activation) (None, 256) 0
_________________________________________________________________
dropout_39 (Dropout) (None, 256) 0
_________________________________________________________________
dense_19 (Dense) (None, 10) 2570
_________________________________________________________________
activation_19 (Activation) (None, 10) 0
=================================================================
Total params: 1,619,470
Trainable params: 1,619,084
Non-trainable params: 386
_________________________________________________________________
10.992455269000004
GPU time taken (seconds): 10.992455269000004
</code></pre></div></div>
<p>The code below show the version of code that can be executed in TPU</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">tensorflow</span> <span class="k">as</span> <span class="n">tf</span>
<span class="kn">import</span> <span class="nn">timeit</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="n">warnings</span><span class="p">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s">'ignore'</span><span class="p">)</span>
<span class="n">tf</span><span class="p">.</span><span class="n">get_logger</span><span class="p">().</span><span class="n">setLevel</span><span class="p">(</span><span class="s">'INFO'</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">tpu</span> <span class="o">=</span> <span class="n">tf</span><span class="p">.</span><span class="n">distribute</span><span class="p">.</span><span class="n">cluster_resolver</span><span class="p">.</span><span class="n">TPUClusterResolver</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Running on TPU '</span><span class="p">,</span> <span class="n">tpu</span><span class="p">.</span><span class="n">cluster_spec</span><span class="p">().</span><span class="n">as_dict</span><span class="p">()[</span><span class="s">'worker'</span><span class="p">])</span>
<span class="k">except</span> <span class="nb">ValueError</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">BaseException</span><span class="p">(</span><span class="s">'ERROR: Not connected to a TPU runtime; please see the previous cell in this notebook for instructions!'</span><span class="p">)</span>
<span class="n">testtpu</span> <span class="o">=</span> <span class="s">"""
import os
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit
with tf.device('/device:XLA_CPU:0'):
<SAMPLE CNN CODE>
"""</span>
<span class="n">tpu_time</span> <span class="o">=</span> <span class="n">timeit</span><span class="p">.</span><span class="n">timeit</span><span class="p">(</span><span class="n">testtpu</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'TPU time taken (seconds):'</span><span class="p">,</span> <span class="n">tpu_time</span><span class="p">)</span>
</code></pre></div></div>
<p>Again, same as previous section, while running on google colab in TPU mode make sure the following configuration as
previously. And you can obtain the following outputs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Running on TPU ['10.18.116.242:8470']
TPU (s):
<tensorflow.python.distribute.cluster_resolver.tpu.tpu_cluster_resolver.TPUClusterResolver object at 0x7f825f37b690>
Model: "sequential_23"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
batch_normalization_69 (Batc (None, 28, 28, 1) 4
_________________________________________________________________
conv2d_69 (Conv2D) (None, 28, 28, 64) 1664
.....
.....
.....
_________________________________________________________________
activation_64 (Activation) (None, 256) 0
_________________________________________________________________
dropout_131 (Dropout) (None, 256) 0
_________________________________________________________________
dense_65 (Dense) (None, 10) 2570
_________________________________________________________________
activation_65 (Activation) (None, 10) 0
=================================================================
Total params: 1,619,470
Trainable params: 1,619,084
Non-trainable params: 386
_________________________________________________________________
TPU time taken (seconds): 6.602945475999945
</code></pre></div></div>
<h4 id="summary-1">Summary:</h4>
<p>Based on the results TPU performs around <strong>1.5</strong> times better than GPU in-terms the computation time of the CNN sample
code.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://petamind.com/quick-benchmark-colab-cpu-gpu-tpu-xla-cpu/">https://petamind.com/quick-benchmark-colab-cpu-gpu-tpu-xla-cpu/</a></li>
<li><a href="https://heartbeat.fritz.ai/step-by-step-use-of-google-colab-free-tpu-75f8629492b3">https://heartbeat.fritz.ai/step-by-step-use-of-google-colab-free-tpu-75f8629492b3</a></li>
<li><a href="https://colab.research.google.com/notebooks/tpu.ipynb#scrollTo=FpvUOuC3j27n">https://colab.research.google.com/notebooks/tpu.ipynb#scrollTo=FpvUOuC3j27n</a></li>
</ol>Amutheezan SivagnanamI have implemented following simple comparison ofn performance on Google Colab CPU, GPU, and TPU as a part of an assignment for COSC 6385 course in University of Houston.Spectre Vulnerablity Simulation2021-03-31T00:00:00-04:002021-03-31T00:00:00-04:00https://amutheezan.com/computer%20architecture/spectre<p>In this post, I share some details on my extension to a simple simulation for the Spectre attack as part of the
assignment for <strong>COSC 6385</strong> course at the University of Houston.</p>
<h2 id="how-attack-works">How Attack Works</h2>
<p>Spectre attacks alters the branch prediction system. It can affect the branch prediction system by following two
scenarios.</p>
<ol>
<li>
<p>By mistraining the branch predictor. To achieve this the attacker executes a apparently innocent code designed to
confuse the system. Then, attacker executes a branch that will definitely mispredicted, and that will eventually jump
into the piece of code chosen by attacker. This piece of code also know and gadget, which can later steal the secret
data.</p>
</li>
<li>
<p>Through direct injection. When the sub parts of branch prediction system are shared among different programs and if
one is an attacking program, this attack can easily achieve using carefully chosen bad-data. When victim executes
their program either at the same time as the attacker or afterward, the victim will wind up using the predictor state
that was filled in by the attacker and unwittingly start to run the gadget. In this scenario victim program is
attacked by another program.</p>
</li>
</ol>
<h2 id="demo">Demo</h2>
<h3 id="environment-setup">Environment Setup</h3>
<ul>
<li>Oracle Virtual Box : Version 6.1.18 r142142 (Qt5.6.3)</li>
<li>Ubuntu 16.04.07 LTS</li>
<li>Kernel Version: 4.15.0-136-generic</li>
</ul>
<p>First I clone the <a href="https://github.com/flxwu/spectre-attack-demo">repository</a> and compile the file <code class="language-plaintext highlighter-rouge">spectre.c</code> using
following command,</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc spectre.c <span class="nt">-o</span> spectre
</code></pre></div></div>
<p>This will generate the executable file which will demonstrate the spectre attack. Then I execute the executable file
using the following command,</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./spectre
</code></pre></div></div>
<p>and I obtained following results.</p>
<p><img src="https://amutheezan.com/images/spectre_first.png" alt="image" /></p>
<p><img src="https://amutheezan.com/images/spectre_second.png" alt="image" /></p>
<p>As circled in the above figures the exploitation happen successfully and it able to read the secret contents.</p>
<p>Note: I didn’t face any issue while compiling or running the demo.</p>
<h2 id="how-to-fix">How to Fix</h2>
<h3 id="software">SOFTWARE</h3>
<p>For software level protection, we can uses the patches such as LLVM patch, MSVC and ARM speculation barrier header.
Further, some mitigation proposed by paper which disclose the spectre for the first time to public [1].
<br />(1). Inserting serializing instruction can helps on avoiding indirect branch poisoning.<br />
(2). By enabling strategies to prevent reading secret data, when performing speculative execution. <br />
(3). Intel tries to prevent the branch poisoning using microcode updates for some processors, which fall-back to the BTB
for the prediction, to disable this fall-back mechanism</p>
<h3 id="hardware">HARDWARE</h3>
<p>By tracking down whether the data was fetch as a result of speculative execution or not. And if it obtained from
speculative execution then prevent it using in subsequent execution, which might leak the information.</p>
<p>Note: Meltdown attack simulation can be found in the <a href="https://amutheezan.com/computer%20architecture/meltdown">post</a>.</p>
<h2 id="references">REFERENCES</h2>
<ol>
<li><a href="https://meltdownattack.com/spectre.pdf">Spectre Paper</a></li>
</ol>Amutheezan SivagnanamIn this post, I share some details on my extension to a simple simulation for the Spectre attack as part of the assignment for COSC 6385 course at the University of Houston.Meltdown Vvulnerability Ssimulation2021-03-30T00:00:00-04:002021-03-30T00:00:00-04:00https://amutheezan.com/computer%20architecture/meltdown<p>I have implemented a simple simulation for the Meltdown vulnerability as part of the assignment for <strong>COSC
6385</strong> course at the University of Houston.</p>
<h2 id="how-attack-works">How Attack Works</h2>
<p>Meltdown uses the race condition between memory access and privilege level checking while instruction is in processing.
Meltdown attacks allow access to the parts of memory used by the operating systems or other running processes or
recently used processes. Generally, one process is not permitted to access the memory of another running process. But in
a meltdown attack, one process tries to access other process contents. Operating system(OS) has a permission setting,
which will ensure that users are not allowed to access the kernel memory in user mode. And If a user tries to access the
memory from kernel address space, it will result in a page fault. But due to the speculative execution and the process
will execute some instruction ahead of page faulting instruction, they will roll back after the CPU has determined the
permission setting. But these executions are still available in the cache, and attackers use various OS functionalities
to dump these kinds of data from the cache. Based on this, the meltdown attack
works <a href="https://en.wikipedia.org/wiki/Kernel_page-table_isolation">1</a>,<a href="https://github.com/IAIK/meltdown/">2</a>,<a href="https://t.com/meltdow">3</a>.</p>
<h2 id="demonstration">Demonstration</h2>
<ul>
<li>Oracle Virtual Box : Version 6.1.18 r142142 (Qt5.6.3)</li>
<li>Ubuntu 14.04.06 LTS</li>
<li>Kernel Version: 4.4.0-142-generic</li>
</ul>
<p>I first clone the meltdown demo repository <a href="https://github.com/IAIK/meltdown/"></a> from GitHub and tried the following
demonstration presents in the repository.</p>
<h3 id="demonstrations-of-meltdown-attack">Demonstrations of Meltdown Attack</h3>
<ul>
<li>Demo #01 - A first test (<code class="language-plaintext highlighter-rouge">test</code>)</li>
<li>Demo #02 - Breaking KASLR (<code class="language-plaintext highlighter-rouge">kaslr</code>)</li>
<li>Demo #03 - Reliability test (<code class="language-plaintext highlighter-rouge">reliability</code>)</li>
<li>Demo #04 - Read physical memory (<code class="language-plaintext highlighter-rouge">physical_reader</code>)</li>
<li>Demo #05 - Dump the memory (<code class="language-plaintext highlighter-rouge">memdump</code>)</li>
</ul>
<h4 id="demo-01---a-first-test-test">Demo #01 - A first test (<code class="language-plaintext highlighter-rouge">test</code>)</h4>
<p>I have executed the basic test case for <code class="language-plaintext highlighter-rouge">meltdown</code> demos in this demo. I was able to get the same text in expect and
got places. I also tried to call the same command, and it returns random texts in each run. (randomization of text
happen based on the line 26 of <code class="language-plaintext highlighter-rouge">test.c</code></p>
<h5 id="commands">Commands</h5>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make<span class="p">;</span>
<span class="nb">sudo </span>taskset 0x1 ./test
</code></pre></div></div>
<h5 id="screenshot">Screenshot</h5>
<p><img src="https://amutheezan.com/images/test.png" alt="image" /></p>
<h4 id="demo-02---breaking-kaslr-kaslr">Demo #02 - Breaking KASLR (<code class="language-plaintext highlighter-rouge">kaslr</code>)</h4>
<p>This demo uses Meltdown to leak the secret randomization of the direct physical map. To get the offset quickly, we have
to execute the commands with admin privileges. Note that I have used Ubuntu 14.04, which has the kernel 4.4.0-142 as
disable <code class="language-plaintext highlighter-rouge">kaslr</code> by default.</p>
<h5 id="commands-1">Commands</h5>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make<span class="p">;</span>
<span class="nb">sudo </span>taskset 0x1 ./kaslr
</code></pre></div></div>
<h5 id="screenshot-1">Screenshot</h5>
<p><img src="https://amutheezan.com/images/kaslr.png" alt="image" /></p>
<h4 id="demo-03---reliability-test-reliability">Demo #03 - Reliability test (<code class="language-plaintext highlighter-rouge">reliability</code>)</h4>
<p>This demo tests how physical memory can be read. Note that I have used Ubuntu 14.04, which has kernel 4.4.0-142 as
disable <code class="language-plaintext highlighter-rouge">kaslr</code> by default. So I am technically not required to specify the offset value <code class="language-plaintext highlighter-rouge">0xffff8a6b80000000</code>.</p>
<h5 id="commands-2">Commands</h5>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make<span class="p">;</span>
<span class="nb">sudo </span>taskset 0x1 ./reliability 0xffff8a6b80000000
</code></pre></div></div>
<h5 id="screenshot-2">Screenshot</h5>
<p><img src="https://amutheezan.com/images/reliability.png" alt="image" /></p>
<h5 id="issues-aced">Issues aced</h5>
<p>Unlike the demonstration shown in the GitHub repository <a href="https://github.com/IAIK/meltdown/">2</a>, I am unable to get
higher reliability, and always I get reliability less than 1\%. I also tried similar commands
with <a href="\footnote{http://old-releases.ubuntu.com/releases/14.10/">Ubuntu 14.10</a> [<code class="language-plaintext highlighter-rouge">ubuntu-14.10-desktop-amd64.iso Last Modified: 2014-10-22 19:43</code>],
but I faced the same issues in there as well.</p>
<h4 id="demo-04---read-physical-memory-physical_reader">Demo #04 - Read physical memory (<code class="language-plaintext highlighter-rouge">physical_reader</code>)</h4>
<p>This demo reads memory from another process by directly reading physical memory. This demo contains two steps,</p>
<h5 id="steps-and-commands">Steps and Commands</h5>
<ul>
<li>call <code class="language-plaintext highlighter-rouge">secret</code> with admin privileges and this will return the physical address of the test.</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo</span> ./secret
</code></pre></div></div>
<ul>
<li>call <code class="language-plaintext highlighter-rouge">physical_reader</code> with the specified physical address of secret text and offset.</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> make<span class="p">;</span>
<span class="nb">sudo </span>taskset 0x1 ./physical_reader 0xcc26cac8 0xffff8a6b80000000
</code></pre></div></div>
<p>I have used Ubuntu 14.04, which has kernel 4.4.0-142 as disable kaslr by default. If kaslr is disabled, we can skip
providing the offset parameter. So I don’t need to provide the offset value <code class="language-plaintext highlighter-rouge">0xffff8a6b80000000</code>.</p>
<h5 id="screenshots">Screenshots</h5>
<p><img src="https://amutheezan.com/images/physical_reader_part_1.png" alt="image" />
<img src="https://amutheezan.com/images/physical_reader_part_2.png" alt="image" /></p>
<h5 id="issues-faced">Issues Faced</h5>
<p>Unlike the demonstration shown in the GitHub repository <a href="https://github.com/IAIK/\cite{meltdown/">2</a>, I am unable to get
contents of secret. I also tried similar commands with Ubuntu 14.10, but I faced the same issues there as well.</p>
<h4 id="demo-05---dump-the-memory-memdump">Demo #05 - Dump the memory (<code class="language-plaintext highlighter-rouge">memdump</code>)</h4>
<p>This demo dumps the content of the memory. I set the memory size to 8GB as RAM for the virtual box. This demo contains
two steps,</p>
<h5 id="steps-and-commands-1">Steps and Commands</h5>
<ul>
<li>call <code class="language-plaintext highlighter-rouge">memory_filler</code> with memory value specified to fill the memory.</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo</span> ./memory_filler 9
</code></pre></div></div>
<ul>
<li>call <code class="language-plaintext highlighter-rouge">memdump</code> to read the contents from memory.</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> make<span class="p">;</span>
taskset 0x1 ./memdump 0x240000000 <span class="nt">-1</span> 0xffff8a6b80000000
</code></pre></div></div>
<h5 id="issues-faced-1">Issues Faced</h5>
<p>Unlike the demonstration shown in the GitHub repository <a href="https://github.com/IAIK/\cite{meltdown/">2</a>, }, I am unable to
get any meaningful human-readable data. I also tried similar commands with Ubuntu 14.10, but I faced the same issues
there as well.</p>
<h5 id="screenshots-1">Screenshots</h5>
<p><img src="https://amutheezan.com/images/memdump_part_1.png" alt="image" />
<img src="https://amutheezan.com/images/memdump_part_2.png" alt="image" /></p>
<h2 id="how-to-fix">How to Fix</h2>
<h3 id="software">Software</h3>
<p>For software level protection, we can use patches for Linux, Windows, and OS X.
Kernel page-table isolation (KPTI) (earlier referenced as KAISER) is a Linux kernel feature that protect the system from
the Meltdown security vulnerability affecting mainly Intel’s X86 CPU. It improves the kernel hardening against attempts
to bypass the KSLR [1,2].</p>
<h3 id="hardware">Hardware</h3>
<p>For hardware level protection, we have to introduce a hard split between the user space and the kernel space. This can
be enabled optionally by modern kernels using the newly introduce hard-split bit in the CPU control register (e.g. CR4).
By setting the control bit the user space and kernel space can resides in different areas of address. This hard-split
can determine whether a memory fetch violates security boundary with the help virtual address.</p>
<p>Note: Spectre attack simulation can be found in the <a href="https://amutheezan.com/computer%20architecture/spectre/">post</a>.</p>
<h2 id="references">REFERENCES</h2>
<ol>
<li><a href="https://en.wikipedia.org/wiki/Kernel_page-table_isolation">https://en.wikipedia.org/wiki/Kernel_page-table_isolation</a></li>
<li><a href="https://github.com/IAIK/meltdown/">https://github.com/IAIK/meltdown/</a></li>
<li><a href="https://meltdownattack.com/meltdown.pdf">Meltdown Paper</a></li>
</ol>Amutheezan SivagnanamI have implemented a simple simulation for the Meltdown vulnerability as part of the assignment for COSC 6385 course at the University of Houston.