<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.4">Jekyll</generator><link href="https://www.five-embeddev.com//feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.five-embeddev.com//" rel="alternate" type="text/html" /><updated>2025-05-01T13:22:52+00:00</updated><id>https://www.five-embeddev.com//feed.xml</id><title type="html">Five EmbedDev</title><subtitle>Embedded Systems Developer RISC-V Blog</subtitle><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><entry><title type="html">Building a header-only C++20 coroutine runtime for bare-metal RISC-V</title><link href="https://www.five-embeddev.com//articles/2024/11/24/part-1-cpp20-coroutines-runtime/" rel="alternate" type="text/html" title="Building a header-only C++20 coroutine runtime for bare-metal RISC-V" /><published>2024-11-24T00:00:00+00:00</published><updated>2024-11-24T00:00:00+00:00</updated><id>https://www.five-embeddev.com//articles/2024/11/24/part-1-cpp20-coroutines-runtime</id><content type="html" xml:base="https://www.five-embeddev.com//articles/2024/11/24/part-1-cpp20-coroutines-runtime/">&lt;h2 id=&quot;creating-the-coroutines-runtime-infrastructure&quot;&gt;Creating the coroutines runtime infrastructure&lt;/h2&gt;

&lt;p&gt;A simple coroutine example was presented in &lt;a href=&quot;/articles/2024/11/24/part-2-cpp20-coroutines-short/&quot;&gt;“C++20 coroutines, header only, without an OS”&lt;/a&gt;. This post describes the runtime used for that example in detail.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/cpp-coro-amos-book-crop.jpg&quot; alt=&quot;Project X&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This story is also published on &lt;a href=&quot;https://philmulholland.medium.com/c-20-coroutines-a-header-only-runtime-for-re-entrant-tasks-87cb8e2c0ee1&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;summary-of-the-runtime-files&quot;&gt;Summary of the runtime files&lt;/h3&gt;

&lt;p&gt;The runtime for this example is a set of include files in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;include/coro&lt;/code&gt;&lt;/a&gt;. These files are used:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/nop_task.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;nop_task.hpp&lt;/code&gt;&lt;/a&gt; : Task structure including &lt;code class=&quot;highlighter-rouge&quot;&gt;promise_type&lt;/code&gt; to conform the C++ coroutines task concept.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/scheduler.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler.hpp&lt;/code&gt;&lt;/a&gt; : Generic scheduler class that can manage a set of &lt;code class=&quot;highlighter-rouge&quot;&gt;std::coroutine_handle&lt;/code&gt; to determine when they should resume and implement the resumption.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/awaitable_timer.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_timer.hpp&lt;/code&gt;&lt;/a&gt; : An “awaitable” class that can be used with &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt; to schedule a coroutines to wake up after a given &lt;code class=&quot;highlighter-rouge&quot;&gt;std::chono&lt;/code&gt; delay.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/static_list.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;static_list.hpp&lt;/code&gt;&lt;/a&gt;: An alternative to &lt;code class=&quot;highlighter-rouge&quot;&gt;std::list&lt;/code&gt; that uses custom memory allocation from a static region to avoid heap usage.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/awaitable_priority.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_priority.hpp&lt;/code&gt;&lt;/a&gt;: An alternative “awaitable” class for tasks to be scheduled to wake according to priority.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All classes here are designed to not use the heap for allocation. They will allocate all memory from statically declared buffers.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;the-coroutine-task-concept&quot;&gt;The coroutine task concept&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;nop_task&lt;/code&gt; class in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/nop_task.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;nop_task.hpp&lt;/code&gt;&lt;/a&gt; file implements the coroutine task concept.&lt;/p&gt;

&lt;p&gt;A coroutine task includes a promise concept with no return values. The important structures in this file are&lt;code class=&quot;highlighter-rouge&quot;&gt;struct nop_task&lt;/code&gt; / &lt;code class=&quot;highlighter-rouge&quot;&gt;struct nop_task::promise_type&lt;/code&gt;. This is implemented as described in &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/coroutines&quot;&gt;CPP Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This task structure will be allocated each time a coroutine is called. To avoid heap allocation static memory allocation is used (to be described below). When using a memory constrained platform it is important to understand that the number of coroutines that can be called is restricted by the memory allocated for &lt;code class=&quot;highlighter-rouge&quot;&gt;nop_task::task_heap_&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The relationships between the task classes is shown in the following class diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/nop_task.svg&quot; alt=&quot;Task&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-awaitable-concept&quot;&gt;The awaitable concept&lt;/h3&gt;

&lt;p&gt;The classes in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/awaitable_timer.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_timer.hpp&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/awaitable_priority.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_priority.hpp&lt;/code&gt;&lt;/a&gt; represent asynchronous events that pause the coroutine task until an event occurs.&lt;/p&gt;

&lt;p&gt;These classes are designed to be returned from a &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt;, this ensures a task can be scheduled to be resumed on a later event.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_timer&lt;/code&gt; class implements the awaitable concept described in &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/coroutines&quot;&gt;CPP Reference&lt;/a&gt;, and also the &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt; operator that is overloaded to take the &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler_delay&lt;/code&gt; struct and return &lt;code class=&quot;highlighter-rouge&quot;&gt;awaitable_timer&lt;/code&gt;. An additional concept of the &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler&lt;/code&gt; class is being used to manage the coroutine handle and wake up conditions that are used to implement coroutine task pause.&lt;/p&gt;

&lt;p&gt;The relationships between the awaitable classes is shown in the following class diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/awaitable.svg&quot; alt=&quot;Awaitable&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-scheduler-class&quot;&gt;The scheduler class&lt;/h3&gt;

&lt;p&gt;The classes in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/include/coro/scheduler.hpp&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler.hpp&lt;/code&gt;&lt;/a&gt; are designed to do the work of managing the coroutines that are paused. It is a template class, parameterized according to the type of event that should be scheduled, and the maximum number of concurrent active tasks.&lt;/p&gt;

&lt;p&gt;The scheduler does the work that would be done by an RTOS or General Purpose OS. It manages a task list of waiting tasks with wake conditions and resumes them on the wake event.&lt;/p&gt;

&lt;p&gt;The awaitable classes, introduced above, will insert paused tasks via &lt;code class=&quot;highlighter-rouge&quot;&gt;insert()&lt;/code&gt;. The active execution context must call &lt;code class=&quot;highlighter-rouge&quot;&gt;resume()&lt;/code&gt; to resume the paused tasks. Each entry in the task list is a &lt;code class=&quot;highlighter-rouge&quot;&gt;schedule_entry&lt;/code&gt; structure. The classe are templates specialized by the wake up condition.&lt;/p&gt;

&lt;p&gt;This scheduler class is not a concept required by C++ coroutines, but in this example it is needed as there is no operating system scheduler.&lt;/p&gt;

&lt;p&gt;The relationships between scheduler classes is shown in the following class diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/scheduler.svg&quot; alt=&quot;Software Timer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;using-the-awaitable-and-scheduler-classes-to-create-a-software-timer&quot;&gt;Using the awaitable and scheduler classes to create a software timer&lt;/h3&gt;

&lt;p&gt;The awaitable class and scheduler are combined to implement the software timer feature. The following diagram shows how the classes relate.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/software_timer.svg&quot; alt=&quot;Software Timer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;walk-through-of-the-detailed-sequence-of-suspend-and-resume&quot;&gt;Walk through of the detailed sequence of suspend and resume&lt;/h3&gt;

&lt;p&gt;Now the concrete classes have been defined, the sequence to suspend and resume a coroutine class can be show.&lt;/p&gt;

&lt;p&gt;It is shown below in 3 stages in relation to the simple timer example.&lt;/p&gt;

&lt;h4 id=&quot;1-setup-a-coroutine-and-suspend-on-the-first-wait&quot;&gt;1. Setup a coroutine, and suspend on the first wait.&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/task_sequence.svg&quot; alt=&quot;Task Sequence&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;2-resume-and-suspend-iterate-over-several-time-delays&quot;&gt;2. Resume and suspend, iterate over several time delays.&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/task_sequence_001.svg&quot; alt=&quot;Task Sequence&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;3-complete-iterating-and-exit-coroutines&quot;&gt;3. Complete iterating and exit coroutines.&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/task_sequence_002.svg&quot; alt=&quot;Task Sequence&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;

&lt;p&gt;The runtime has some basic unit testing implemented in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/test&quot;&gt;test&lt;/a&gt; using the &lt;a href=&quot;https://www.throwtheswitch.org/unity&quot;&gt;unity&lt;/a&gt; test framework.  The tests are not comprehensive, but run independent of hardware as the runtime is host &amp;amp; OS independent.  The tests are compiled for the host OS and run locally.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The runtime presented in this article is not meant for production usage and has the bare minimal functionality to implement a re-entrant function using a software timer.&lt;/p&gt;

&lt;p&gt;However, it does show the potential of C++ coroutines to be applied to real time applications that are portable across different OS and target architectures.&lt;/p&gt;

&lt;h2 id=&quot;appendix&quot;&gt;Appendix&lt;/h2&gt;

