Skip to content

Commit

Permalink
Improved log_active preprocessor for wait statements.
Browse files Browse the repository at this point in the history
  • Loading branch information
LarsAsplund committed Feb 11, 2023
1 parent 04633b5 commit e113d0f
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 31 deletions.
5 changes: 4 additions & 1 deletion docs/blog/2022_09_20_vunit_events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,10 @@ use this example as a template for your own project.
.. raw:: html
:file: img/vunit_events/wait_statement_preprocessor.html

The preprocessor is added to the project using the :meth:`~vunit.ui.VUnit.add_preprocessor` method. The order number must be higher than that of the location preprocessor which is 1000 by default. This is to avoid unintended interference between the two.
The preprocessor is added to the project using the :meth:`~vunit.ui.VUnit.add_preprocessor` method. By setting the
order number lower than that of the location preprocessor (which has a default value of 100), the ``log_active``
function is inserted first, allowing the location preprocessor to accurately pinpoint the source of the statement.


.. raw:: html
:file: img/vunit_events/add_preprocessor.html
Expand Down
4 changes: 2 additions & 2 deletions docs/blog/img/vunit_events/add_preprocessor.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="highlight"><pre><span></span><span class="n">vu</span> <span class="o">=</span> <span class="n">VUnit</span><span class="o">.</span><span class="n">from_argv</span><span class="p">()</span>
<span class="n">vu</span><span class="o">.</span><span class="n">enable_location_preprocessing</span><span class="p">()</span> <span class="c1"># order = 1000 if no other value is provided</span>
<span class="n">vu</span><span class="o">.</span><span class="n">add_preprocessor</span><span class="p">(</span><span class="n">WaitStatementPreprocessor</span><span class="p">(</span><span class="n">order</span><span class="o">=</span><span class="mi">1001</span><span class="p">))</span>
<span class="n">vu</span><span class="o">.</span><span class="n">enable_location_preprocessing</span><span class="p">()</span> <span class="c1"># order = 100 if no other value is provided</span>
<span class="n">vu</span><span class="o">.</span><span class="n">add_preprocessor</span><span class="p">(</span><span class="n">WaitStatementPreprocessor</span><span class="p">(</span><span class="n">order</span><span class="o">=</span><span class="mi">99</span><span class="p">))</span>
</pre></div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="highlight" style="background: #002b36; color: #eee8d5;"><pre style="line-height: 125%; background: #002b36; color: #eee8d5;"><span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">vunit_lib</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">event_pkg</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Event vunit_lib:vunit_error activated while waiting on "wait until is_active(new_data_set);"
<div class="highlight" style="background: #002b36; color: #eee8d5;"><pre style="line-height: 125%; background: #002b36; color: #eee8d5;"><span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">vunit_lib</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">event_pkg</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Event vunit_lib:vunit_error activated while waiting on "wait until is_active(new_data_set);" (tb_event.vhd:417)
<span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">check</span> - <span style="font_weight: bold; color: #cb4b16; ">ERROR</span> - Equality check failed for #processed samples - Got 0000_0101 (5). Expected 10 (0000_1010). (tb_event.vhd:265)
</pre></div>
2 changes: 1 addition & 1 deletion docs/blog/img/vunit_events/log_with_core_dump.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="highlight" style="background: #002b36; color: #eee8d5;"><pre style="line-height: 125%; background: #002b36; color: #eee8d5;"><span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">vunit_lib</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">event_pkg</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Event vunit_lib:vunit_error activated while waiting on "wait until is_active(new_data_set);"
<div class="highlight" style="background: #002b36; color: #eee8d5;"><pre style="line-height: 125%; background: #002b36; color: #eee8d5;"><span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">vunit_lib</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">event_pkg</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Event vunit_lib:vunit_error activated while waiting on "wait until is_active(new_data_set);" (tb_event.vhd:417)
<span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">incrementer</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">core_dump</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Control state is idle (incrementer.vhd:180)
<span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">incrementer</span><span style="font_weight: bold; color: #2aa198; ">:</span><span style="font_weight: bold; color: #eee8d5; ">core_dump</span> - <span style="font_weight: bold; color: #eee8d5; ">INFO</span> - Data processing state is idle (incrementer.vhd:181)
<span style="color: #2aa198; ">178000000 fs</span> - <span style="font_weight: bold; color: #eee8d5; ">check</span> - <span style="font_weight: bold; color: #cb4b16; ">ERROR</span> - Equality check failed for #processed samples - Got 0000_0101 (5). Expected 10 (0000_1010). (tb_event.vhd:265)
Expand Down
35 changes: 29 additions & 6 deletions docs/blog/img/vunit_events/wait_statement_preprocessor.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

<span class="c1"># Regular expression finding wait statements on the form</span>
<span class="c1"># wait [on sensitivity_list] [until condition] [for timeout];</span>
<span class="c1"># Any preceding text (prefix) is also picked-up. It will be examined later to exclude some special cases.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_wait_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
<span class="sa">r</span><span class="s2">&quot;wait(\s+on\s+(?P&lt;sensitivity_list&gt;.*?))?(\s+until\s+(?P&lt;condition&gt;.*?))?(\s+for\s+(?P&lt;timeout&gt;.*?))?;&quot;</span><span class="p">,</span>
<span class="sa">r</span><span class="s2">&quot;(?P&lt;prefix&gt;^[^\r\n]*?)(?P&lt;wait&gt;wait)(\s+on\s+(?P&lt;sensitivity_list&gt;.*?))?(\s+until\s+(?P&lt;condition&gt;.*?))?(\s+for\s+(?P&lt;timeout&gt;.*?))?;&quot;</span><span class="p">,</span>
<span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">DOTALL</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">IGNORECASE</span><span class="p">,</span>
<span class="p">)</span>

Expand All @@ -30,24 +31,46 @@
<span class="n">wait_statements</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">wait_statement</span><span class="p">:</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">start</span><span class="p">(),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

<span class="k">for</span> <span class="n">wait_statement</span> <span class="ow">in</span> <span class="n">wait_statements</span><span class="p">:</span>
<span class="n">prefix</span> <span class="o">=</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;prefix&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">prefix</span><span class="p">:</span>
<span class="c1"># Ignore commented statements wait looking statements in strings (not foolproof)</span>
<span class="k">if</span> <span class="p">(</span><span class="s2">&quot;--&quot;</span> <span class="ow">in</span> <span class="n">prefix</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="s1">&#39;&quot;&#39;</span> <span class="ow">in</span> <span class="n">prefix</span><span class="p">):</span>
<span class="k">continue</span>
<span class="c1"># Remove any preceding statements but keep labels</span>
<span class="n">prefix</span> <span class="o">=</span> <span class="n">prefix</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;;&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">()</span>

<span class="n">modified_wait_statement</span> <span class="o">=</span> <span class="s2">&quot;wait&quot;</span>

<span class="c1"># If the wait statement has an explicit sensitivity list (on ...), then vunit_error must be added to that</span>
<span class="n">sensitivity_list</span> <span class="o">=</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;sensitivity_list&quot;</span><span class="p">)</span>
<span class="n">sensitivity_list_signals</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">sensitivity_list</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">new_sensitivity_list</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">sensitivity_list</span><span class="si">}</span><span class="s2">, vunit_error&quot;</span>
<span class="n">sensitivity_list_signals</span> <span class="o">=</span> <span class="p">[</span><span class="n">signal</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">signal</span> <span class="ow">in</span> <span class="n">sensitivity_list</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)]</span>
<span class="n">new_sensitivity_list</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sensitivity_list_signals</span><span class="p">)</span><span class="si">}</span><span class="s2">, vunit_error&quot;</span>
<span class="n">modified_wait_statement</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">&quot; on </span><span class="si">{</span><span class="n">new_sensitivity_list</span><span class="si">}</span><span class="s2">&quot;</span>