&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;

&lt;p&gt;I won’t explain the details of C++ coroutines, there are much better resources. I used the following to understand coroutines:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://lewissbaker.github.io/2020/05/11/understanding_symmetric_transfer&quot;&gt;Lewis Baker’s “C++ coroutines: Understanding Symmetric-Transfer” -&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://godbolt.org/z/-Kw6Nf&quot;&gt;Lewis Baker’s “C++ coroutines: Understanding Symmetric-Transfer” - the code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/lewissbaker/cppcoro&quot;&gt;CPPcoro library, has not been updated for gcc support - however the documentation is great!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;&quot;&gt;The folly library has an updated coro from Lewis Baker&lt;/a&gt;, and &lt;a href=&quot;https://blog.the-pans.com/build-folly-coro/&quot;&gt;some info on enabling coroutines &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20210504-01/?p=105178&quot;&gt;Raymond Chen’s explanations, and demonstration of legacy callback integration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mariusbancila.ro/blog/2020/06/22/a-cpp20-coroutine-example/&quot;&gt;Some nice examples here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/language/coroutines&quot;&gt;CPP Reference is incomplete, but a start&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;a-few-implementation-details&quot;&gt;A Few implementation details&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Tasks are created at the first call to an asynchronous routine. The allocated task data structure is minimal.&lt;/li&gt;
  &lt;li&gt;Tasks do not have a dedicated stack, they will be restored to the stack where they are woken.&lt;/li&gt;
  &lt;li&gt;Context switching stack management is implemented by the compiler, no custom assembler routines are needed (such as &lt;a href=&quot;https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/4d4f8d0d50bedc37e1d07c96aded7d2bc20f0d6c/portable/GCC/RISC-V/portASM.S&quot;&gt;portASM.s in FreeRTOS&lt;/a&gt;). This is possible as there is no pre-emptive context switching.&lt;/li&gt;
  &lt;li&gt;The scheduler can be made a C++ object, and context switching can be controlled programmatically..&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="C++" /><category term="baremetal" /><category term="coroutines" /><summary type="html">Creating the coroutines runtime infrastructure A simple coroutine example was presented in “C++20 coroutines, header only, without an OS”. This post describes the runtime used for that example in detail. This story is also published on Medium. Summary of the runtime files The runtime for this example is a set of include files in include/coro. These files are used: nop_task.hpp : Task structure including promise_type to conform the C++ coroutines task concept. scheduler.hpp : Generic scheduler class that can manage a set of std::coroutine_handle to determine when they should resume and implement the resumption. awaitable_timer.hpp : An “awaitable” class that can be used with co_await to schedule a coroutines to wake up after a given std::chono delay. static_list.hpp: An alternative to std::list that uses custom memory allocation from a static region to avoid heap usage. awaitable_priority.hpp: An alternative “awaitable” class for tasks to be scheduled to wake according to priority. NOTE: All classes here are designed to not use the heap for allocation. They will allocate all memory from statically declared buffers.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">Exploring C++20 coroutines for embedded and bare-metal development on RISC-V platforms</title><link href="https://www.five-embeddev.com//articles/2024/11/24/part-2-cpp20-coroutines-short/" rel="alternate" type="text/html" title="Exploring C++20 coroutines for embedded and bare-metal development on RISC-V platforms" /><published>2024-11-24T00:00:00+00:00</published><updated>2024-11-24T00:00:00+00:00</updated><id>https://www.five-embeddev.com//articles/2024/11/24/part-2-cpp20-coroutines-short</id><content type="html" xml:base="https://www.five-embeddev.com//articles/2024/11/24/part-2-cpp20-coroutines-short/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This post is about using C++ coroutines to suspend and resume functions in real time. The objective is a simple way of building real time tasks using only C++, without the need for an RTOS or operating system kernel.&lt;/p&gt;

&lt;p&gt;Coroutines are functions that can be suspended and resumed, using the keywords &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/coroutines&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;co_yield&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;co_return&lt;/code&gt;&lt;/a&gt;. The C++20 standard introduced coroutines to the language.&lt;/p&gt;

&lt;p&gt;C++ standardized the keywords and type concepts for coroutines, but it did not standardize a
 runtime&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The lack of a standard runtime has made them hard to use them “out of the box”, but the implementation of coroutines is very adaptable to different use cases.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/cpp-coro-project-x-sm.jpg&quot; alt=&quot;Project X&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here I use a simple runtime implementing C++20
coroutines on bare metal (no operating system) for RISC-V, using the
&lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt; keyword. This is done by passing the real time scheduler and resume time condition as the argument to the asynchronous wait operator.&lt;/p&gt;

&lt;p&gt;The runtime is described in detail in &lt;a href=&quot;/articles/2024/11/24/part-1-cpp20-coroutines-runtime/&quot;&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This story is also published on &lt;a href=&quot;https://philmulholland.medium.com/c-20-coroutines-re-entrant-scheduled-tasks-no-os-required-061c20efafad&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;why-coroutines&quot;&gt;Why coroutines?&lt;/h2&gt;

&lt;p&gt;I’m interested in coroutines for the follow benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Event driven asynchronous functions can be written using a control/data flow in a single body of code that can be easy to understand.&lt;/li&gt;
  &lt;li&gt;Code is portable so that the same code can be tested on development OS and target systems.&lt;/li&gt;
  &lt;li&gt;Resource efficiency, in terms of memory usage (stack and heap) and CPU cycle usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-software-timer-example&quot;&gt;A software timer example&lt;/h2&gt;

&lt;p&gt;This article will build a simple software timer example. The function has a loop that pauses for several micro seconds before iterating again. While the loop is paused the control flow returns to the caller function.&lt;/p&gt;

&lt;h3 id=&quot;a-simple-coroutines-task&quot;&gt;A simple coroutines task&lt;/h3&gt;

&lt;p&gt;A simple task &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic&lt;/code&gt; is defined in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/src/example_simple.cpp#L30&quot;&gt;example_simple.cpp&lt;/a&gt;.
It takes &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;period&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;resume_count&lt;/code&gt; as arguments and asynchronously waits &lt;code class=&quot;highlighter-rouge&quot;&gt;period&lt;/code&gt; microseconds for 10 iterations, updating the &lt;code class=&quot;highlighter-rouge&quot;&gt;resume_count&lt;/code&gt; value each iteration.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler&lt;/code&gt; passed as an argument is not strictly necessary for C++ coroutines, but is used to make the ownership of the context of each task explicit. (It could be possible to use a global scheduler, such as when implementing via OS threads.)&lt;/p&gt;