<span class="c1"># Add log_active to an existing condition clause (until ...) or create one if not present</span>
<span class="n">original_wait_statement</span> <span class="o">=</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">original_wait_statement</span> <span class="o">=</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)[</span><span class="n">wait_statement</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="s2">&quot;wait&quot;</span><span class="p">)</span> <span class="o">-</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> <span class="p">:]</span>
<span class="n">log_message</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;decorate(&quot;while waiting on &quot;&quot;</span><span class="si">{</span><span class="n">original_wait_statement</span><span class="si">}</span><span class="s1">&quot;&quot;&quot;)&#39;</span>
<span class="c1"># The location preprocessor will not detect that the code in the message is quoted and it will modify</span>
<span class="c1"># any function it targets. is_active_msg is such a function but by appending a non-printable character</span>
<span class="c1"># to that function name we avoid this problem without altering the logged message</span>
<span class="n">log_message</span> <span class="o">=</span> <span class="n">log_message</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;is_active_msg&quot;</span><span class="p">,</span> <span class="s1">&#39;is_active_msg&quot; &amp; NUL &amp; &quot;&#39;</span><span class="p">)</span>
<span class="n">condition</span> <span class="o">=</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;condition&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">condition</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">new_condition</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;log_active(vunit_error, </span><span class="si">{</span><span class="n">log_message</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="c1"># If there was a sensitivity list the VHDL event attribute of those signals must be in the</span>
<span class="c1"># condition or the wait statement will remain blocked on those VHDL events (log_active always</span>
<span class="c1"># returns false).</span>
<span class="n">new_condition</span> <span class="o">=</span> <span class="s2">&quot; or &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">signal</span><span class="si">}</span><span class="s2">&#39;event&quot;</span> <span class="k">for</span> <span class="n">signal</span> <span class="ow">in</span> <span class="n">sensitivity_list_signals</span><span class="p">])</span>
<span class="n">new_condition</span> <span class="o">=</span> <span class="n">new_condition</span> <span class="o">+</span> <span class="s2">&quot; or &quot;</span> <span class="k">if</span> <span class="n">new_condition</span> <span class="k">else</span> <span class="n">new_condition</span>
<span class="n">new_condition</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">&quot;log_active(vunit_error, </span><span class="si">{</span><span class="n">log_message</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="k">elif</span> <span class="s2">&quot;vunit_error&quot;</span> <span class="ow">in</span> <span class="n">condition</span><span class="p">:</span>
<span class="k">continue</span> <span class="c1"># Don&#39;t touch a wait statement already triggering on vunit_error</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">new_condition</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;(</span><span class="si">{</span><span class="n">condition</span><span class="si">}</span><span class="s2">) or log_active(vunit_error, </span><span class="si">{</span><span class="n">log_message</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="c1"># The condition_operator function turns the original condition to a boolean that can be ORed</span>
<span class="c1"># with the boolean log_active function. Using the condition operator (??) doesn&#39;t work since it can&#39;t</span>
<span class="c1"># be applied to a condition that was already a boolean</span>
<span class="n">new_condition</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;condition_operator(</span><span class="si">{</span><span class="n">condition</span><span class="si">}</span><span class="s2">) or log_active(vunit_error, </span><span class="si">{</span><span class="n">log_message</span><span class="si">}</span><span class="s2">)&quot;</span>

<span class="n">modified_wait_statement</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">&quot; until </span><span class="si">{</span><span class="n">new_condition</span><span class="si">}</span><span class="s2">&quot;</span>

Expand All @@ -59,7 +82,7 @@
<span class="n">modified_wait_statement</span> <span class="o">+=</span> <span class="s2">&quot;;&quot;</span>

<span class="c1"># Replace original wait statement</span>
<span class="n">code</span> <span class="o">=</span> <span class="n">code</span><span class="p">[:</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">start</span><span class="p">()]</span> <span class="o">+</span> <span class="n">modified_wait_statement</span> <span class="o">+</span> <span class="n">code</span><span class="p">[</span><span class="n">wait_statement</span><span class="o">.</span><span class="n">end</span><span class="p">()</span> <span class="p">:]</span>
<span class="n">code</span> <span class="o">=</span> <span class="n">code</span><span class="p">[:</span> <span class="n">wait_statement</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="s2">&quot;wait&quot;</span><span class="p">)]</span> <span class="o">+</span> <span class="n">modified_wait_statement</span> <span class="o">+</span> <span class="n">code</span><span class="p">[</span><span class="n">wait_statement</span><span class="o">.</span><span class="n">end</span><span class="p">()</span> <span class="p">:]</span>

<span class="k">return</span> <span class="n">code</span>
</pre></div>
Loading

0 comments on commit e113d0f

Please sign in to comment.