&lt;p&gt;The task returns &lt;code class=&quot;highlighter-rouge&quot;&gt;nop_task&lt;/code&gt;. This is a special structure that is linked to the coroutines implementation. In this case a “nop task” refers to a task that does not return a value via &lt;code class=&quot;highlighter-rouge&quot;&gt;co_return&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCHEDULER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;nop_task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;periodic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SCHEDULER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chrono&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;microseconds&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;period&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resume_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mtimer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;co_await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduled_delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;period&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp_resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resume_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mtimer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer_ticks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;resume_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;co_return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Not strictly needed&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The function has the following behavior:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Take &lt;code class=&quot;highlighter-rouge&quot;&gt;period&lt;/code&gt; as a parameter in microseconds.&lt;/li&gt;
  &lt;li&gt;Keep track of the number of iteraton via the &lt;code class=&quot;highlighter-rouge&quot;&gt;resume_count&lt;/code&gt; counter.&lt;/li&gt;
  &lt;li&gt;Iterate 10 times.&lt;/li&gt;
  &lt;li&gt;For each iteration,
    &lt;ul&gt;
      &lt;li&gt;wait &lt;code class=&quot;highlighter-rouge&quot;&gt;period&lt;/code&gt; using the &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt; keyword.&lt;/li&gt;
      &lt;li&gt;then increment &lt;code class=&quot;highlighter-rouge&quot;&gt;resume_count&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;co_return&lt;/code&gt; to exit the coroutines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following sequence diagram shows an abstract coroutine execution where an abstracted OS exists to handle the scheduling of process execution. (&lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/docs/diagrams/tast_sequence_abstract.puml&quot;&gt;PlantUML source&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/tast_sequence_abstract.svg&quot; alt=&quot;Task Sequence&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;calling-the-simple-coroutine-task&quot;&gt;Calling the simple coroutine task&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt; function in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/src/example_simple.cpp#L41&quot;&gt;example_simple.cpp&lt;/a&gt; calls the &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic&lt;/code&gt; function once, with &lt;code class=&quot;highlighter-rouge&quot;&gt;100ms&lt;/code&gt; as the &lt;code class=&quot;highlighter-rouge&quot;&gt;period&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler_delay&amp;lt;mtimer_clock&amp;gt;&lt;/code&gt; is a scheduler class that will manage the software timer to wake each coroutine at the appropriate time, using our RISC-V machine mode timer driver &lt;code class=&quot;highlighter-rouge&quot;&gt;mtimer&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;    &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mtimer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Class to manage timer coroutines&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scheduler_delay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtimer_clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Run two concurrent loops. The first loop will run concurrently to the second loop.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mx&quot;&gt;100ms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resume_simple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;resuming-the-coroutine-tasks&quot;&gt;Resuming the coroutine tasks&lt;/h3&gt;

&lt;p&gt;For this example the scheduler is an object instantiated in the &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt; function. It needs to be called explicitly to calculate when each coroutine needs to be woken and resumed. This is a convention of the runtime for this example, and not a required convention for C++ coroutines.&lt;/p&gt;

&lt;p&gt;The tasks are resumed in the &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/src/example_simple.cpp#L82&quot;&gt;WFI busy loop of &lt;code class=&quot;highlighter-rouge&quot;&gt;example_Simple()&lt;/code&gt;&lt;/a&gt; when &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler.update()&lt;/code&gt; is called. However, as the scheduler is just a C++ class, this can be called from other locations, such as a timer interrupt handler.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Get a delay to the next coroutines wake up&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;schedule_by_delay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtimer_clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_wake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Next wakeup&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mtimer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_time_cmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_wake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Timer interrupt enable&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;riscv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mstatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;riscv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// WFI Should be called while interrupts are disabled &lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// to ensure interrupt enable and WFI is atomic.            &lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wfi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For example as the IRQ handler in this example is a lambda function, we could also capture the scheduler and run the timer coroutine in the IRQ handler.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;schedule_by_delay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtimer_clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_wake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;building-and-running-with-platform-io&quot;&gt;Building and running with Platform IO&lt;/h2&gt;

&lt;p&gt;The example can be built and run using Platform IO. The default RISC-V platforms use an old version of GCC that does not support C++20, so a custom virtual platform configured to use &lt;a href=&quot;https://xpack.github.io/dev-tools/riscv-none-elf-gcc/&quot;&gt;xPack 12.2.0-3 riscv-none-elf-gcc&lt;/a&gt; and run on QEMU has been created in &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/tree/main/platformio/platforms/virt_riscv&quot;&gt;platformio/platforms/virt_riscv&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;build_flags = 
    -std=c++20
    -O2
    -g
    -Wall 
    -ffunction-sections 
    -fcoroutines
    -fno-exceptions 
    -fno-rtti 
    -fno-nonansi-builtins 
    -fno-use-cxa-atexit 
    -fno-threadsafe-statics
    -nostartfiles 
    -Wl,-Map,c-hardware-access-riscv.map
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The debug sequence shows entering the function &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt;, initializing &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler_delay&amp;lt;mtimer_clock&amp;gt; scheduler;&lt;/code&gt; then calling &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic(scheduler, 100ms, resume_simple);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the statement &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await scheduled_delay{ scheduler, period };&lt;/code&gt; is reached the context returns to &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt;. Then when &lt;code class=&quot;highlighter-rouge&quot;&gt;auto [pending, next_wake] = scheduler.resume(now);&lt;/code&gt; is called it returns to the &lt;code class=&quot;highlighter-rouge&quot;&gt;for&lt;/code&gt; loop in &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The coroutine handle is stored in the scheduler class by the first call to &lt;code class=&quot;highlighter-rouge&quot;&gt;co_await&lt;/code&gt;. The  following call to &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler.resume()&lt;/code&gt; looks up the pending coroutine handle and calls resume on the handle.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/coro-debug.gif&quot; alt=&quot;Debug Sequence&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The stack of the coroutine &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic()&lt;/code&gt; before resume can be seen below. It’s called from &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/coro-debug-coro-stack-0.png&quot; alt=&quot;Debug Stack - coro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The stack of the coroutines &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic()&lt;/code&gt; after resume can be seen below. It’s called from &lt;code class=&quot;highlighter-rouge&quot;&gt;coroutine_handle::resume&lt;/code&gt;, which is called from &lt;code class=&quot;highlighter-rouge&quot;&gt;scheduler_ordered::resume&lt;/code&gt;.
&lt;img src=&quot;/images/coro-debug-coro-stack-1.png&quot; alt=&quot;Debug Stack - coro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The stack of &lt;code class=&quot;highlighter-rouge&quot;&gt;example_simple()&lt;/code&gt; function calling &lt;code class=&quot;highlighter-rouge&quot;&gt;resume()&lt;/code&gt; is also on the same stack. 
&lt;img src=&quot;/images/coro-debug-main-stack.png&quot; alt=&quot;Debug Stack - main&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;building-with-cmake-and-running-with-spike&quot;&gt;Building with CMake and running with Spike&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/Makefile&quot;&gt;Makefile&lt;/a&gt; has targets to build with &lt;a href=&quot;https://www.five-embeddev.com/baremetal/cmake/&quot;&gt;CMake&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make target
cmake &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cmake/riscv.cmake &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-DCMAKE_EXPORT_COMPILE_COMMANDS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ON &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-B&lt;/span&gt; build_target &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
cmake &lt;span class=&quot;nt&quot;&gt;--build&lt;/span&gt; build_target &lt;span class=&quot;nt&quot;&gt;--verbose&lt;/span&gt;
 &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/Makefile&quot;&gt;Makefile&lt;/a&gt; also has targets to simulate and trace with the standard RISC-V ISA simulator, spike.  The &lt;a href=&quot;https://www.five-embeddev.com/toolchain/2022/09/02/spike-fork/&quot;&gt;forked spike with VCD tracing&lt;/a&gt; is used. The forked spike is included in a &lt;a href=&quot;https://www.five-embeddev.com/toolchain/2024/06/15/docker/&quot;&gt;docker container&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make spike_sim
docker run &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; .:/project &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        fiveembeddev/forked_riscv_spike_dev_env:latest  &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        /opt/riscv-isa-sim/bin/spike &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;spike_sim.log &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--isa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rv32imac_zicsr &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-m0x8000000&lt;/span&gt;:0x2000,0x80000000:0x4000,0x20010000:0x6a120 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--priv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;m &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--pc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0x20010000 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--vcd-log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;spike_sim.vcd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--max-cycles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10000000  &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_simple &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_0 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_1 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_2 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_3 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_4 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_5 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_6 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_7 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_8 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timestamp_resume_9 &lt;span class=&quot;nt&quot;&gt;--trace-var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;resume_simple &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        build_target/src/main.elf
docker run &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; .:/project &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     fiveembeddev/riscv_gtkwave_base:latest &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     vcd2fst spike_sim.vcd spike_sim.fst&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The results can be viewed with GTKWave. The &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/spike_sim.gtkw&quot;&gt;GTKWave savefile&lt;/a&gt; includes &lt;a href=&quot;https://www.five-embeddev.com/code/2024/04/21/gtkwave/&quot;&gt;address decode and opcode decode&lt;/a&gt; by using &lt;a href=&quot;https://github.com/five-embeddev/build-and-verify/tree/main/docker/riscv-gtkwave&quot;&gt;docker images&lt;/a&gt; containing the decoders.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gtkwave spike_sim.fst  spike_sim.gtkw&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The benefit of tracing results from the ISA is that it is easy to confirm the periodic timing of the coroutine. (For this example the parameter to &lt;code class=&quot;highlighter-rouge&quot;&gt;periodic()&lt;/code&gt; was changed to &lt;code class=&quot;highlighter-rouge&quot;&gt;1ms&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The periodic write to &lt;code class=&quot;highlighter-rouge&quot;&gt;resume_count&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;timestamp_resume&lt;/code&gt; is traced to VCD so the exact timing of the coroutine execution is visible.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/coro-debug-gtkwave.png&quot; alt=&quot;Debug GTKWave Trace&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using GTKWave the context switch can also be examined in detail. In the fake 1GhZ clock used by spike, the context switch takes 104ns.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/coro-debug-gtkwave-detail.png&quot; alt=&quot;Debug GTKWave Trace Detail&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;coroutine-runtime&quot;&gt;Coroutine runtime&lt;/h2&gt;

&lt;p&gt;The runtime is described in detail in &lt;a href=&quot;/articles/2024/11/24/part-1-cpp20-coroutines-runtime/&quot;&gt;this post&lt;/a&gt;. The runtime for this example is in the header &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/include/embeddev_coro.hpp&quot;&gt;embeddev_coro.hpp&lt;/a&gt;, and it uses the &lt;a href=&quot;https://github.com/five-embeddev/baremetal-cxx-coro/blob/main/include/embeddev_riscv.hpp&quot;&gt;embeddev_riscv.hpp&lt;/a&gt; header to provide a simple HAL for RISC-V and host emulation.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This post describes a simple working example of how to use C++ coroutines in an embedded context. The example and context are not meant to be a realistic use case, but the simplest possible use case that involves and interrupt handler and a context switch.&lt;/p&gt;

&lt;p&gt;However, the example can be built on to explore portable and lightweight asynchronous programming techniques. Future posts will look at that topic.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;The C++23 standard library provides a limited runtime for coroutines generators. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="C++" /><category term="baremetal" /><category term="coroutines" /><summary type="html">Introduction This post is about using C++ coroutines to suspend and resume functions in real time. The objective is a simple way of building real time tasks using only C++, without the need for an RTOS or operating system kernel. Coroutines are functions that can be suspended and resumed, using the keywords co_await, co_yield and co_return. The C++20 standard introduced coroutines to the language. C++ standardized the keywords and type concepts for coroutines, but it did not standardize a runtime1. The lack of a standard runtime has made them hard to use them “out of the box”, but the implementation of coroutines is very adaptable to different use cases. Here I use a simple runtime implementing C++20 coroutines on bare metal (no operating system) for RISC-V, using the co_await keyword. This is done by passing the real time scheduler and resume time condition as the argument to the asynchronous wait operator. The runtime is described in detail in this post. This story is also published on Medium. The C++23 standard library provides a limited runtime for coroutines generators. &amp;#8617;</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">Update to Docker</title><link href="https://www.five-embeddev.com//toolchain/2024/06/15/docker/" rel="alternate" type="text/html" title="Update to Docker" /><published>2024-06-15T00:00:00+00:00</published><updated>2024-06-15T00:00:00+00:00</updated><id>https://www.five-embeddev.com//toolchain/2024/06/15/docker</id><content type="html" xml:base="https://www.five-embeddev.com//toolchain/2024/06/15/docker/">&lt;h1 id=&quot;docker-images&quot;&gt;Docker Images&lt;/h1&gt;

&lt;p&gt;The reference docker images for building and simulating examples from this blog have been updated:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/five-embeddev/build-and-verify/tree/main/docker&quot;&gt;https://github.com/five-embeddev/build-and-verify/tree/main/docker&lt;/a&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Target&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-tool-build&lt;/td&gt;
      &lt;td&gt;Base image for compiling tools&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-spike&lt;/td&gt;
      &lt;td&gt;RISC-V ISA Simulator.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-openocd&lt;/td&gt;
      &lt;td&gt;OpenOCD JTAG debugger interface&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-xpack-gcc&lt;/td&gt;
      &lt;td&gt;X-PACK packaged GCC&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-spike-debug-sim&lt;/td&gt;
      &lt;td&gt;RISC-V Spike ISA configured to run with OpenOCD&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-spike-debug-gdb&lt;/td&gt;
      &lt;td&gt;RISC-V Spike ISA configured to run with OpenOCD &amp;amp; GDB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-rust&lt;/td&gt;
      &lt;td&gt;Rust for RISC-V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-gnu-toolchain&lt;/td&gt;
      &lt;td&gt;Build GCC for RISC-V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;riscv-gnu-toolchain-2&lt;/td&gt;
      &lt;td&gt;Build GCC for RISC-V (using docker compose to conserve resources)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;docker-examples&quot;&gt;Docker Examples&lt;/h1&gt;

&lt;p&gt;Examples of usage:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/five-embeddev/build-and-verify/tree/main/examples&quot;&gt;https://github.com/five-embeddev/build-and-verify/tree/main/examples&lt;/a&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Example&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;build-c/&lt;/td&gt;
      &lt;td&gt;Build a simple C test program for host and target&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;build-rust/&lt;/td&gt;
      &lt;td&gt;Build a small rust program&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;build-run-sim/&lt;/td&gt;
      &lt;td&gt;Build a full baremetal example and simulate with Spike, debug with GDB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;test-code-c/&lt;/td&gt;
      &lt;td&gt;Small example program&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;build-with-cmake&quot;&gt;Build with Cmake&lt;/h1&gt;

&lt;p&gt;e.g. &lt;a href=&quot;https://github.com/five-embeddev/build-and-verify/tree/main/examples/build-run-sim&quot;&gt;https://github.com/five-embeddev/build-and-verify/tree/main/examples/build-run-sim&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run \
    --rm \
    -v .:/project \
    -v /home/five/five-embeddev-wsl/build-and-verify/examples/build-run-sim/../test-code-c:/project/test_code \
        fiveembeddev/riscv_xpack_gcc_dev_env:latest \
        cmake \
                -S test_code \
                -B build \
                -G &quot;Unix Makefiles&quot; \
                -DCMAKE_TOOLCHAIN_FILE=../test_code/riscv.cmake
docker run \
    --rm \
    -v .:/project \
    -v /home/five/five-embeddev-wsl/build-and-verify/examples/build-run-sim/../test-code-c:/project/test_code \
        fiveembeddev/riscv_xpack_gcc_dev_env:latest \
                make \
                        VERBOSE=1 \
                        -C build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="toolchain" /><category term="vcd" /><category term="simulation" /><category term="debugging" /><category term="tracing" /><category term="baremetal" /><category term="C" /><category term="gtkwave" /><summary type="html">Docker Images The reference docker images for building and simulating examples from this blog have been updated: https://github.com/five-embeddev/build-and-verify/tree/main/docker Target Description riscv-tool-build Base image for compiling tools riscv-spike RISC-V ISA Simulator. riscv-openocd OpenOCD JTAG debugger interface riscv-xpack-gcc X-PACK packaged GCC riscv-spike-debug-sim RISC-V Spike ISA configured to run with OpenOCD riscv-spike-debug-gdb RISC-V Spike ISA configured to run with OpenOCD &amp;amp; GDB riscv-rust Rust for RISC-V riscv-gnu-toolchain Build GCC for RISC-V riscv-gnu-toolchain-2 Build GCC for RISC-V (using docker compose to conserve resources) Docker Examples Examples of usage: https://github.com/five-embeddev/build-and-verify/tree/main/examples Example Description build-c/ Build a simple C test program for host and target build-rust/ Build a small rust program build-run-sim/ Build a full baremetal example and simulate with Spike, debug with GDB test-code-c/ Small example program Build with Cmake e.g. https://github.com/five-embeddev/build-and-verify/tree/main/examples/build-run-sim docker run \ --rm \ -v .:/project \ -v /home/five/five-embeddev-wsl/build-and-verify/examples/build-run-sim/../test-code-c:/project/test_code \ fiveembeddev/riscv_xpack_gcc_dev_env:latest \ cmake \ -S test_code \ -B build \ -G &quot;Unix Makefiles&quot; \ -DCMAKE_TOOLCHAIN_FILE=../test_code/riscv.cmake docker run \ --rm \ -v .:/project \ -v /home/five/five-embeddev-wsl/build-and-verify/examples/build-run-sim/../test-code-c:/project/test_code \ fiveembeddev/riscv_xpack_gcc_dev_env:latest \ make \ VERBOSE=1 \ -C build</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">GTKWave Filters for Debugging VCD Traces of RISC-V Software</title><link href="https://www.five-embeddev.com//code/2024/04/21/gtkwave/" rel="alternate" type="text/html" title="GTKWave Filters for Debugging VCD Traces of RISC-V Software" /><published>2024-04-21T00:00:00+00:00</published><updated>2024-04-21T00:00:00+00:00</updated><id>https://www.five-embeddev.com//code/2024/04/21/gtkwave</id><content type="html" xml:base="https://www.five-embeddev.com//code/2024/04/21/gtkwave/">&lt;p&gt;GTKWave can be used for firmware debugging. This is obviously useful for co-simulation, but is also useful for debugging timing and integration problems.&lt;/p&gt;

&lt;p&gt;In a &lt;a href=&quot;/code/2022/09/04/vcd-trace/&quot;&gt;previous post&lt;/a&gt; I showed how to create a vcd trace of a firmware run via a fork of the RISC-V ISA simulator.&lt;/p&gt;

&lt;p&gt;In this post using &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave&quot;&gt;https://github.com/five-embeddev/riscv-gtkwave&lt;/a&gt; I add:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Instruction Decoding according to the Spike disassembler.&lt;/li&gt;
  &lt;li&gt;Bus Address decoding according to an elf file.&lt;/li&gt;
  &lt;li&gt;CSR register decoding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a few methods to decode via GTKWave. The decoders in &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave&quot;&gt;https://github.com/five-embeddev/riscv-gtkwave&lt;/a&gt; are using 3 methods:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generated Translate filter file.&lt;/li&gt;
  &lt;li&gt;Translate Filter process.&lt;/li&gt;
  &lt;li&gt;Signal Grouping and Vector Expansion and Combination&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;generated-translate-filter-file&quot;&gt;Generated Translate Filter File.&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave/blob/main/scripts/generate_csrs.py&quot;&gt;generate_csrs.py&lt;/a&gt; script uses &lt;a href=&quot;https://pyvcd.readthedocs.io/en/latest/vcd.gtkw.html&quot;&gt;pyvcd&lt;/a&gt; to generate enumeration files such as &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave/blob/main/csr_data/mcause.exception_code.gtkw&quot;&gt;mcause.exception_code.gtkw&lt;/a&gt; from YAML CSR data &lt;a href=&quot;https://github.com/five-embeddev/riscv-isa-data/blob/master/csr.yaml&quot;&gt;csr.yaml&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;filter-process&quot;&gt;Filter Process&lt;/h2&gt;

&lt;h3 id=&quot;risc-v-isa-disassembly-for-gtkwave&quot;&gt;RISC-V ISA Disassembly for GTKWave&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave/blob/main/src/decode_inst.cpp&quot;&gt;decode_inst&lt;/a&gt; program uses the disassembler defined by the RISC-V ISA Simulator in &lt;a href=&quot;https://github.com/riscv-software-src/riscv-isa-sim/blob/3192ee4d31f481e84281a24d55bb6130e3743668/riscv/disasm.h#L4&quot;&gt;disasm.h&lt;/a&gt; to disassemble instruction words.&lt;/p&gt;

&lt;p&gt;It also uses &lt;a href=&quot;https://github.com/riscv-software-src/riscv-isa-sim/blob/3192ee4d31f481e84281a24d55bb6130e3743668/riscv/isa_parser.h&quot;&gt;isa_parser&lt;/a&gt; to determine the ISA to dissassemble. The filename determines the ISA (via &lt;code class=&quot;highlighter-rouge&quot;&gt;argv[0]&lt;/code&gt;, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;decode_inst-rv32ic&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;decode_inst-rv64g&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;e.g. the &lt;code class=&quot;highlighter-rouge&quot;&gt;opcodes.hex&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;20010ae2
20010ae6
20010ae8
20010aea
20010aee
20010af0
20010af2
20010af4
20010af6
20010afa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Piped into &lt;code class=&quot;highlighter-rouge&quot;&gt;decode_inst&lt;/code&gt; gives the following result.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat opcodes.hex | ./decode_inst 
auipc   t0, 0x0
c.add   a3, t0
c.mv    t0, ra
jalr    ra, a3, -88
c.mv    ra, t0
c.addi  a5, -16
c.sub   a4, a5
c.add   a2, a5
bgeu    t1, a2, pc - 120
c.j     pc - 152
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;elf-symbol-lookup-for-gtkwave&quot;&gt;ELF Symbol Lookup for GTKWave&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave/blob/main/src/decode_addr.cpp&quot;&gt;decode_addr&lt;/a&gt; program converts hex address values to symbols names. It uses the global variable symbols or function symbols.&lt;/p&gt;

&lt;p&gt;It is derived from &lt;a href=&quot;https://github.com/riscv-software-src/riscv-isa-sim/blob/3192ee4d31f481e84281a24d55bb6130e3743668/fesvr/elfloader.cc&quot;&gt;elfloader.cc&lt;/a&gt; in the RISC-V ISA simulator.&lt;/p&gt;

&lt;p&gt;As GTKWave cannot pass command line arguments &lt;code class=&quot;highlighter-rouge&quot;&gt;DECODE_ELF&lt;/code&gt; must be set as an environment variable with the path to the ELF file to use.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cd src/
$ DECODE_ELF=../example/main.elf ./decode_addr
0
-
0000
-
0000000020010000
_enter
0000000080000008
mti_count
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;signal-grouping-and-vector-expansion-and-combination&quot;&gt;Signal Grouping and Vector Expansion and Combination&lt;/h2&gt;

&lt;p&gt;Registers signal vectors are expanded into bits, and fields combined as groups of bits.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://pyvcd.readthedocs.io/en/latest/vcd.gtkw.html&quot;&gt;pyvcd&lt;/a&gt;
class &lt;code class=&quot;highlighter-rouge&quot;&gt;GTKWSave&lt;/code&gt; provides &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bits&lt;/code&gt; for this. However it only
provides a single bit function &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/five-embeddev/riscv-gtkwave/blob/main/scripts/generate_csrs.py&quot;&gt;generate_csrs.py&lt;/a&gt; script subclasses &lt;code class=&quot;highlighter-rouge&quot;&gt;GTKWSave&lt;/code&gt; and adds &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bit_group&lt;/code&gt; for multibit fields. These can be interpreted via translate filter files.&lt;/p&gt;

&lt;p&gt;Added &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bit_group&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class UpdateGTKWSave(vcd.gtkw.GTKWSave):
    def trace_bit_group(
        self,
        lsb: int, msb: int,
        name: str,
        alias: str,
        color: Optional[Union[vcd.gtkw.GTKWColor, str, int]] = None,
        translate_filter_file: Optional[str] = None,
    ) -&amp;gt; None:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Iterate over fields in a register and add the &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bit&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_bit_group&lt;/code&gt;. There is one save file per CSR.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   gtkw = UpdateGTKWSave(rout)
   gtkw.comment(f&quot;Fields for register {reg_name}&quot;)
   gtkw.begin_group(reg_name)
   with gtkw.trace_bits(reg_path):
       for fkey, fdata in reg_data['fields'].items():
           gtkw.comment(f&quot;Field {reg_name}_{fkey}&quot;)
           fwidth=get_field_width(fdata)
           msb,lsb=get_field_range(fdata)
           if fwidth==1:
               gtkw.trace_bit(reg_width-lsb-1, 
                   name=f&quot;{reg_path}&quot;,
                   alias=f&quot;{reg_name}_{fkey}&quot;)
           else:
               translate_filter_file=...
               gtkw.trace_bit_group(
                   reg_width-msb-1, 
                   reg_width-lsb, 
                   name=f&quot;{reg_path}&quot;,
                   alias=f&quot;{reg_name}_{fkey}&quot;,
                   translate_filter_file=translate_filter_file)
   gtkw.end_group(reg_name)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;firmware-trace-example&quot;&gt;Firmware Trace Example&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/vcd-wave-int.png&quot; alt=&quot;Example of firmware trace&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;todo&quot;&gt;TODO&lt;/h2&gt;

&lt;p&gt;There are many limitations to these programs.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;64bit/32bit distinctions are not&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a real world application other decoders that are useful are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;MMIO Peripheral register decoding.&lt;/li&gt;
  &lt;li&gt;External bus/device (I2C/SPI) register decoding.&lt;/li&gt;
  &lt;li&gt;RTOS/OS instrumentation (e.g. current task, current memory map etc)&lt;/li&gt;
  &lt;li&gt;Test name/assertion name.&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="toolchain" /><category term="vcd" /><category term="simulation" /><category term="debugging" /><category term="tracing" /><category term="baremetal" /><category term="C" /><category term="gtkwave" /><summary type="html">GTKWave can be used for firmware debugging. This is obviously useful for co-simulation, but is also useful for debugging timing and integration problems. In a previous post I showed how to create a vcd trace of a firmware run via a fork of the RISC-V ISA simulator. In this post using https://github.com/five-embeddev/riscv-gtkwave I add: Instruction Decoding according to the Spike disassembler. Bus Address decoding according to an elf file. CSR register decoding. There are a few methods to decode via GTKWave. The decoders in https://github.com/five-embeddev/riscv-gtkwave are using 3 methods: Generated Translate filter file. Translate Filter process. Signal Grouping and Vector Expansion and Combination</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">RISC-V ISA Instruction Quick Reference Update</title><link href="https://www.five-embeddev.com//updates/2024/03/03/instructions/" rel="alternate" type="text/html" title="RISC-V ISA Instruction Quick Reference Update" /><published>2024-03-03T00:00:00+00:00</published><updated>2024-03-03T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2024/03/03/instructions</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2024/03/03/instructions/">&lt;p&gt;The &lt;a href=&quot;/quickref/instructions.html&quot;&gt;Instructions Quickref&lt;/a&gt; has been updated to match &lt;a href=&quot;/updates/2023/11/15/compiler-explorer/&quot;&gt;the changes made for Compiler Explorer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The opcode references are generated from &lt;a href=&quot;https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml&quot;&gt;opcodes.yaml&lt;/a&gt; which is generated by &lt;a href=&quot;https://github.com/five-embeddev/riscv-docs-html/blob/gh_pages/generators/scripts/convert_opcodes.rb&quot;&gt;convert_opcodes.rb&lt;/a&gt; in &lt;a href=&quot;https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages&quot;&gt;https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages&lt;/a&gt;.&lt;/p&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="riscv.org" /><category term="spec" /><category term="html" /><summary type="html">The Instructions Quickref has been updated to match the changes made for Compiler Explorer. The opcode references are generated from opcodes.yaml which is generated by convert_opcodes.rb in https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">RISC-V ISA Reference for Compiler Explorer</title><link href="https://www.five-embeddev.com//updates/2023/11/15/compiler-explorer/" rel="alternate" type="text/html" title="RISC-V ISA Reference for Compiler Explorer" /><published>2023-11-15T00:00:00+00:00</published><updated>2023-11-15T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2023/11/15/compiler-explorer</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2023/11/15/compiler-explorer/">&lt;p&gt;Compiler explorer now includes RISC-V opcode references for the rv64 targets, following my pull &lt;a href=&quot;https://github.com/compiler-explorer/compiler-explorer/pull/5598/commits&quot;&gt;pull request&lt;/a&gt; and initial work by &lt;a href=&quot;https://github.com/SiyaoIsHiding&quot;&gt;Siyao&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The updated files are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/compiler-explorer/compiler-explorer/blob/main/etc/scripts/docenizers/docenizer-riscv64.py&quot;&gt;etc/scripts/docenizers/docenizer-riscv64.py&lt;/a&gt;: Generator, converts &lt;code class=&quot;highlighter-rouge&quot;&gt;yaml&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;ts&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/asm-docs/generated/asm-docs-riscv64.ts&quot;&gt;lib/asm-docs/generated/asm-docs-riscv64.ts&lt;/a&gt;: The generated opcode documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The opcode references are generated from &lt;a href=&quot;https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml&quot;&gt;opcodes.yaml&lt;/a&gt; which is generated by &lt;a href=&quot;https://github.com/five-embeddev/riscv-docs-html/blob/gh_pages/generators/scripts/convert_opcodes.rb&quot;&gt;convert_opcodes.rb&lt;/a&gt; in &lt;a href=&quot;https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages&quot;&gt;https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The opcode decriptions are automatically extracted from the ISA user manual in HTML format. For example the description for &lt;a href=&quot;https://godbolt.org/api/asm/riscv64/sd&quot;&gt;sd&lt;/a&gt; is extracted from the &lt;a href=&quot;https://five-embeddev.github.io/riscv-docs-html//riscv-user-isa-manual/Priv-v1.12/rv64.html#load-and-store-instructions&quot;&gt;Load and Store Instructions&lt;/a&gt; section.&lt;/p&gt;

&lt;p&gt;To generate the data run these commands in the compiler explorer repo:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; cd compiler-explorer/etc/scripts/docenizers/
./docenizer-riscv64.py \
    -i https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml \
    -o ../../../lib/asm-docs/generated/asm-docs-riscv64.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="riscv.org" /><category term="spec" /><category term="html" /><summary type="html">Compiler explorer now includes RISC-V opcode references for the rv64 targets, following my pull pull request and initial work by Siyao. The updated files are: etc/scripts/docenizers/docenizer-riscv64.py: Generator, converts yaml to ts. lib/asm-docs/generated/asm-docs-riscv64.ts: The generated opcode documentation. The opcode references are generated from opcodes.yaml which is generated by convert_opcodes.rb in https://github.com/five-embeddev/riscv-docs-html/tree/gh_pages. The opcode decriptions are automatically extracted from the ISA user manual in HTML format. For example the description for sd is extracted from the Load and Store Instructions section. To generate the data run these commands in the compiler explorer repo: cd compiler-explorer/etc/scripts/docenizers/ ./docenizer-riscv64.py \ -i https://five-embeddev.github.io/riscv-docs-html/opcodes.yaml \ -o ../../../lib/asm-docs/generated/asm-docs-riscv64.ts</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">RISC-V ISA Manuals to HTML</title><link href="https://www.five-embeddev.com//updates/2023/07/31/html-docs/" rel="alternate" type="text/html" title="RISC-V ISA Manuals to HTML" /><published>2023-07-31T00:00:00+00:00</published><updated>2023-07-31T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2023/07/31/html-docs</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2023/07/31/html-docs/">&lt;p&gt;The &lt;a href=&quot;/riscv-isa-manual/latest/riscv-spec.html&quot;&gt;User ISA&lt;/a&gt; and &lt;a href=&quot;/riscv-isa-manual/latest/riscv-privileged.html&quot;&gt;Privileged ISA&lt;/a&gt; have been are converted to HTML from TEX on the &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual&quot;&gt;upstream repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The latest upstream versions have recently been converted to
&lt;a href=&quot;https://asciidoc.org/&quot;&gt;asciidoc&lt;/a&gt;, but the legacy versions that were
used to generate HTML on this site are converted from the older TEX.&lt;/p&gt;

&lt;p&gt;In theory converting tex should be as simple as running a conversion tool such
as &lt;a href=&quot;https://pandoc.org/&quot;&gt;pandoc&lt;/a&gt; or
&lt;a href=&quot;https://www.latex2html.org/&quot;&gt;latex2html&lt;/a&gt; but without some
optimization that gives quite ugly results - in particular for tables
and diagrams.&lt;/p&gt;

&lt;p&gt;The set of scripts that this blog uses to optimize the pandoc output
has been uploaded to
&lt;a href=&quot;https://github.com/five-embeddev/riscv-docs-html&quot;&gt;https://github.com/five-embeddev/riscv-docs-html&lt;/a&gt;. A Dockerfile is
used to configure a build environment with pandoc and asciidoctor and
the other tools used to do the conversion.&lt;/p&gt;

&lt;p&gt;A set of static html github pages have been exported here,
&lt;a href=&quot;https://five-embeddev.github.io/riscv-docs-html/&quot;&gt;https://five-embeddev.github.io/riscv-docs-html/&lt;/a&gt;. They HTML is
identical, but it lacks the side navigation menu and css style used by
this site.&lt;/p&gt;

&lt;p&gt;These scripts are also used to create the
&lt;a href=&quot;https://github.com/five-embeddev/riscv-isa-data/blob/master/opcodes.yaml&quot;&gt;opcodes.yaml&lt;/a&gt;
and
&lt;a href=&quot;https://github.com/five-embeddev/riscv-isa-data/blob/master/csr.yaml&quot;&gt;csr.yaml&lt;/a&gt;
data files used by the &lt;a href=&quot;/quickref/instructions.html&quot;&gt;Instruction Quick
Reference&lt;/a&gt; and &lt;a href=&quot;/quickref/csrs.html&quot;&gt;CSR Quick
Reference&lt;/a&gt; on this site.&lt;/p&gt;

&lt;p&gt;More info on that will be posted later.&lt;/p&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="riscv.org" /><category term="spec" /><category term="html" /><category term="docker" /><summary type="html">The User ISA and Privileged ISA have been are converted to HTML from TEX on the upstream repo. The latest upstream versions have recently been converted to asciidoc, but the legacy versions that were used to generate HTML on this site are converted from the older TEX. In theory converting tex should be as simple as running a conversion tool such as pandoc or latex2html but without some optimization that gives quite ugly results - in particular for tables and diagrams. The set of scripts that this blog uses to optimize the pandoc output has been uploaded to https://github.com/five-embeddev/riscv-docs-html. A Dockerfile is used to configure a build environment with pandoc and asciidoctor and the other tools used to do the conversion. A set of static html github pages have been exported here, https://five-embeddev.github.io/riscv-docs-html/. They HTML is identical, but it lacks the side navigation menu and css style used by this site. These scripts are also used to create the opcodes.yaml and csr.yaml data files used by the Instruction Quick Reference and CSR Quick Reference on this site. More info on that will be posted later.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">RISC-V Interrupts/Exceptions Quick Reference</title><link href="https://www.five-embeddev.com//updates/2023/05/11/interrupts/" rel="alternate" type="text/html" title="RISC-V Interrupts/Exceptions Quick Reference" /><published>2023-05-11T00:00:00+00:00</published><updated>2023-05-11T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2023/05/11/interrupts</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2023/05/11/interrupts/">&lt;p&gt;A fix has been made to the &lt;a href=&quot;/quickref/interrupts.html&quot;&gt;Interrupts/Exceptions Quick Reference&lt;/a&gt; to clarify that &lt;span title=&quot;Machine status register.&quot;&gt;&lt;a href=&quot;/riscv-priv-isa-manual/Priv-v1.12/machine.html#machine-status-registers-mstatus-and-mstatush&quot;&gt;&lt;b&gt;mstatus&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;.&lt;b&gt;mpp&lt;/b&gt; is set to the the least-privileged supported mode on &lt;b&gt;&lt;tt&gt;&lt;a href=&quot;/riscv-priv-isa-manual/Priv-v1.12/machine.html#privstack&quot;&gt;mret&lt;/a&gt;&lt;/tt&gt;&lt;/b&gt;. The local version of &lt;a href=&quot;/riscv-isa-manual/latest/machine.html&quot;&gt;Machine-Level ISA&lt;/a&gt; has been updated to the &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/blob/Priv-v1.12/src/machine.tex&quot;&gt;Priv-v1.12 source&lt;/a&gt; as this is the current version on &lt;a href=&quot;https://riscv.org/technical/specifications/&quot;&gt;https://riscv.org/technical/specifications/&lt;/a&gt;. References to the depreciated user mode interrupts and the n extension were also removed.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;From &lt;span title=&quot;Machine status register.&quot;&gt;&lt;a href=&quot;/riscv-priv-isa-manual/Priv-v1.12/machine.html#machine-status-registers-mstatus-and-mstatush&quot;&gt;&lt;b&gt;mstatus&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An MRET or SRET instruction is used to return from a trap in M-mode or S-mode respectively. When executing an xRET instruction, supposing xPP holds the value y, xIE is set to xPIE; the privilege mode is changed to y; xPIE is set to 1; and xPP is set to the least-privileged supported mode (U if U-mode is implemented, else M). If xPP≠M, xRET also sets MPRV=0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From &lt;span title=&quot;Supervisor status register.&quot;&gt;&lt;a href=&quot;/riscv-priv-isa-manual/Priv-v1.12/supervisor.html#sstatus&quot;&gt;&lt;b&gt;sstatus&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When an SRET instruction (see Section [otherpriv]) is executed to return from the trap handler, the privilege level is set to user mode if the SPP bit is 0, or supervisor mode if the SPP bit is 1; SPP is then set to 0.
11&lt;/p&gt;
&lt;/blockquote&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="interrupts" /><category term="quickref" /><summary type="html">A fix has been made to the Interrupts/Exceptions Quick Reference to clarify that mstatus.mpp is set to the the least-privileged supported mode on mret. The local version of Machine-Level ISA has been updated to the Priv-v1.12 source as this is the current version on https://riscv.org/technical/specifications/. References to the depreciated user mode interrupts and the n extension were also removed.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">CSR Quick Reference Update</title><link href="https://www.five-embeddev.com//updates/2023/05/04/csr-update/" rel="alternate" type="text/html" title="CSR Quick Reference Update" /><published>2023-05-04T00:00:00+00:00</published><updated>2023-05-04T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2023/05/04/csr-update</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2023/05/04/csr-update/">&lt;p&gt;The &lt;a href=&quot;/quickref/csrs.html&quot;&gt;CSR quick reference&lt;/a&gt; list was updated:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cross references to manuals.&lt;/li&gt;
  &lt;li&gt;Details for some fields.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="registers" /><category term="csr" /><category term="quickref" /><summary type="html">The CSR quick reference list was updated: Cross references to manuals. Details for some fields.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry><entry><title type="html">RISC-V ISA Manual Update</title><link href="https://www.five-embeddev.com//updates/2023/05/03/isa-update/" rel="alternate" type="text/html" title="RISC-V ISA Manual Update" /><published>2023-05-03T00:00:00+00:00</published><updated>2023-05-03T00:00:00+00:00</updated><id>https://www.five-embeddev.com//updates/2023/05/03/isa-update</id><content type="html" xml:base="https://www.five-embeddev.com//updates/2023/05/03/isa-update/">&lt;p&gt;The &lt;a href=&quot;/riscv-isa-manual/latest/riscv-spec.html&quot;&gt;User ISA&lt;/a&gt; and &lt;a href=&quot;/riscv-isa-manual/latest/riscv-privileged.html&quot;&gt;Privileged ISA&lt;/a&gt; have been updated to tag Priv-1.12 in the &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual&quot;&gt;upstream repo&lt;/a&gt; and re-generated as HTML.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Updated to official release branch (Priv-1.12)&lt;/li&gt;
  &lt;li&gt;Added links to source documents, source version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The upstream changelog from git is:&lt;/p&gt;

&lt;!--more--&gt;

&lt;ul&gt;
  &lt;li&gt;bump priv version&lt;/li&gt;
  &lt;li&gt;Relax Svpbmt sequence slightly&lt;/li&gt;
  &lt;li&gt;Add FLH, FSH to defined transformed instructions for H extension (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/792&quot;&gt;#792&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;priv spec version 20211202&lt;/li&gt;
  &lt;li&gt;boldface ratified extensions&lt;/li&gt;
  &lt;li&gt;Clarify that henvcfg.PBMTE is read-only zero if Svpbmt is not implemented&lt;/li&gt;
  &lt;li&gt;Clarify that PBMTE is read-only zero if Svpbmt is not implemented&lt;/li&gt;
  &lt;li&gt;fix typo&lt;/li&gt;
  &lt;li&gt;Permit speculative execution of HLV/HSV; reset hgatp.MODE, satp.MODE&lt;/li&gt;
  &lt;li&gt;Fix Travis build status image URL&lt;/li&gt;
  &lt;li&gt;Rework the description of exceptions for Svinval (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/786&quot;&gt;#786&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Change H extension to version 1.0 (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/787&quot;&gt;#787&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Interrupts and exceptions are different things. (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/788&quot;&gt;#788&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Priv specs are ratified&lt;/li&gt;
  &lt;li&gt;Add menvcfg.PBMTE / henvcfg.PBMTE&lt;/li&gt;
  &lt;li&gt;Remark that Svnapot and Svpbmt require Sv39&lt;/li&gt;
  &lt;li&gt;Move SFENCE.VMA/satp.MODE remark to better location&lt;/li&gt;
  &lt;li&gt;Clarify that implicit reads of CSRs return same value as explicit reads (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/783&quot;&gt;#783&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix typo&lt;/li&gt;
  &lt;li&gt;Add VS field&lt;/li&gt;
  &lt;li&gt;Split RV32 [v]sstatus figures into two rows&lt;/li&gt;
  &lt;li&gt;Add Hazard3 to open-source marchid list (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/784&quot;&gt;#784&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix typo&lt;/li&gt;
  &lt;li&gt;Specify a sequence to regain coherence wrt. mismatched PBMTs&lt;/li&gt;
  &lt;li&gt;Avoid use of “timebase”&lt;/li&gt;
  &lt;li&gt;Clarify definition of [m]time CSR&lt;/li&gt;
  &lt;li&gt;Merge branch ‘jhauser-us-jhauser-2021-CSRFieldMods’&lt;/li&gt;
  &lt;li&gt;Clarify when SFENCE.VMA/HFENCE.GVMA need be executed&lt;/li&gt;
  &lt;li&gt;Extension is “implemented”, not “enabled” (in Svinval) (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/780&quot;&gt;#780&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Explain why mstatus.TVM doesn’t affect vsatp, HFENCE.VVMA (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/779&quot;&gt;#779&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;H extension requires page-based address translation (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/778&quot;&gt;#778&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Non-normatively remark that high-order PPN bits aren’t ignored&lt;/li&gt;
  &lt;li&gt;Revert “Separate transformation for HLV instructions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/777&quot;&gt;#777&lt;/a&gt;)”&lt;/li&gt;
  &lt;li&gt;Fix typo&lt;/li&gt;
  &lt;li&gt;Separate transformation for HLV instructions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/777&quot;&gt;#777&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Memory access traps may write zero to stval (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/776&quot;&gt;#776&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Accesses to pages with mismatched attrs are I/O &lt;em&gt;and&lt;/em&gt; memory wrt FENCE (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/774&quot;&gt;#774&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Rename hstatus.HU (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/770&quot;&gt;#770&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Allow more bits of hideleg to be writable (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/772&quot;&gt;#772&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify condition when virtual instruction trap will occur (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/773&quot;&gt;#773&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;CSR mideleg masks hideleg, hip, and hie (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/771&quot;&gt;#771&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Rewrite most instances of “hardwire” as “read-only” (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/768&quot;&gt;#768&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Remove trailing whitespace from a.tex (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/767&quot;&gt;#767&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Document version 20211105-signoff&lt;/li&gt;
  &lt;li&gt;Further relax PMP/address-translation caching interactions&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/763&quot;&gt;#763&lt;/a&gt; from riscv/virt-mem-extensions&lt;/li&gt;
  &lt;li&gt;Add Sv57 and Sv57x4&lt;/li&gt;
  &lt;li&gt;Merge branch ‘master’ of github.com:riscv/riscv-isa-manual&lt;/li&gt;
  &lt;li&gt;Back to draft status&lt;/li&gt;
  &lt;li&gt;Define the Zicntr and Zihpm extensions&lt;/li&gt;
  &lt;li&gt;Improve text in Zicntr section&lt;/li&gt;
  &lt;li&gt;Document version 20211028-signoff&lt;/li&gt;
  &lt;li&gt;Incorporate Steve’s feedback&lt;/li&gt;
  &lt;li&gt;No valid LR/SC reservation upon reset&lt;/li&gt;
  &lt;li&gt;Fix editing error in mtval/stval definition&lt;/li&gt;
  &lt;li&gt;Clarify order in which PMP CSRs must be implemented&lt;/li&gt;
  &lt;li&gt;Fix permissions of *envcfg CSRs&lt;/li&gt;
  &lt;li&gt;Improve description of FENCE.TSO&lt;/li&gt;
  &lt;li&gt;Add example to clarify mip.SEIP behavior&lt;/li&gt;
  &lt;li&gt;Bump priv version number&lt;/li&gt;
  &lt;li&gt;Priv-1.12 spec for public review&lt;/li&gt;
  &lt;li&gt;JohnH is an editor of the priv spec&lt;/li&gt;
  &lt;li&gt;RISC-V Foundation -&amp;gt; RISC-V International&lt;/li&gt;
  &lt;li&gt;Freeze the hypervisor extension, version 1.0.0-rc (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/739&quot;&gt;#739&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;mip.MSIP and mie.MSIE may be hardwired zeros (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/738&quot;&gt;#738&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Hypervisor extension requires page-based address translation (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/737&quot;&gt;#737&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix apparent typo re hpmcounter*h (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/735&quot;&gt;#735&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;State behavior of uncacheable accesses to cacheable locations&lt;/li&gt;
  &lt;li&gt;Clarify that WARL fields contain legal values after reset (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/734&quot;&gt;#734&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Rename STCE to STCD to reverse its polarity&lt;/li&gt;
  &lt;li&gt;Generalize SSIP to support forthcoming interrupt controllers (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/726&quot;&gt;#726&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Speculative implicit reads, v2 (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/724&quot;&gt;#724&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix a typo in Figure A.13. (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/733&quot;&gt;#733&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/727&quot;&gt;#727&lt;/a&gt; from riscv/mseccfg&lt;/li&gt;
  &lt;li&gt;Make virtual instruction exceptions more consistent for VU mode (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/730&quot;&gt;#730&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Pedantically clarify behavior of writing lo/hi parts of counters&lt;/li&gt;
  &lt;li&gt;Remove errant preface entry&lt;/li&gt;
  &lt;li&gt;Clarify widths of privileged CSRs (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/728&quot;&gt;#728&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Revert “Replace “EEI” with “execution environment” (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/723&quot;&gt;#723&lt;/a&gt;)”&lt;/li&gt;
  &lt;li&gt;Add preface entry&lt;/li&gt;
  &lt;li&gt;Designate some of SYSTEM opcode for custom use&lt;/li&gt;
  &lt;li&gt;Add mconfigptr CSR (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/697&quot;&gt;#697&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Replace “EEI” with “execution environment” (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/723&quot;&gt;#723&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix (again) non-normative CSR side-effect text&lt;/li&gt;
  &lt;li&gt;Remove historical remark on MRET definition&lt;/li&gt;
  &lt;li&gt;Fix non-normative text about CSR ordering (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/720&quot;&gt;#720&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add marchid for Hummingbirdv2 E203 (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/664&quot;&gt;#664&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Update H chapter table of synchronous exception priorities (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/717&quot;&gt;#717&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Tweak table of synchronous exception priorities (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/716&quot;&gt;#716&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Make explicit the priorities of synch. exceptions of H extension (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/711&quot;&gt;#711&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify priorities of synchronous exceptions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/715&quot;&gt;#715&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;stval already cannot be zero on breakpoints, misaligned addresses (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/714&quot;&gt;#714&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;VS mode should not see exception code 10 (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/712&quot;&gt;#712&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Merge branch ‘jhauser-us-jhauser-2021-HBaseI’&lt;/li&gt;
  &lt;li&gt;Corrections to mstatus in hypervisor chapter (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/710&quot;&gt;#710&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Minor improvements to text for virtual instruction exceptions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/709&quot;&gt;#709&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify when mstatus.FS may be hardwired zero (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/707&quot;&gt;#707&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Interrupt conditions are also evaluated on falling edges&lt;/li&gt;
  &lt;li&gt;Generalize interrupt trap condition evaluation conditions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/705&quot;&gt;#705&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify that RV64 accesses to mtime[cmp] are atomic&lt;/li&gt;
  &lt;li&gt;State that misa.F does not affect mstatus.FS&lt;/li&gt;
  &lt;li&gt;Improve rules for virtual instruction exceptions, again (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/703&quot;&gt;#703&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify mepc invalid address conversion&lt;/li&gt;
  &lt;li&gt;Improve description of interrupt traps (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/701&quot;&gt;#701&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Merge branch ‘jhauser-us-jhauser-2021-extStats’&lt;/li&gt;
  &lt;li&gt;Clarify that SFENCE.VMA isn’t required for Sbare&lt;/li&gt;
  &lt;li&gt;Fix b6cade07034d39e65134a879a5c3369d50e0df0e&lt;/li&gt;
  &lt;li&gt;Remove N extension chapter for now&lt;/li&gt;
  &lt;li&gt;CSR instead of field (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/669&quot;&gt;#669&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add non-normative text about VIPT caches not being exposed&lt;/li&gt;
  &lt;li&gt;Remove concept of hard reset from normative text&lt;/li&gt;
  &lt;li&gt;Add marchid for XiangShan (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/661&quot;&gt;#661&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;PMP RWX are collectively WARL, with R=0 W=1 being illegal (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/658&quot;&gt;#658&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Delete detailed text surrounding RVC immediates&lt;/li&gt;
  &lt;li&gt;Merge branch ‘jscheid-ventana-jscheid/c-pmas’&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/655&quot;&gt;#655&lt;/a&gt; from riscv/remove-l-t&lt;/li&gt;
  &lt;li&gt;Clarifying FENCE operation behavior for external devices. (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/657&quot;&gt;#657&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/652&quot;&gt;#652&lt;/a&gt; from rafaelcalcada/master&lt;/li&gt;
  &lt;li&gt;Use plural “base ISAs” rather than “base ISA” when appropriate&lt;/li&gt;
  &lt;li&gt;Fix capitalization of HINTs&lt;/li&gt;
  &lt;li&gt;Fix hyphenation&lt;/li&gt;
  &lt;li&gt;Clarify need for HFENCE.GVMA after hgatp.MODE change&lt;/li&gt;
  &lt;li&gt;Assin version number 0.1 to Zmmul&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/648&quot;&gt;#648&lt;/a&gt; from riscv/zmmul&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/645&quot;&gt;#645&lt;/a&gt; from riscv/listofitems&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/644&quot;&gt;#644&lt;/a&gt; from EwoutH/patch-1&lt;/li&gt;
  &lt;li&gt;marchid request for RudolV (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/643&quot;&gt;#643&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Minor mstatus and sstatus layout edits. (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/642&quot;&gt;#642&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;SUM should be hardwired to 0 for cores without paging (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/641&quot;&gt;#641&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Requesting marchid for cv32e40x and cv32e40s (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/630&quot;&gt;#630&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;marchid request for Ibex (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/638&quot;&gt;#638&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Define canonical location of K extension in ISA string&lt;/li&gt;
  &lt;li&gt;Clarify hypervisor privilege hierarchy/global interrupt enables&lt;/li&gt;
  &lt;li&gt;Add FENCE.TSO and PAUSE to RV32I instruction table&lt;/li&gt;
  &lt;li&gt;Clarify that AMOs use the original address when rd == rs1 (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/632&quot;&gt;#632&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;fix typo in preface&lt;/li&gt;
  &lt;li&gt;s/NSE/Custom/ in RVC spec&lt;/li&gt;
  &lt;li&gt;wrap long line&lt;/li&gt;
  &lt;li&gt;Merge pull request &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/398&quot;&gt;#398&lt;/a&gt; from riscv/pause&lt;/li&gt;
  &lt;li&gt;Update preface&lt;/li&gt;
  &lt;li&gt;Clarify type of timer interrupt (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/617&quot;&gt;#617&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Fix editing error introduced in 9ff515cd6695ac392e5ca32b73a135aa197e2778&lt;/li&gt;
  &lt;li&gt;Delete duplicate (and now inconsistent) version number given in body text. Closes &lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/618&quot;&gt;#618&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Revert “should -&amp;gt; shall in definition of 0 instruction”&lt;/li&gt;
  &lt;li&gt;should -&amp;gt; shall in definition of 0 instruction&lt;/li&gt;
  &lt;li&gt;Explain rationale for seting xPP=U on an xRET&lt;/li&gt;
  &lt;li&gt;Add preface note that N extension was moved to its own chapter&lt;/li&gt;
  &lt;li&gt;Clean up NMI/mepc wording&lt;/li&gt;
  &lt;li&gt;Additional FS clarification&lt;/li&gt;
  &lt;li&gt;Clarify rm field on widening conversions (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/619&quot;&gt;#619&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;spell check&lt;/li&gt;
  &lt;li&gt;clarify that FS need only be set to dirty if the state is actually changed&lt;/li&gt;
  &lt;li&gt;LR/SC extension commentary tweak&lt;/li&gt;
  &lt;li&gt;Clarify when FP conversions raise the Inexact flag&lt;/li&gt;
  &lt;li&gt;Use consistent wording for FP exception text&lt;/li&gt;
  &lt;li&gt;Make unused misa fields 0 (WARL) rather than WLRL. (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/615&quot;&gt;#615&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Dedicated section for machine-level memory-mapped registers (not standard CSRs) (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/614&quot;&gt;#614&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Clarify G bits in all G-stage PTEs are reserved (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/613&quot;&gt;#613&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;PMP uses physical addresses (not effective addresses) (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/610&quot;&gt;#610&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Update editors&lt;/li&gt;
  &lt;li&gt;Update contributors&lt;/li&gt;
  &lt;li&gt;mcounteren is WARL&lt;/li&gt;
  &lt;li&gt;PMP TOR clarifications&lt;/li&gt;
  &lt;li&gt;Another attempt to clarify SEIP RMW semantics&lt;/li&gt;
  &lt;li&gt;Attempt to clarify SEIP RMW semantics&lt;/li&gt;
  &lt;li&gt;fm=0 for FENCE HINTs&lt;/li&gt;
  &lt;li&gt;Both HWBPs and EBREAKs populate mtval (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/601&quot;&gt;#601&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;marchid request for NEORV32 core (&lt;a href=&quot;https://github.com/riscv/riscv-isa-manual/issues/579&quot;&gt;#579&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Five Embeddev</name><email>blog@five-embeddev.com</email></author><category term="riscv.org" /><category term="spec" /><summary type="html">The User ISA and Privileged ISA have been updated to tag Priv-1.12 in the upstream repo and re-generated as HTML. Updated to official release branch (Priv-1.12) Added links to source documents, source version. The upstream changelog from git is:</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.five-embeddev.com//siteicon.png" /></entry></feed>