<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>James W. Hanlon</title><link href="https://jameswhanlon.com/" rel="alternate"/><link href="https://jameswhanlon.com/reeds/atom.xml" rel="self"/><id>https://jameswhanlon.com/</id><updated>2024-08-26T00:00:00+02:00</updated><entry><title>Personal data and self hosting</title><link href="https://jameswhanlon.com/personal-data-and-self-hosting.html" rel="alternate"/><published>2024-08-26T00:00:00+02:00</published><updated>2024-08-26T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2024-08-26:/personal-data-and-self-hosting.html</id><summary type="html">&lt;p&gt;Details of how I how self host services to maintain a degree of
digital privacy and&amp;nbsp;freedom.&lt;/p&gt;</summary><content type="html">&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/self-hosted/boxes.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boxes_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;As part of a conscious effort to reduce or remove my dependence on cloud
services for storing my data, I have been running a modest self-hosted setup
for quite a few years, which has worked well and required very little ongoing
maintenance. I haven’t attempted to self-host services like email, opting
instead for trusted providers. This short note goes over the main&amp;nbsp;details.&lt;/p&gt;
&lt;p&gt;The goals for my personal computing&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;To have complete control over my personal data, giving me flexibility over
  how to manage and access it. Even with &lt;span class="caps"&gt;GDPR&lt;/span&gt;, this would be an ambitious goal for
  all personal data, so I really mean files and media created on personal
  computing devices. Anything that I can download from a cloud service, I aim
  backup on my own storage, or master it there if I no longer require access via
  the cloud&amp;nbsp;service.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To have independence from companies that (a) offer free services in return
  for collecting profiling data or to target adverts at me, (b) lock me in as a
  user so it is hard to move to another service and (c) to avoid services that I
  come to rely on being&amp;nbsp;end-of-lifed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To have a system that is simple to set up, maintain, use, upgrade and
  possibly/eventually to migrate&amp;nbsp;from.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To provide a significant amount of storage (in personal data terms, ~tens of TBs).
  This is because accessing volumes of data this large through cloud services can be
  expensive when you factor in monthly charges and transfer&amp;nbsp;costs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main philosophy of my approach is to minimise maintenance effort whilst
still achieving the above goals, so my setup is very vanilla. Many more exotic
and interesting self hosted systems can be found (I’ve linked to a few
resources at &lt;a href="#links"&gt;the end&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Synology&amp;nbsp;Diskstation&lt;/h2&gt;
&lt;p&gt;The main machine is a Synology Diskstation &lt;span class="caps"&gt;DS220&lt;/span&gt;+, a two-bay network-attached-storage (&lt;span class="caps"&gt;NAS&lt;/span&gt;) box.
I have this running with two 8 &lt;span class="caps"&gt;TB&lt;/span&gt; disks in &lt;span class="caps"&gt;RAID&lt;/span&gt; 1 configuration (two-way redundant
using one disk as a mirror), and I upgraded it with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; of memory in addition to the
2 &lt;span class="caps"&gt;GB&lt;/span&gt; it comes with. There are many applications that Synology provide, but the main ones
I use&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fileserver (&lt;span class="caps"&gt;SMB&lt;/span&gt; for access via Windows and Mac machines, and the Drive app for accessing and syncing&amp;nbsp;files).&lt;/li&gt;
&lt;li&gt;Photos (in particular the photos mobile app automatically syncs photos to the &lt;span class="caps"&gt;NAS&lt;/span&gt; for&amp;nbsp;backup).&lt;/li&gt;
&lt;li&gt;Music.&lt;/li&gt;
&lt;li&gt;Hyperbackup.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The advantage of a Synology system is good hardware complemented
by their ecosystem of applications, spanning iPhone and Android too. The catch
is that this ecosystem is closed source and managed by Synology. As such, support for old
hardware is eventually dropped and some software packages are deprecated.
To mitigate these problems, an alternative is TrueNAS (formerly FreeNAS), running on
some suitable hardware. Other non-Synology software can be run on
a Synology device using Docker, however I&amp;#8217;ve had problems doing this with constant disk
accesses caused by
&lt;a href="https://www.reddit.com/r/synology/comments/xpn5rh/docker_constant_hdd_readwrite"&gt;container health checks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A neat feature of Synology hardware is their &lt;a href="https://quickconnect.to"&gt;Quickconnect&lt;/a&gt;
remote access, without needing a &lt;span class="caps"&gt;VPN&lt;/span&gt; or having an open port. This works with
the web interface and phone&amp;nbsp;apps.&lt;/p&gt;
&lt;p&gt;The single most important aspect of managing personal data is ensuring it is
robustly backed up. &lt;span class="caps"&gt;RAID&lt;/span&gt; 1 provides protection against loss of a single disk
(and Synology handles this well), but not against damage to the system such as would
happen in an accident or fire. To mitigate this, I have setup an off-site backup
using another Synology Diskstation &lt;span class="caps"&gt;NAS&lt;/span&gt;. A full incremental backup
is performed nightly using Synology&amp;#8217;s Hyperbackup. I have checked that files
are retrievable but I admit I have not tried a full system restore since it has
not yet been&amp;nbsp;necessary.&lt;/p&gt;
&lt;h2&gt;Linux&amp;nbsp;host&lt;/h2&gt;
&lt;p&gt;The second box in the picture above is a Lenovo ThinkCentre M75q Tiny &lt;span class="caps"&gt;PC&lt;/span&gt; that I
got to plug the gap in the Synology&amp;#8217;s capabilities, namely in running
additional services and providing a Linux host that I can use for development
etc, rather than paying for an under powered &lt;span class="caps"&gt;VPS&lt;/span&gt;. The machine has a Ryzen 5
&lt;span class="caps"&gt;3400GE&lt;/span&gt; processor with &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;  and a 500 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;. You can pick these
machines up very&amp;nbsp;cheaply.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/self-hosted/homepage.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/homepage_600x600.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Currently it&amp;nbsp;runs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gethomepage.dev"&gt;Homepage&lt;/a&gt; providing a general internal landing page for statuses and convenient&amp;nbsp;links.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freshrss.org"&gt;FreshRSS&lt;/a&gt; for aggregating and reading &lt;span class="caps"&gt;RSS&lt;/span&gt;&amp;nbsp;feeds.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://speedtest-tracker.dev"&gt;Speedtest Tracker&lt;/a&gt; for monitoring my internet&amp;nbsp;connection.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Yanson/octograph"&gt;Octograph&lt;/a&gt; for monitoring my home electricity use and&amp;nbsp;pricing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Access&lt;/h2&gt;
&lt;p&gt;Using Synology &lt;span class="caps"&gt;VPN&lt;/span&gt; server on the &lt;span class="caps"&gt;DS220&lt;/span&gt;+, I have an OpenVPN service setup that
allows me to access my home network remotely. This gives me access to the
various services, as well as to machines via &lt;span class="caps"&gt;RDP&lt;/span&gt; and &lt;span class="caps"&gt;SSH&lt;/span&gt;. Within the network, I
have a local &lt;span class="caps"&gt;DNS&lt;/span&gt; service (also running on the &lt;span class="caps"&gt;DS220&lt;/span&gt;+) to provide convenient
names for&amp;nbsp;devices.&lt;/p&gt;
&lt;h2&gt;Other&amp;nbsp;services&lt;/h2&gt;
&lt;p&gt;As I mentioned at the start, there are a number of third-party services that I
use. The key ones&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://proton.me"&gt;Proton&lt;/a&gt; primarily for email, calendar and&amp;nbsp;passwords.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com"&gt;Github&lt;/a&gt; for code and Github pages for hosting this website (at the time of&amp;nbsp;writing).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com"&gt;Digital Ocean&lt;/a&gt; for object storage with&amp;nbsp;Spaces.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com"&gt;Google Sheets&lt;/a&gt; for word processing and&amp;nbsp;spreadsheets.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://standardnotes.com"&gt;Standard notes&lt;/a&gt; for note taking, since they have
  recently been acquired by&amp;nbsp;Proton.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.icloud.com"&gt;Apple iCloud&lt;/a&gt; for contacts and&amp;nbsp;reminders.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.strava.com"&gt;Strava&lt;/a&gt; and &lt;a href="https://connect.garmin.com"&gt;Garmin&lt;/a&gt; for fitness&amp;nbsp;data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This list is not exhaustive but these services all hold valuable data that I
would not want to lose in the event the provider loses the data or I get
locked out of my account. Although these scenarios is unlikely, I mitigate the
risks by taking manual backups, albeit on a less frequent basis that I&amp;nbsp;should.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This note details hardware and software alternatives for operating personal services
that are east to setup and maintain, with scope to add much more functionality. This
approach provides a strong alternative to entrusting a third party to hold your data.
Moreover, it can be done cheaply too, with the cost of &lt;span class="caps"&gt;NAS&lt;/span&gt; setups being dominated by the
price of disks themselves and many great open-source software&amp;nbsp;options.&lt;/p&gt;
&lt;p&gt;&lt;a name="links"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Related&amp;nbsp;links&lt;/h2&gt;
&lt;p&gt;There are many great blog posts about self hosting of computing services. These
are a few that I have come&amp;nbsp;across.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://awesome-selfhosted.net"&gt;Awesome-Selfhosted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jnsgr.uk/2024/07/how-i-computer-in-2024"&gt;How I Computer in 2024&lt;/a&gt;, blog post by Jon&amp;nbsp;Seager.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.fidelramos.net/software/homelab"&gt;My homelab setup&lt;/a&gt;, blog post by Fidel&amp;nbsp;Ramos.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.devroom.io/2020/02/28/building-a-diy-home-server-with-freenas"&gt;Building a &lt;span class="caps"&gt;DIY&lt;/span&gt; Home Server with FreeNAS&lt;/a&gt;,&amp;nbsp;devroom.io.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Perspectives"/><category term="self-hosted"/></entry><entry><title>Discrete-event simulation</title><link href="https://jameswhanlon.com/discrete-event-simulation.html" rel="alternate"/><published>2024-08-14T00:00:00+02:00</published><updated>2024-08-14T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2024-08-14:/discrete-event-simulation.html</id><summary type="html">&lt;p&gt;How to build a simple discrete-event simulation with an example in&amp;nbsp;Rust&lt;/p&gt;</summary><content type="html">&lt;p&gt;Discrete event simulation (&lt;span class="caps"&gt;DES&lt;/span&gt;) is a methodology for modelling dynamic systems
as a sequence of events in time. There are plenty of places to read about &lt;span class="caps"&gt;DES&lt;/span&gt;,
but in this note I want to outline how it works and can be simply implement,
recognising several subtleties. &lt;span class="caps"&gt;DES&lt;/span&gt; is widely used in different areas where
analytical solutions are difficult; I am focusing on its use in modelling
digital logic and computer&amp;nbsp;systems.&lt;/p&gt;
&lt;p&gt;In a &lt;span class="caps"&gt;DES&lt;/span&gt;, each event is scheduled to occur at a particular point in time and
represents a change in the state of the system and the possible generation of
future events. Because there are no state changes between events, the
simulation jumps through time from one event to the next. These variable time
steps are in contrast with a discrete-event scheme with fixed timesteps. Fixed
timesteps are particularly suited to digital systems with clocked logic, where
each time increment corresponds to clock cycle. Fixed-time simulation has the
drawback that all time steps are evaluated regardless of whether anything
happens, although it is easier to reason about since everything proceeds in
lockstep. &lt;span class="caps"&gt;DES&lt;/span&gt; is inherently more flexible but can be harder to parallelise
because of the need to maintain a centralised event&amp;nbsp;list.&lt;/p&gt;
&lt;h2&gt;Operation&lt;/h2&gt;
&lt;p&gt;The main components of a &lt;span class="caps"&gt;DES&lt;/span&gt;&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;state&lt;/strong&gt; (or set of states) representing the components of the&amp;nbsp;system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Events&lt;/strong&gt;, that occur atomically at a particular instant and can update
  the system state and create new future&amp;nbsp;events.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;clock&lt;/strong&gt;, that records the simulation&amp;nbsp;time.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;list of future events&lt;/strong&gt; (the &lt;em&gt;event list&lt;/em&gt;). This is most often implemented
  as a priority queue with events queued in chronological order, soonest at
  the&amp;nbsp;front.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An outline of the &lt;span class="caps"&gt;DES&lt;/span&gt; algorithm is as&amp;nbsp;follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create one or more initial events and add them to the event&amp;nbsp;list.&lt;/li&gt;
&lt;li&gt;While the event list not empty:&lt;ul&gt;
&lt;li&gt;Choose a next event with the earliest&amp;nbsp;time.&lt;/li&gt;
&lt;li&gt;Advance simulation clock to time of&amp;nbsp;event.&lt;/li&gt;
&lt;li&gt;Execute the event.&lt;ul&gt;
&lt;li&gt;State updates are committed&amp;nbsp;immediately.&lt;/li&gt;
&lt;li&gt;New events are added to the event&amp;nbsp;queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simulation proceeds until there are no more events to process, or a maximum
time is&amp;nbsp;reached.&lt;/p&gt;
&lt;p&gt;During the simulation the following must be&amp;nbsp;ensured:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;For events that occur at the same time, it must be possible to execute them
   in any order, without affecting the behaviour of the simulation. In other
   words, the outcome of the simulation must not depend on any ordering of
   simultaneous&amp;nbsp;events.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Duplicate events must not be created. For example, if a component of the
   system is servicing some kind of input queue, when an item is added to the
   queue a corresponding &amp;#8216;service&amp;#8217; event must be created, but only when the queue
   is empty. As such, delegation of responsibility for event creation must be&amp;nbsp;clear.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To avoid violating point 1 above, each time step can be divided into
phases to impose an ordering of&amp;nbsp;events.&lt;/p&gt;
&lt;p&gt;The simplest case is to divide each timestep into two phases to serialise the
handling of two dependent events. As an example, consider nodes in a ring
topology that can pass tokens between themselves in one direction, with it
taking one timestep to for a token to traverse one node. Each node has two
associated events: &lt;em&gt;transmit&lt;/em&gt; and &lt;em&gt;receive&lt;/em&gt;. It must hold that a transmit event
for a node must be scheduled any receive events for that node have been
processed. By separating event processing in this way, there can be no
dependencies between the serialisation of transmit and receive events as they
are fetched from the simulation&amp;nbsp;queue.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/discrete-event-simulation/DES-ring.png" alt="DES of a ring of nodes that exchange a token with events for transmit and receive, separated by different phases within a simulation timestep."&gt;
  &lt;figcaption&gt;&lt;span class="caps"&gt;DES&lt;/span&gt; of a ring of nodes that exchange a token with events for transmit and receive, separated by different phases within a simulation timestep.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Extending this concept of phases, a timestep can be divided into an arbitrary
number of sub phases to model more complex behaviours. An interesting example
of this is SystemVerliog, which defines its execution semantics in terms of
multi-phase discrete event simulation. Roughly, a design or test bench defines
a set of stateful processes that respond to changes on their inputs to produce
outputs. Every change in state of a net or variable causes processes sensitive
to them to be evaluated. There may be many steps of evaluation to produce a
final output for the timestep. The timestep is divided into a fixed set of
ordered regions (17 in total) to provide predictable interactions with a
design. Within a region, many events may be processed and further ones
scheduled to resolve sensitivity&amp;nbsp;dependencies.&lt;/p&gt;
&lt;h2&gt;Example&amp;nbsp;implementation&lt;/h2&gt;
&lt;p&gt;Using the above example of a ring of nodes passing a token around them, the
following Rust code implements a &lt;span class="caps"&gt;DES&lt;/span&gt; of the system. This is a very simple &lt;span class="caps"&gt;DES&lt;/span&gt;
example and only one possible implementation, but sufficient to illustrate the
main&amp;nbsp;concepts.&lt;/p&gt;
&lt;p&gt;The main component is&amp;nbsp;a &lt;code&gt;Simulator&lt;/code&gt; object that maintains the event queue and
the system&amp;nbsp;state:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Simulator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;max_cycles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;event_queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BinaryHeap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Events have a type, a time at which they occur and node in the system that they
belong to.&amp;nbsp;The &lt;code&gt;node_id&lt;/code&gt; is used for directing state&amp;nbsp;updates.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Transmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Receive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The main simulation loop pops events off of the queue while it is not empty and
dispatches them to a handler&amp;nbsp;function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_cycles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_cycles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The&amp;nbsp;simulation &lt;code&gt;current_time&lt;/code&gt; is updated to the time of the current event being
processed. The event handler function implements the behaviour for each&amp;nbsp;event:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transmit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// Deactivate.&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Node {} inactive&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// Schedule receive at next node.&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;recv_event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Receive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schedule_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recv_event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Receive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// Activate.&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Node {} active&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// Schedule transmit.&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;send_event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_timestep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schedule_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;send_event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each event action updates the node state and creates a new event corresponding
to the passing of the token to the next node of the&amp;nbsp;ring.&lt;/p&gt;
&lt;p&gt;The simulation is setup with a initial receive event at node&amp;nbsp;0:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Simulator&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;initial_event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Receive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schedule_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And running it produces the&amp;nbsp;output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Node 0 active
Node 0 inactive
Node 1 active
Node 1 inactive
Node 2 active
Node 2 inactive
Node 3 active
Node 3 inactive
Node 4 active
Node 4 inactive
Node 5 active
Node 5 inactive
Node 6 active
Node 6 inactive
Node 7 active
Node 7 inactive
Node 8 active
Node 8 inactive
Node 9 active
Node 9 inactive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The complete source code for the example can be found in &lt;a href="https://gist.github.com/jameshanlon/a14685408f8b0f44919610d7f7cfa4a6"&gt;this
Gist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are many libraries for implementing &lt;span class="caps"&gt;DES&lt;/span&gt; such as
&lt;a href="https://systemc.org"&gt;SystemC&lt;/a&gt; and
&lt;a href="https://simpy.readthedocs.io/en/latest/"&gt;SimPy&lt;/a&gt;. Different libraries provide
varying approaches for creating and managing events with supporting
infrastructure, and their applicability depends on the application and system
being&amp;nbsp;simulated.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This note explains how &lt;span class="caps"&gt;DES&lt;/span&gt; simulation works and how it simple to implement. &lt;span class="caps"&gt;DES&lt;/span&gt;
is well suited to modelling synchronous and asynchronous digital systems, but
care must be taken to ensure that simultaneous events are scheduled without
dependencies and events are not&amp;nbsp;duplicated.&lt;/p&gt;
&lt;h2&gt;References / further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/discrete-event-simulator"&gt;GitHub&amp;nbsp;repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Discrete-event_simulation"&gt;Discrete-event simulation&lt;/a&gt;,&amp;nbsp;Wikipedia.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/List_of_discrete_event_simulation_software"&gt;List of &lt;span class="caps"&gt;DES&lt;/span&gt; software&lt;/a&gt;,&amp;nbsp;Wikipedia.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cs.cmu.edu/~music/cmsip/readings/intro-discrete-event-sim.html"&gt;Introduction to discrete event simulation&lt;/a&gt;, &lt;span class="caps"&gt;CMU&lt;/span&gt; lecture&amp;nbsp;notes.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dl.acm.org/doi/pdf/10.1145/6462.6485"&gt;Distributed discrete event simulation&lt;/a&gt;, Jayadev Misra&amp;nbsp;(1986).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dl.acm.org/doi/10.1145/84537.84545"&gt;Parallel discrete event simulation&lt;/a&gt;, Richard M. Fujimoto&amp;nbsp;(1990).&lt;/li&gt;
&lt;li&gt;Principles and Practices of Interconnection Networks, Chapter 24, William Dally, Brian Towles&amp;nbsp;(2004).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ieeexplore.ieee.org/document/8299595"&gt;1800-2017 SystemVerilog &lt;span class="caps"&gt;LRM&lt;/span&gt;&lt;/a&gt;,  section 4 &amp;#8216;Scheduling&amp;nbsp;semantics&amp;#8217;.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/></entry><entry><title>Review of heat pump use and performance</title><link href="https://jameswhanlon.com/review-of-heat-pump-use-and-performance.html" rel="alternate"/><published>2024-07-31T00:00:00+02:00</published><updated>2024-07-31T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2024-07-31:/review-of-heat-pump-use-and-performance.html</id><summary type="html">&lt;p&gt;A review of one year&amp;#8217;s worth of data from my home heat&amp;nbsp;pump.&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;:&lt;/em&gt;&lt;/strong&gt;  Updated October 2024 with improved&amp;nbsp;charts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/heat-pump-cropped.jpg" alt="My 10kW Vaillant Arotherm
Plus."&gt;
  &lt;figcaption&gt;My 10kW Vaillant Arotherm
Plus.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I had a 10 kW Vaillant Arotherm heat pump installed in July 2022, and a year
later a &lt;a href="https://www.vaillant.co.uk/product-systems/smart-controls/myvaillant-connect-internet-gateway"&gt;Vaillant Sensonet gateway&lt;/a&gt;, which provides monitoring and
logging services via the &amp;#8216;myVaillant&amp;#8217; smartphone app. Since I now have a year&amp;#8217;s
worth of data, this note reviews what has been logged to see how the system is&amp;nbsp;performing.&lt;/p&gt;
&lt;p&gt;The heat pump serves my house of approximately 90 square meters internal area.
I have previously posted about the building&amp;#8217;s &lt;a href="home-thermal-imaging-survey.html"&gt;energy
efficiency&lt;/a&gt; and &lt;a href="cornish-unit-house-retrofit-insulation.html"&gt;additional first floor
insulation&lt;/a&gt; added. This pump&amp;#8217;s
capacity exceeds the current requirements of the house, but we are planning an
extension in the near&amp;nbsp;future.&lt;/p&gt;
&lt;h2&gt;System&amp;nbsp;operation&lt;/h2&gt;
&lt;p&gt;The way I run the system is for space heating to run continuously with a fixed
temperature of 19 degrees C is set in the downstairs hallway (a central point
in the house), and hot water to run continuously at 50 degrees C. In the first
year of running the system, I experimented with running heating and hot water
for set periods during each day of the week, but I found that the heat pump had
to work hard to bring the system and the fabric of the house back up to&amp;nbsp;temperature.&lt;/p&gt;
&lt;p&gt;I was advised that continuous operation was more efficient and since the house
is almost always occupied, this matched our use. At that point I hadn&amp;#8217;t taken a
close look at the measured performance and was just monitoring the electricity
demand ad hoc. It is not to say that running the system with setback
temperatures would not be effective and may better match occupancy: see
analysis from &lt;a href="https://www.heatgeek.com/should-your-heating-be-left-on-all-the-time-or-not"&gt;Heatgeek&lt;/a&gt; or &lt;a href="https://protonsforbreakfast.wordpress.com/2022/12/19/setback-should-you-lower-heating-overnight"&gt;Protons for
Breakfast&lt;/a&gt; on this subject, But for me, having a continuous
temperature is the most comfortable and seems to work&amp;nbsp;well.&lt;/p&gt;
&lt;h2&gt;The &lt;em&gt;myViallant&lt;/em&gt;&amp;nbsp;app&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;myVaillant&lt;/em&gt; app usefully provides a button to download all logged data per
year in a set of &lt;span class="caps"&gt;CSV&lt;/span&gt; files and this code is &lt;a href="https://github.com/jameshanlon/home-energy-data"&gt;available on
Github&lt;/a&gt;. I have summarised the year period from July 2023 to
July 2024 in the following charts. Having read this &lt;a href="https://protonsforbreakfast.wordpress.com/2023/02/06/the-myvaillant-app-a-review"&gt;&lt;span class="caps"&gt;PFB&lt;/span&gt; review&lt;/a&gt;,
I am aware that there are issues with the quality of the logged data.
The review measured a ~8% error in electricity consumed and a ~20% error in the heat
energy produced, as well as pointing out many logged values are quantised to
kWh units, which I also observe in my data. Significantly, this means that the
raw Vaillant data under reports &lt;span class="caps"&gt;COP&lt;/span&gt;. I don&amp;#8217;t have a point of comparison with
with an alternative measurement of the consumed and generated energy (although I
would like to install an &lt;a href="https://openenergymonitor.org"&gt;OpenEnergyMonitor&lt;/a&gt; to do this).
Despite the potential inaccuracies of the Vaillant data, it remains useful for
a high-level review of the&amp;nbsp;system.&lt;/p&gt;
&lt;h2&gt;Analysis&lt;/h2&gt;
&lt;p&gt;The overall performance of the system for the year from July 2023 to July 2024
is summarised in the following&amp;nbsp;table.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Metric&lt;/th&gt;
      &lt;th scope="col"&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
 &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Consumed electricity heating&lt;/td&gt;
      &lt;td&gt;1.34 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Consumed electricity hot water&lt;/td&gt;
      &lt;td&gt;1.01 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total consumed electricity&lt;/td&gt;
      &lt;td&gt;2.36 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Average daily electricity consumption&lt;/td&gt;
      &lt;td&gt;6.65 kWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Heat generated heating&lt;/td&gt;
      &lt;td&gt;4.91 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Heat generated hot water&lt;/td&gt;
      &lt;td&gt;3.13 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total heat generated&lt;/td&gt;
      &lt;td&gt;8.04 MWh&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Heating &lt;span class="caps"&gt;SCOP&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;3.65&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hot water &lt;span class="caps"&gt;SCOP&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;3.09&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total &lt;span class="caps"&gt;SCOP&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;3.41&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Note that when scaling consumed electricity by 8% and generated electricity by
20% to adjust for possible inaccuracy, heating &lt;span class="caps"&gt;SCOP&lt;/span&gt; is 4.06, hot water &lt;span class="caps"&gt;SCOP&lt;/span&gt; is
3.43 and they are combined at 3.79. Note also, that these figures do not include
the electricity used for the weekly Legionella purge performed by an immersion
heater I have installed in my&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Looking more closely at consumption, the chart below shows all measurements
over this period for heating, hot water and their&amp;nbsp;combination.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/consumed.png" alt="Electrical energy consumed in kWh."&gt;
  &lt;figcaption&gt;Electrical energy consumed in kWh.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Most obviously, electricity consumption during the winter months increases
significantly when the heat pump is using approximately 10 kWh per day. There
are two spikes in November and January where temperatures went below zero, and
at these times consumption went up close to 30 kWh per day. As expected,
electricity consumption for hot water is more consistent throughout the year
with a lesser increase through the winter months. The short periods where both
drop to zero are due either to a holiday and the system being in &amp;#8216;absence&amp;#8217; mode
or a technical issue. The technical issue has been due to a loss of pressure in
the system, requiring a manual top up from the mains water&amp;nbsp;supply.&lt;/p&gt;
&lt;p&gt;The next chart is the heat energy generated, which is tightly correlated with
the consumption&amp;nbsp;graph.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/generated.png" alt="Heat energy generated (hot water and heating) in kWh."&gt;
  &lt;figcaption&gt;Heat energy generated (hot water and heating) in kWh.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Combining the previous two charts by calculating the ratio between generated and
consumed, gives the coefficient of performance (&lt;span class="caps"&gt;COP&lt;/span&gt;). A handful of measurements
produced very large &lt;span class="caps"&gt;COP&lt;/span&gt; values, that are unrealistic, so I have clipped these
with a maximum &lt;span class="caps"&gt;COP&lt;/span&gt; of&amp;nbsp;6.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/COP.png" alt="COP calculated by dividing heat generated by electrical energy consumed."&gt;
  &lt;figcaption&gt;&lt;span class="caps"&gt;COP&lt;/span&gt; calculated by dividing heat generated by electrical energy consumed.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This is the same &lt;span class="caps"&gt;COP&lt;/span&gt; data averaged over weekly&amp;nbsp;intervals.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/weekly-COP.png" alt="Weekly averaged COP."&gt;
  &lt;figcaption&gt;Weekly averaged &lt;span class="caps"&gt;COP&lt;/span&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The next chart is a different presentation of the &lt;span class="caps"&gt;COP&lt;/span&gt; data, with &lt;span class="caps"&gt;COP&lt;/span&gt; plotted as
a function of heat output. It&amp;#8217;s clear that peak &lt;span class="caps"&gt;COP&lt;/span&gt; is at ~10 kW heat output,
but there is little penalty in efficiency between that and the highest recorded&amp;nbsp;output.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/heat-output-vs-COP.png" alt="Heat output versus weekly averaged COP."&gt;
  &lt;figcaption&gt;Heat output versus weekly averaged &lt;span class="caps"&gt;COP&lt;/span&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Looking at the temperature of the hot water tank, this stays constant as expected
but with a few exceptions: when I changed the temperature from 45 to 50 degrees C
in October 2023; when the system has been off or out of order; and when every week
on a Monday the immersion heater kicks in to perform a Legionella purge (which
curiously it has stopped since March 2024. After later investigation this
appears to be a faulty timer or immersion heater, so I switched to performing
the purge using the heat pump&amp;nbsp;itself).&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/water-temperature.png" alt="Hot water temperature in degrees Celsius."&gt;
  &lt;figcaption&gt;Hot water temperature in degrees Celsius.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Finally, we have a plot of internal (red) vs external (blue) temperature in
degrees C. This clearly shows that the 19 degrees C target was maintained
throughout the year, notwithstanding the periods of absence/downtime and on
particular hot days when the temperature rose above the target. Given how
quickly our summers are changing with more intense heat, having a system that
can also perform cooling would be a big benefit. But overall, I think this
chart well represents the benefit of having a heat pump, providing a home
environment with a continuous temperature throughout the&amp;nbsp;year.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/internal-external-temperature.png" alt="Internal and external temperatures in degrees Celsius."&gt;
  &lt;figcaption&gt;Internal and external temperatures in degrees Celsius.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;For the same period I obtained the electricity use and cost data from Octopus
using their excellent &lt;span class="caps"&gt;API&lt;/span&gt; via the &lt;a href="https://github.com/Yanson/octograph"&gt;Octograph tool&lt;/a&gt;, visualised below
on a Grafana dashboard. According to the Vaillant data, the heat pump used 2.39
MWh of energy, which is only 32% of the total electricity use. I am suspicious
that this is inaccurate, even factoring in an 8% underestimate from the Vaillant
measurements. I would expect the heat pump to be using more like half of total
electricity on average, given that other electricity use is cooking and
appliances etc, but perhaps I am wrong. Otherwise the usage profile matches between
the two data&amp;nbsp;sets.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/heat-pump/Grafana-Octopus-electricity-use.png" alt="Electricity use from Octopus data."&gt;
  &lt;figcaption&gt;Electricity use from Octopus data.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;The data collected by the Vaillant heat pump control system appears to be
somewhat inaccurate but nevertheless provides a high-level overview of the
performance of the system. I&amp;#8217;ve been very pleased with how it has performed
over the last year, and this is backed up by the statistics I have collated.
With work planned on the house, there are more thermal-efficiency gains to be
made, so hopefully I can further improve it&amp;#8217;s running&amp;nbsp;efficiency.&lt;/p&gt;
&lt;h2&gt;References and further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://protonsforbreakfast.wordpress.com/heat-pump-articles/"&gt;Protons for Breakfast, articles about heat
  pumps&lt;/a&gt; is a
  fantastic set of articles by physicist Michael de&amp;nbsp;Podesta.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://energy-stats.uk"&gt;Energy Stats&lt;/a&gt; provides pricing data for various
  Octopus Energy&amp;nbsp;tariffs.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.guylipman.com/octopus"&gt;Guy Lipman&amp;#8217;s Octopus Energy resources&lt;/a&gt; is
  a collection of notes focusing on using the Octopus &lt;span class="caps"&gt;API&lt;/span&gt; to access energy&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://octopus.energy/blog/agile-smart-home-diy"&gt;Octopus Energy &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; is the
  landing page for using their &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Yanson/octograph"&gt;Octograph (Github)&lt;/a&gt; A Python tool for
  extracting Octopus Energy meter readings to InfluxDB and&amp;nbsp;Grafana.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Home and Sustainability"/><category term="sustainability"/></entry><entry><title>Silicon infrastructure</title><link href="https://jameswhanlon.com/silicon-infrastructure.html" rel="alternate"/><published>2023-08-02T00:00:00+02:00</published><updated>2023-08-02T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2023-08-02:/silicon-infrastructure.html</id><summary type="html">&lt;p&gt;Thoughts on the requirements of software infrastructure
to support chip&amp;nbsp;design.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Modern chip design differs to conventional software engineering in three
fundamental aspects that require a somewhat different approach to project&amp;nbsp;development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Transformations and representations&lt;/strong&gt;. The creation of a chip design from
  a source-level representation through to a final &lt;span class="caps"&gt;GDSII&lt;/span&gt; description of the
  layout involves many stages of incremental transformations of the circuit and
  layout, and then incremental assembly of components into various subsystems
  before finally the entire chip. At various stages through this process, checks
  are performed on the design typically using simplified representations to
  reduce complexity and make run times&amp;nbsp;practical.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tooling&lt;/strong&gt;. Compared to software tooling, standard chip-design tooling
  (known in the industry as &lt;em&gt;electronic design automation&lt;/em&gt;) :
    (1) is almost all proprietary and used under license, meaning that interactive
    and automated use is limited and at odds with a continuous-integration model
    of development;
    (2) can have long run times (upwards of 12 hours for a job are not uncommon) and produce
    vast quantities of data, making it very unattractive to rerun something
    unless absolutely necessary; and
    (3) can be non-deterministic in that rerunning a job with the same set of inputs
    produces a different&amp;nbsp;output.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tape out&lt;/strong&gt;. When a design is released for manufacture (known in the
  industry as a &lt;em&gt;tape out&lt;/em&gt;), there are typically high non-recoverable expenses associated
  with setting up the processes and a long lead time in receiving a (hopefully)
  working device. There are two implications of this situation:
    (1) chip tape outs precludes incremental releases, for example to fix trivial bugs, and
    therefore means that the confidence in the correct functionality of the
    design must be very high;
    (2) post tape out, the design source code is effectively frozen forever more for
    the purposes of debug and&amp;nbsp;analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite these differences, many of the techniques and tools from software
engineering can readily be applied to chip development, particularly to manage
complexity and maintain high standards of code quality, testing and
integration. This note lays out some thoughts and opinions on the components
and structure of a software infrastructure to build&amp;nbsp;chips.&lt;/p&gt;
&lt;h3&gt;Table of&amp;nbsp;contents&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#aims"&gt;Aims&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#principles"&gt;Guiding&amp;nbsp;principles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;Flows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#model"&gt;Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#details"&gt;Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#acknowledgements"&gt;Acknowledgments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#related-projects"&gt;Related&amp;nbsp;projects&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Aims &lt;a name="aims" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The overall objective of a silicon infrastructure is to &lt;strong&gt;support the
development of a verified chip design from &lt;span class="caps"&gt;RTL&lt;/span&gt; to &lt;span class="caps"&gt;GDSII&lt;/span&gt;&lt;/strong&gt;. To make this more
specific, I also define the following capabilities that should be supported as
an overall philosophy of the approach that is explored in this&amp;nbsp;note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;To &lt;strong&gt;rerun everything from scratch&lt;/strong&gt;, requiring full
  automation of an the end-to-end flow. This is intended to: (1) distribute the
  task of integrating components of a design across a team, thereby revealing
  issues at as earlier stage in the project as possible to avoid disruptive
  changes towards the end; (2) enable faster design iteration; and (3)
  provide traceability of results (a foundation for the next&amp;nbsp;aim).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provide a &lt;strong&gt;full audit trail&lt;/strong&gt; such that a release of a design for tape out
  has data and a set of reports, logs, coverage metrics, documentation and
  signoffs that are traceable back to the original &lt;span class="caps"&gt;RTL&lt;/span&gt; source files. This is
  important for building confidence to tape out, as well as providing information
  for future work on a completed&amp;nbsp;design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support &lt;strong&gt;multiple chips and frozen designs&lt;/strong&gt; to keep previous generations
  alive for debug of silicon issues and/or as a basis for a incremental tape out
  (known as a &lt;em&gt;respin&lt;/em&gt;), and to allow multiple designs to be built&amp;nbsp;concurrently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Guiding principles &lt;a name="principles" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think it is useful to underpin the aims, implementation and operation of a
chip-design infrastructure are a set of guiding principles for the project team
to employ when design decisions need to be made.  These principles are formed
from my own experience and through conversations with others. I am sure that
alternative foundations can be constructed and argued&amp;nbsp;for.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simple and explicit&lt;/strong&gt;. Build a complex system using simple, well-defined
components composed and controlled using explicit mechanisms. Conversely, avoid
easy-to-use high-level interfaces that hide important behaviours. This borrows
from the &lt;a href="https://peps.python.org/pep-0020/"&gt;Zen of Python&lt;/a&gt;: &lt;em&gt;explicit is better
than implicit and simple is better than complex&lt;/em&gt;. Examples include avoiding the
use of global variables, preferring flat rather than nested, preferring
decisions to be made explicitly and avoiding special cases that break the&amp;nbsp;rules.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use a monorepository&lt;/strong&gt;. One repository should contain all the code for all
active projects. This enhances all team members&amp;#8217; ability to integrate their
changes across projects and removes barriers to interaction between different
teams and/or areas of the design. Other &lt;a href="https://en.wikipedia.org/wiki/Monorepo"&gt;general
benefits&lt;/a&gt; of a monorepository are the
ability to reuse code and do large-scale refactoring. A great deal of care must
be taken to manage dependencies between projects/components within a
monorepository. Without such care, unexpected interdependencies can cause
unexpected breakages, prevent refactoring and preclude focused testing. In
general: isolate components by restricting them to only be able to access their
listed dependencies; divide components by function and abstraction level (eg
don&amp;#8217;t group by language or technology); and use a standard structure for each
component (such&amp;nbsp;as &lt;code&gt;lib&lt;/code&gt;, &lt;code&gt;sources&lt;/code&gt;, &lt;code&gt;README&lt;/code&gt; etc).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Embrace open source&lt;/strong&gt;. To save on effort, leverage freely-available tools
and libraries wherever possible in the infrastructure, rather than implementing
custom versions. Where open source is used, contributions back upstream benefit
the community and help to align the project with the way it is being deployed.
This particularly applies to open source in the &lt;span class="caps"&gt;ASIC&lt;/span&gt;/&lt;span class="caps"&gt;FPGA&lt;/span&gt; domain, where
&lt;a href="https://github.com/aolofsson/awesome-opensource-hardware"&gt;open-source software&lt;/a&gt; is unencumbered by licensing restrictions. Often
chip projects will be on tight schedules, so careful judgment of the
effort-benefit tradeoff must be&amp;nbsp;made.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance is important&lt;/strong&gt;. With the ability to rerun everything from
scratch coupled with a multi-chip and monorepository approach, the compute
demands can scale quickly so it is crucial that the infrastructure is
performant. This can easily become a problem with codebases make extensive use
of a scripting language such as Python.  Mitigations include writing (or
rewriting) parts in a lower-level language such as C++, and setting things up in
such a way that this Python and C++ components can interoperate cleanly (eg
well-defined boundaries and&amp;nbsp;dependencies).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Flows &lt;a name="flows" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This section outlines the high-level &lt;em&gt;flows&lt;/em&gt; that a chip-design infrastructure
needs to support, meaning (typically) a sequence of steps to achieve some
&lt;em&gt;task&lt;/em&gt;. This is not meant to be exhaustive, but characteristic of the types of
tasks that need to be performed. Flows can be just a single step or can be
composed together to create different flows, but always have defined inputs and
outputs. I use the term &lt;em&gt;job&lt;/em&gt; to mean a particular program or script that is
executed, typically corresponding to a&amp;nbsp;step.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Design representation&lt;/strong&gt;. To read a design into a tool, the design must have
  a complete representation including tool-agnostic configuration, macro
  defines, library files and &lt;span class="caps"&gt;RTL&lt;/span&gt; sources. Often, &lt;span class="caps"&gt;RTL&lt;/span&gt; code will need to be
  generated programatically using templates or other types of code generators. It
  is also typical that a design will be implemented in a hierarchical fashion, so
  a configuration step must gather together the required modules and package it
  into a single representation. As an example, the open-source &lt;a href="https://github.com/pulp-platform/bender"&gt;Bender&lt;/a&gt;
  dependency management tool provides very similar&amp;nbsp;functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/design-representation.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Verification representation&lt;/strong&gt;. For the purposes of simulation and
  analysis, a verification representation is a variation of a design
  representation, adding configuration and macro defines, source files for a test
  bench, monitors, assertions etc, and possibly substituting parts of the design
  for fast models or block boxes. These verification components will likely live
  with the corresponding parts of the design and be collected together as they
  were for the design representation during a configuration&amp;nbsp;step.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/verif-representation.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lint checking&lt;/strong&gt;. &lt;span class="caps"&gt;RTL&lt;/span&gt; source code can be checked for basic coding issues
  (referred to as &lt;em&gt;linting&lt;/em&gt;) by passing it through tools that perform various
  built-in or custom checks. The input to this task is the specification of a
  design and the output is a list of warnings to be reviewed. Example open-source
  tools that can be used for linting are &lt;a href="https://verilator.org/guide/latest"&gt;Verilator&lt;/a&gt;,
  &lt;a href="https://chipsalliance.github.io/verible"&gt;Verible&lt;/a&gt;, &lt;a href="https://sv-lang.com"&gt;Slang&lt;/a&gt;, &lt;a href="https://github.com/dalance/svlint"&gt;svlint&lt;/a&gt; and &lt;a href="https://yosyshq.net/yosys"&gt;Yosys&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/lint-check.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/lint-check_1000x1000.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CDC&lt;/span&gt; and &lt;span class="caps"&gt;RDC&lt;/span&gt; checking&lt;/strong&gt;. Clock- and reset-domain crossings can be checked
  automatically with tools that analyse a design, typically with a set of
  annotations and constraints. The output will be warning messages from the
  checker that need to be&amp;nbsp;investigated.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/cdc-rdc-check.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simulation testbench&lt;/strong&gt;. A simulation test bench requires a representation
  of the design, a verification environment and test stimulus. Test stimulus is
  often randomly generated. Coverage (structural or functional) can be collected
  during simulation and when many test instances are run for a particular test
  generator or over a larger regression of different test generators, coverage
  may need to be merged then reported on. Simulation is typically performed on an
  &lt;span class="caps"&gt;RTL&lt;/span&gt; representation, but can also be performed on gate-level netlists and with
  and without delay&amp;nbsp;annotations.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/simulation-flow.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Formal property test bench&lt;/strong&gt;. Analysing and proving formal properties of a
  design is a complementary technique to standard functional coverage. Inputs
  to this are a verification representation of the design and a set of
  assumptions and properties to be&amp;nbsp;checked.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/formal-property-check.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Formal equivalence check&lt;/strong&gt;. As a design is incrementally transformed
  between &lt;span class="caps"&gt;RTL&lt;/span&gt; and &lt;span class="caps"&gt;GDSII&lt;/span&gt;, it is essential to perform equivalence checks to
  prove that each transformation maintains the functional behaviour of the
  design. Inputs to an equivalence check are two representations, typically
  called a &lt;em&gt;reference&lt;/em&gt; that is the baseline and an &lt;em&gt;implementation&lt;/em&gt; to&amp;nbsp;check.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/equivalence-flow.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Physical build&lt;/strong&gt;. All flows up to this point have mainly operated on &lt;span class="caps"&gt;RTL&lt;/span&gt;
  representations of a design. A physical build flow starts off by
  transforming &lt;span class="caps"&gt;RTL&lt;/span&gt; into gates using a synthesis tool, then progressively
  transforming the design into a set of two-dimensional layers. Following synthesis
  are: scan insertion for &lt;span class="caps"&gt;DFT&lt;/span&gt;, floorplanning (placing ports and macros),
  placement (placing cells), clock tree synthesis, routing (establishing all
  required connections using the available routing layers, finishing and
  checking. See &lt;a href="https://github.com/The-OpenROAD-Project/OpenROAD"&gt;OpenROAD&lt;/a&gt; for an example open source physical build&amp;nbsp;flow.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/silicon-infra/phys-build-flow.png" alt="No alt text"&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A note on &lt;span class="caps"&gt;DFT&lt;/span&gt;&lt;/strong&gt;. A central aspect of any chip design is the &lt;span class="caps"&gt;DFT&lt;/span&gt; (device
test) strategy. Testability is achieved by adding logic in the form of
&lt;em&gt;instruments&lt;/em&gt; and &lt;em&gt;connectivity&lt;/em&gt; to make the the existing logic
&lt;em&gt;controllable&lt;/em&gt; and &lt;em&gt;observable&lt;/em&gt;. The means by which this is done and the
point in the development process is heavily dependent on the design and the
tooling used. Typically, &lt;span class="caps"&gt;DFT&lt;/span&gt; logic is inserted using automated tools during
the physical build but increasingly it is being added in &lt;span class="caps"&gt;RTL&lt;/span&gt; also using
automated tooling - either way adding additional transformation steps to the
front- or back-end&amp;nbsp;flows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A note on physical builds&lt;/strong&gt;. There are two unique aspects of physical
builds that present challenges for the infrastructure presented in this note.
The first is that physical &lt;span class="caps"&gt;EDA&lt;/span&gt; tools do not always produce the same output
given the same inputs due to the nature of the optimisation algorithms they
use. The second is that close to the closure of a design component, manual
interventions will be made to address localised issues in the design. The
combination of these issues mean that it is not possible to rerun physical
builds from scratch and achieve satisfactory results. Therefore, a silicon
infrastructure must be able to support frozen data from particular flow&amp;nbsp;stages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Model &lt;a name="model" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A model for a silicon infrastructure that captures the use cases described is a
hierarchical collection of &lt;em&gt;tasks&lt;/em&gt; that consume inputs and produce outputs. A
task can be dependent on another task by consuming that task&amp;#8217;s output and
tasks can be composed together in this way into &lt;em&gt;flows&lt;/em&gt;. The set of tasks
implementing a flow form an acyclic directed graph (&lt;span class="caps"&gt;DAG&lt;/span&gt;) with nodes representing
fixed inputs or jobs and edges corresponding to dependencies. The structure of
this graph is determined statically (ie without any dependence on runtime
data). Execution proceeds by running tasks whose inputs are ready and letting
the task run to completion before marking its outputs as available to trigger
the execution of more tasks or the termination of the&amp;nbsp;flow.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;task&lt;/em&gt; is defined&amp;nbsp;by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A set of&amp;nbsp;inputs.&lt;/li&gt;
&lt;li&gt;A set of&amp;nbsp;outputs.&lt;/li&gt;
&lt;li&gt;A set of configuration&amp;nbsp;values.&lt;/li&gt;
&lt;li&gt;A set of resource requirements (time, memory,&amp;nbsp;cores).&lt;/li&gt;
&lt;li&gt;An &lt;em&gt;action&lt;/em&gt; that that operates only on the inputs and must produce all the
  of the outputs, typically achieved by executing a script or separate&amp;nbsp;tool.&lt;/li&gt;
&lt;li&gt;If a task attempts to access an input that is not specified, then an error is&amp;nbsp;raised.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;em&gt;flow&lt;/em&gt; is a hierarchical task and defined&amp;nbsp;by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A set of&amp;nbsp;inputs.&lt;/li&gt;
&lt;li&gt;A set of&amp;nbsp;outputs.&lt;/li&gt;
&lt;li&gt;A set of configuration&amp;nbsp;values.&lt;/li&gt;
&lt;li&gt;A set of resource&amp;nbsp;requirements.&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;action&lt;/em&gt; consisting of executing one or more tasks according to their
  dependencies. Inputs and outputs of the flow must be connected to the sub
  tasks and similarly for dependencies between sub&amp;nbsp;tasks.&lt;/li&gt;
&lt;li&gt;Tasks can be specified using &lt;em&gt;replication&lt;/em&gt; with static bounds
  to create arrays, and &lt;em&gt;conditionality&lt;/em&gt; to include or exclude tasks dependent on
  configuration&amp;nbsp;values.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Configuration values are used to control the behaviour of a flow or task.
A flow can propagate configuration into its sub tasks, but it must do so
explicitly. Configuration values can be set on the command line. Example use of
configuration options is to control features like debug flags, substitution
of components of the design for simulation, or the inclusion of
tests to run in a&amp;nbsp;regression.&lt;/p&gt;
&lt;p&gt;There are a number of similar programming models that support scalable
pipelined data processing. In the field of genomics, the &lt;a href="https://openwdl.org"&gt;Workflow Description
Language&lt;/a&gt; (&lt;span class="caps"&gt;WDL&lt;/span&gt;) and &lt;a href="https://www.commonwl.org"&gt;Common Workflow Language&lt;/a&gt; (&lt;span class="caps"&gt;CWL&lt;/span&gt;) are open
programming language specifications. Example implementations of &lt;span class="caps"&gt;WDL&lt;/span&gt; are
&lt;a href="https://github.com/chanzuckerberg/miniwdl"&gt;MiniWDL&lt;/a&gt; and &lt;a href="https://cromwell.readthedocs.io"&gt;Cromwell&lt;/a&gt;, and of &lt;span class="caps"&gt;CWL&lt;/span&gt; are &lt;a href="https://github.com/common-workflow-language/cwltool"&gt;cwltool&lt;/a&gt;
and &lt;a href="http://toil.ucsc-cgl.org"&gt;Toil&lt;/a&gt;. A &lt;a href="https://www.nextflow.io"&gt;Nextflow&lt;/a&gt; offers comparable features but is
based on a domain-specific language implemented in Groovy. This
&lt;a href="https://www.nature.com/articles/s41598-021-99288-8"&gt;paper&lt;/a&gt; offers a good comparison of &lt;span class="caps"&gt;WDL&lt;/span&gt;, &lt;span class="caps"&gt;CWL&lt;/span&gt; and Nextflow. Also
worth mentioning are &lt;a href="https://snakemake.github.io"&gt;Snakemake&lt;/a&gt;, &lt;a href="https://airflow.apache.org"&gt;Apache Airflow&lt;/a&gt;, &lt;a href="https://beam.apache.org"&gt;Apache
Beam&lt;/a&gt;, &lt;a href="https://github.com/spotify/luigi"&gt;Luigi&lt;/a&gt; and &lt;a href="https://flyte.org"&gt;Flyte&lt;/a&gt;. I&amp;#8217;m still investigating the
suitability of these tools for Silicon design&amp;nbsp;workloads.&lt;/p&gt;
&lt;h2&gt;Implementation details &lt;a name="details" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This section records some important details to consider when implementing a silicon
flow, as well as some nice-to-have&amp;nbsp;features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Environment&lt;/strong&gt;. A controlled environment execution environment with specific
  tool versions for reproducability and legacy support. Container technology
  supports this requirement very will with implementations such as
  &lt;a href="https://apptainer.org"&gt;Singularity/Apptainer&lt;/a&gt;. A lighter-weight solution is
  &lt;a href="https://github.com/enfabrica/enkit/tree/master/faketree"&gt;faketree&lt;/a&gt; for managing filesystem layout in a dynamic way to meet
  the constraints of &lt;span class="caps"&gt;EDA&lt;/span&gt;&amp;nbsp;tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access to compute&lt;/strong&gt;. Dispatching of jobs to compute resources such as a
  compute cluster requires interaction with a queuing system such as
  &lt;a href="https://slurm.schedmd.com"&gt;Slurm&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Logging&lt;/strong&gt;. Extensive logging of job statuses is important for a
  compute-intensive workload. Straightforward access to these logs for
  inspection during and after the run should be provided, likely through a
  web-based&amp;nbsp;dashboard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fault tolerance&lt;/strong&gt;. Flows should be robust to failures. When an task failure
  does occur, the correct statuses should be propagated up any hierarchy of
  tasks to provides visibility of the issue. The logging infrastructure should
  record any progress that was made, providing a starting point for debug or to
  restart the task. It should be straightforward to rerun part of a job that has
  failed in a reproducible&amp;nbsp;way.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Storage&lt;/strong&gt;. The use of a shared filesystem such as &lt;span class="caps"&gt;NFS&lt;/span&gt; is typical in silicon
  &lt;span class="caps"&gt;EDA&lt;/span&gt; flows, however it creates a single point of failure and has limited
  scalability. An alternative shared storage system is object storage such as
  &lt;a href="https://min.io"&gt;MinIO&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Releasing&lt;/strong&gt;. It should be simple to release data from the repository into
  immutable storage that can then be referenced as a&amp;nbsp;dependency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Periodic jobs&lt;/strong&gt;. A mechanism for running periodic jobs is required to
  implement a continuous-integration (&lt;span class="caps"&gt;CI&lt;/span&gt;) and/or continuous-delivery (&lt;span class="caps"&gt;CD&lt;/span&gt;).
  &lt;a href="https://www.jenkins.io"&gt;Jenkins&lt;/a&gt;, &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; or &lt;a href="https://docs.gitlab.com/ee/ci"&gt;GitLab &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt;&lt;/a&gt;
  are all directly applicable&amp;nbsp;here.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summary &lt;a name="summary" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This note outlines the principles and requirements for a modern software
infrastructure to build chips. This is very different to conventional software
engineering due to fundamental differences in processes, and is likely to be
quite different from the typical methodologies used in conventional silicon
design. Based on some simple use cases, a model is proposed that abstracts the
details of resource allocation and data movement by providing tasks with inputs
and outputs as primitives. Surprisingly, there already exist a family of tools
from data science that employ a very similar&amp;nbsp;model.&lt;/p&gt;
&lt;h2&gt;Acknowledgments &lt;a name="acknowledgements" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The motivation for writing this note came from recent discussions on building a
from-scratch silicon infrastructure with &lt;a href="http://www.jpallister.com"&gt;James Pallister&lt;/a&gt; and &lt;a href="https://intuity.io"&gt;Peter
Birch&lt;/a&gt;. This note is a synthesis of ideas from those&amp;nbsp;conversations.&lt;/p&gt;
&lt;h2&gt;Related projects &lt;a name="related-projects" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gator.intuity.io"&gt;Gator&lt;/a&gt;, a framework for running a hierarchy of
  jobs and aggregating logs, metrics, resource utilisation, and&amp;nbsp;artefacts.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/blockwork-eda/blockwork"&gt;Blockwork&lt;/a&gt;, is a build system and
  orchestrator for silicon&amp;nbsp;design.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blu-blade.readthedocs.io"&gt;Blade&lt;/a&gt; is a tool for autogenerating
  modules, interconnects and register definitions from an &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;schema.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/siliconcompiler/siliconcompiler"&gt;Siliconcompiler&lt;/a&gt; is a modular
  build system for silicon&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;Berkeley &lt;a href="https://github.com/ucb-bar/chipyard"&gt;Chipyard&lt;/a&gt; is an agile framework
  for hardware design, using Chisel for &lt;span class="caps"&gt;RTL&lt;/span&gt;&amp;nbsp;specification.&lt;/li&gt;
&lt;li&gt;Berkeley &lt;a href="https://github.com/ucb-bar/hammer"&gt;Hammer&lt;/a&gt; is a physical design&amp;nbsp;framework.&lt;/li&gt;
&lt;li&gt;Pulp Platform &lt;a href="https://github.com/pulp-platform/bender"&gt;Bender&lt;/a&gt; is a dependency
  management tool for hardware design&amp;nbsp;projects.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dungspreader.blogspot.com/"&gt;Rich Porter&amp;#8217;s series on digital verification&lt;/a&gt;
  and &lt;a href="https://github.com/rporter/verilog_integration"&gt;source code&lt;/a&gt; for the&amp;nbsp;project.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/enfabrica/melding-hardware-and-software-a-story-in-the-making-bcce28b821a8"&gt;Melding hardware and software: a story in the making&lt;/a&gt;,
  a position piece by Enfabrica on their approach to &lt;span class="caps"&gt;ASIC&lt;/span&gt;&amp;nbsp;design.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="microelectronics"/><category term="verilog"/></entry><entry><title>Building a Python processor</title><link href="https://jameswhanlon.com/building-a-python-processor.html" rel="alternate"/><published>2023-06-27T00:00:00+02:00</published><updated>2023-06-27T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2023-06-27:/building-a-python-processor.html</id><summary type="html">&lt;p&gt;A rationale and strawman for a processor to accelerate
dynamic-language&amp;nbsp;workloads.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have recently spent some time thinking about how hardware can be architected
and optimised to better support high-level dynamic languages such as Python and
JavaScript. There appears to be a significant gap between the way processors
and memory systems are built, which is to prioritise performance,  and the
characteristics of dynamic-language workloads, which prioritise ease of use. I
argue that dynamic languages are setting the direction of travel in the way we
use computers and this gap presents a huge opportunity for new hardware&amp;nbsp;innovation.&lt;/p&gt;
&lt;h3&gt;Table of&amp;nbsp;contents&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#dynamic-languages"&gt;Dymamic&amp;nbsp;languages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#py-ai"&gt;Python and &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#py-perf"&gt;Python&amp;nbsp;performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#py-hw-impacts"&gt;Hardware impacts on Python&amp;nbsp;performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#py-hw-support"&gt;Hardware support for&amp;nbsp;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#acknowledgements"&gt;Acknowledgements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#references"&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#related-links"&gt;Related&amp;nbsp;links&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Dynamic languages &lt;a name="dynamic-languages" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;According to &lt;a href="https://survey.stackoverflow.co/2023/#technology-most-popular-technologies"&gt;Stack Overflow&amp;#8217;s 2023 developer survey&lt;/a&gt;, JavaScript
has now been the most commonly-used language for the last 11 years and Python
has become the third most commonly-used language amongst all developers and the
first amongst non-professional developers and those learning to code. Nestled
amongst the most common languages are also TypeScript (a variant of
JavaScript), C#, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Lua and Ruby. Applications of these languages are wide
ranging and varied, across all aspects of industry, science, business and&amp;nbsp;government.&lt;/p&gt;
&lt;p&gt;Dynamic languages have become popular because they are easy to use when
compared with their statically-compiled counterparts. There are many aspects of
the languages that &lt;a href="https://erik-engheim.medium.com/the-many-advantages-of-dynamic-languages-267d08f4c7"&gt;contribute to this&lt;/a&gt;, such as dynamic
typing, high-level features, no requirement for a compilation step to produce
an executable format (leading to rapid iteration times), portability between
platforms, powerful debugging due to runtime introspection, integration with
editors and IDEs and natural support for metaprogramming. Ease of use improves
programmer productivity and widens participation to non-professionals and those
without expertise in low-level programming. These benefits are also a critical
factor in the development of new application areas and technologies such as &lt;span class="caps"&gt;AI&lt;/span&gt;,
where research and practice moves rapidly and participation across academia and
industry is&amp;nbsp;broad.&lt;/p&gt;
&lt;p&gt;The cost of these benefits when compared with compiled languages is a runtime
performance overhead due to the additional work the language implementation
must do, for example to resolve names and types. The overhead depends on the
workload, but is often in the realms of tens to hundreds of times slower. The
evidence in the use of dynamic languages however is proof that this performance
overhead is acceptable price to pay for their benefits. Having said this, there
are ongoing substantial efforts to close the gap by optimising the language
implementations and compilation strategies. As far as I can see, this effort
has not extended to optimisation of the underlying&amp;nbsp;hardware.&lt;/p&gt;
&lt;h2&gt;Python and &lt;span class="caps"&gt;AI&lt;/span&gt; &lt;a name="py-ai" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this remainder of this note I will focus on Python and its application to
&lt;span class="caps"&gt;AI&lt;/span&gt;, a domain that is significant enough to cause the development of new
computer hardware and rapid adoption of new process, integration and packaging&amp;nbsp;technologies.&lt;/p&gt;
&lt;p&gt;Python has established itself as the main programming language in &lt;span class="caps"&gt;AI&lt;/span&gt;, and this
is due to ease-of-use considerations. Programming in &lt;span class="caps"&gt;AI&lt;/span&gt; is typically done using
&lt;em&gt;frameworks&lt;/em&gt;, meaning a library that provides facilities to express a
computation that is compiled and run within the program, rather than expressing
the computation directly in the programming language. TensorFlow and PyTorch
are two pre-eminent examples, but with PyTorch having &lt;a href="https://www.semianalysis.com/p/nvidiaopenaitritonpytorch"&gt;taken the
lead&lt;/a&gt; in becoming the most widely-used framework. TensorFlow
established itself early with support from Google, but it has lost its
dominance to PyTorch because PyTorch was easier to use and more flexible. It
was thus more widely adopted and more quickly applied to new application&amp;nbsp;areas.&lt;/p&gt;
&lt;p&gt;PyTorch&amp;#8217;s &lt;a href="https://pytorch.org/docs/stable/community/design.html"&gt;first design principle&lt;/a&gt; is &lt;em&gt;usability over
performance&lt;/em&gt; which clearly indicates ease of use is the driving force in &lt;span class="caps"&gt;AI&lt;/span&gt;
model development and deployment. PyTorch&amp;#8217;s third design principle is &lt;em&gt;Python
first&lt;/em&gt; meaning that working in Python natively (using the features of the
language) provides the best experience and results for users, rather than
deferring to optimised compiled-language libraries. PyTorch&amp;#8217;s primacy and clear
prioritisation of ease of use indicates the direction of travel: that Python
will continue to become a first-class citizen in &lt;span class="caps"&gt;AI&lt;/span&gt; programming and so its
performance will be increasingly under&amp;nbsp;scrutiny.&lt;/p&gt;
&lt;p&gt;Since around 2012, &lt;span class="caps"&gt;AI&lt;/span&gt; has undergone a renaissance by scaling the performance of
deep neural networks with GPUs. Looking forward, there are many ways in which &lt;span class="caps"&gt;AI&lt;/span&gt;
models are expected to develop, requiring programming techniques and hardware to
develop to provide these capabilities&amp;nbsp;too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model size&lt;/strong&gt; is growing and will continue to grow. Although &lt;span class="caps"&gt;GPT&lt;/span&gt;-3 has 175
  bn parameters, there are an estimated 86 bn neurons in the human brain and an
  order-of 100 tn parameters (albeit encoded using analog mechanisms). It is
  likely that sparsity will increasingly be required to train and access these
  models&amp;nbsp;efficiently.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Conditional sparsity&lt;/strong&gt; through conditionality in the structure of a
  network, eg routing of activity based on the data. In a dense network, every
  input interacts with every weight, but our brains don&amp;#8217;t fire all neurons in
  response to every stimulus, and &lt;strong&gt;unconditional sparsity&lt;/strong&gt; that is not
  dependent on the input, such as from pruning of&amp;nbsp;connections.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Symbolic representations&lt;/strong&gt;. Symbolic &lt;span class="caps"&gt;AI&lt;/span&gt; programs are based on creating
  explicit structures and behaviour rules. This approach was the dominant
  paradigm in &lt;span class="caps"&gt;AI&lt;/span&gt; from the 1950s up to the mid 1990s. It is however considered a
  complementary technique to deep learning, possibly reflecting &lt;a href="https://aaai-2022.virtualchair.net/plenary_13.html"&gt;the fast and
  slow parts of the human cognitive system&lt;/a&gt;. Examples are &lt;a href="https://en.wikipedia.org/wiki/Decision_tree"&gt;decision
  trees&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Probably_approximately_correct_learning"&gt;&lt;span class="caps"&gt;PAC&lt;/span&gt; learning&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Composition&lt;/strong&gt;. New models will be created from parts such as whole sub models,
  or other reusable components. This is the way any complex system is
  constructed, including our&amp;nbsp;brains.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Python performance &lt;a name="py-perf" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Broadly, the performance of Python programs can be improved at three&amp;nbsp;levels:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Optimising the&amp;nbsp;application.&lt;/li&gt;
&lt;li&gt;Optimising the language&amp;nbsp;implementation.&lt;/li&gt;
&lt;li&gt;Optimising the&amp;nbsp;hardware.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The work in &lt;em&gt;Quantitative Overhead Analysis for Python&lt;/em&gt; [1] provides a detailed
analysis of overheads in CPython. &lt;sup id="fnref:python-overheads"&gt;&lt;a class="footnote-ref" href="#fn:python-overheads"&gt;1&lt;/a&gt;&lt;/sup&gt; The different types of
overhead are described in the following table, which is taken from the&amp;nbsp;paper.&lt;/p&gt;
&lt;table&gt;
  &lt;caption&gt;Sources of performance overhead in Python, from [1].&lt;/caption&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Group&lt;/th&gt;
      &lt;th scope="col"&gt;Overhead category&lt;/th&gt;
      &lt;th scope="col"&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td rowspan="4"&gt;Additional language features&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Error check&lt;/td&gt;&lt;td&gt;Check for overflow, out-of-bounds and other errors&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Garbage collection&lt;/td&gt;&lt;td&gt;Automatically freeing unused memory&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Rich flow control&lt;/td&gt;&lt;td&gt;Support for more condition cases and control structures&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td rowspan="6"&gt;Dynamic language features&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Type check&lt;/td&gt;&lt;td&gt;Checking variable type to determine operation&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Boxing/unboxing&lt;/td&gt;&lt;td&gt;Wrapping or unwrapping integer or float types&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Name resolution&lt;/td&gt;&lt;td&gt;Looking up variable in a map&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Function resolution&lt;/td&gt;&lt;td&gt;Dereferencing function pointers to perform an operation&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Function setup/cleanup&lt;/td&gt;&lt;td&gt;Setting up for a function call and cleaning up when finished&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td rowspan="7"&gt;Interpreter operations&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Dispatch&lt;/td&gt;&lt;td&gt;Reading and decoding bytecode instruction&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Stack&lt;/td&gt;&lt;td&gt;Reading, writing, and managing &lt;span class="caps"&gt;VM&lt;/span&gt; stack&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Const load&lt;/td&gt;&lt;td&gt;Reading constants&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Object allocation&lt;/td&gt;&lt;td&gt;Inefficient deallocation followed by allocation of objects&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Reg transfer&lt;/td&gt;&lt;td&gt;Calculating address of &lt;span class="caps"&gt;VM&lt;/span&gt; storage&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;C function call&lt;/td&gt;&lt;td&gt;Following the C calling convention in the interpreter&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The following charts (also taken from the paper) show the proportions are given
as a percentage of total execution time, based on the measured execution of a
set of benchmarks. On average, 64.9% of overall execution time is overhead, and
the remaining 35.1% is used for the execution of the program. Of the language
features, name resolution and function setup/cleanup dominate. Of the
interpreter operations, dispatch (reading bytecode and executing the correct
operations) and C function calls&amp;nbsp;dominate.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/measured-overheads.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/measured-overheads_1000x1000.png" alt="Python overheads measured in various benchmarks, from [1]."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Python overheads measured in various benchmarks, from [1].&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;There has been significant work on tackling (2) the language implementation.
Prominent examples include:
&lt;a href="https://www.pypy.org"&gt;PyPy&lt;/a&gt;, an alternative &lt;a href="https://doc.pypy.org/en/latest/interpreter-optimizations.html"&gt;optimised&lt;/a&gt; implementation written in
Python that includes a just in-time (&lt;span class="caps"&gt;JIT&lt;/span&gt;) compiler to dynamically optimise
common code paths;
&lt;a href="https://github.com/facebookincubator/cinder"&gt;Cinder&lt;/a&gt; is Meta&amp;#8217;s internal performance-optimised version of
CPython that includes various performance optimisations and a per-method &lt;span class="caps"&gt;JIT&lt;/span&gt;;
&lt;a href="https://cython.org"&gt;Cython&lt;/a&gt; translates Python to C/C++ for static compilation and
execution in the CPython runtime environment;
&lt;a href="https://nuitka.net"&gt;Nuitka&lt;/a&gt; is similar to Cython, as a compiler from Python to C,
using the CPython interpreter as a library;
And not forgetting CPython itself has an active project led by Microsoft and
Guido van Rossum called &lt;a href="https://github.com/faster-cpython/ideas"&gt;Faster CPython&lt;/a&gt; to explore
performance optimisations.
Approximately, these approaches achieve speedups of up to an order of magnitude
when compared to the standard CPython&amp;nbsp;implementation.&lt;/p&gt;
&lt;p&gt;Where the previous examples optimise Python as a general-purpose language, some
approaches such as &lt;a href="https://docs.exaloop.io/codon"&gt;Codon&lt;/a&gt;, &lt;a href="https://numba.pydata.org/"&gt;Numba&lt;/a&gt; and &lt;a href="https://triton-lang.org"&gt;Triton&lt;/a&gt; compile
subsets of Python into machine code for host or accelerator devices,
eliminating the runtime overhead altogether. These approaches can achieve
speedups of the order of 100 times for serial execution. They focus however
on accelerating numerical computations and therefore sidestep the difficulties
of statically-compiling dynamic features such as naming, large integers and
data structures, which are much more&amp;nbsp;challenging.&lt;/p&gt;
&lt;p&gt;Within the scope of (1) optimising the application, a significant issue
preventing the use of parallelism is Python&amp;#8217;s &lt;a href="https://wiki.python.org/moin/GlobalInterpreterLock"&gt;Global Interpreter Lock
(&lt;span class="caps"&gt;GIL&lt;/span&gt;)&lt;/a&gt;. This lock allows only one thread to execute the interpreter at
once, which was done originally to make the counting of object references
simpler. It is possible to work around the constraints imposed by the &lt;span class="caps"&gt;GIL&lt;/span&gt;, such
as with&amp;nbsp;the &lt;code&gt;multiprocessing&lt;/code&gt; module but this makes it difficult to express
different types of parallelism and creates an ease-of-use problem. A
&lt;a href="https://peps.python.org/pep-0703/"&gt;&lt;span class="caps"&gt;PEP&lt;/span&gt;&lt;/a&gt; submitted by a PyTorch developer makes the case for removing the
&lt;span class="caps"&gt;GIL&lt;/span&gt;, outlining motivating examples in scientific and numerical computing, and
tasks using Python for coordination and communication. A decision on adoption
of this &lt;span class="caps"&gt;PEP&lt;/span&gt; is yet to be made but a &lt;a href="https://github.com/colesbury/nogil-3.12"&gt;reference implementation&lt;/a&gt; is&amp;nbsp;available.&lt;/p&gt;
&lt;p&gt;There are various sources of overhead in the execution of a Python program that
can contribute to orders-of-magnitude slower runtime compared to a compiled
program. Strategies to reduce this overhead are in optimising the sources of
overhead directly by improving compilation strategies, improving runtime
strategies (such as caching of accesses or performing &lt;span class="caps"&gt;JIT&lt;/span&gt; compilation to
machine code of frequent code paths), statically compiling Python code to C
code including inline calls to the interpreter, and, for restricted subsets of
Python, statically compiling Python code to machine code without the
interpreter. These approaches are all within the software domain, so it is
interesting to consider in what ways computer hardware could be optimised to
further reduce the runtime overheads in Python&amp;nbsp;programs.&lt;/p&gt;
&lt;h2&gt;Hardware impacts on Python performance &lt;a name="py-hw-impacts" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The main findings from the microarchitecture investigation in [1] summarised
below provide a useful basis for understanding how Python is limited by current
computer hardware. The study is based on a range of benchmarks run with CPython
and PyPy with and without &lt;span class="caps"&gt;JIT&lt;/span&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;ILP&lt;/span&gt;&lt;/strong&gt;. Both CPython and PyPy exhibit low instruction-level parallelism.
  This suggests that choosing a deeply-pipelined out-of-order core may not
  provide good tradeoff between silicon area and performance. A simpler, in-order
  core may instead be a better choice, particularly when building a parallel
  processor with many&amp;nbsp;cores.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Working memory&lt;/strong&gt;. Across all the benchmarks, large caches do not provide a
  performance benefit, implying that working sets tend to be relatively&amp;nbsp;small.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nursery sizing&lt;/strong&gt;. A critical factor related to working memory is an area
  used for the allocation for short-term objects called a &lt;em&gt;nursery&lt;/em&gt;. When the
  nursery does not fit in cache, performance is impacted due to cache thrashing.
  However, there are two things to consider: reducing the nursery size will
  increase garbage-collection overheads and the optimal nursery size is dependent
  on the&amp;nbsp;application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;JIT&lt;/span&gt;&lt;/strong&gt;. When &lt;span class="caps"&gt;JIT&lt;/span&gt; compilation is used, the memory system is put under more
  pressure, so although the number of instructions executed reduces, the
  latency of memory operations increases due to cache line misses. This implies
  the working memory increases and so accordingly the overhead of garbage
  collection also&amp;nbsp;increases.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is clear from these findings that optimising the memory system will yield a
more significant performance improvement than optimising the processor
microarchitecture and instruction set design (as is typically the focus of new
processor designs). Orthogonal to optimisations in the memory system, providing
more execution parallelism at the process level is the only other way to
significantly scale performance. This gives us the basis for a new Python&amp;nbsp;processor.&lt;/p&gt;
&lt;h2&gt;Hardware support for Python &lt;a name="py-hw-support" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This section presents some rough ideas on what new computer hardware might
look like that optimises the execution of Python (or indeed other dynamic&amp;nbsp;languages).&lt;/p&gt;
&lt;h3&gt;System&amp;nbsp;architecture&lt;/h3&gt;
&lt;p&gt;The most straightforward way to deploy a new processor chip is as an
&lt;em&gt;accelerator&lt;/em&gt; to a conventional &lt;em&gt;host&lt;/em&gt; processor connected via PCIe. The host
processor can then offload parts or all of the Python workload to the
accelerator for improved performance. The following diagrams show two ways that
this could work: one where the host runs the Python interpreter and offloads
parts of the Python program (similar to the way &lt;em&gt;Eager Mode&lt;/em&gt; works in PyTorch
and TensorFlow); the other where the accelerator runs the Python interpreter
and communicates to the host via a standard set of system calls. The first
scenario means that execution can fall back onto the host if the Python code
was not supported by the accelerator, thereby allowing the design of the
accelerator to be simpler. However, managing the communication of Python
objects over this boundary is complicated and potentially a significant
overhead. In the second scenario, the whole Python program is executed by the
interpreter running on the accelerator. This simplifies the interface between
the two devices, which would only need to provide basic system calls to the&amp;nbsp;interpreter.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/offload-model-fine.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/offload-model-fine_1000x1000.png" alt="Fine-grained offload"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Fine-grained offload&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/offload-model-coarse.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/offload-model-coarse_1000x1000.png" alt="Coarse-grained offload"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Coarse-grained offload&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;At a system level, an accelerator device for Python might be integrated between
the host processor and other accelerators (typically GPUs in data-centre-type
deployments) since Python will be responsible for coordinating offload of
computations. Access to external memory can either be to &lt;span class="caps"&gt;DRAM&lt;/span&gt; via the host or
on &lt;span class="caps"&gt;DRAM&lt;/span&gt; integrated with the device. The latter has the benefit of being able to
supply lower latency and higher bandwidth to the&amp;nbsp;memories.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/accelerator.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/accelerator_1000x1000.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;h3&gt;Core&amp;nbsp;architecture&lt;/h3&gt;
&lt;p&gt;At the core level, it makes a lot of sense to use &lt;span class="caps"&gt;RISC&lt;/span&gt;-V as the base
architecture because it is a general-purpose &lt;span class="caps"&gt;ISA&lt;/span&gt; that is open and easily
extensible. As previously noted, the &lt;span class="caps"&gt;RISC&lt;/span&gt;-V microarchitecture can be kept
simple because interpreting Python is not heavily dependent on &lt;span class="caps"&gt;ILP&lt;/span&gt;. The
complexity of the microarchitecture depends on the best tradeoff between
sequential and parallel performance, which in turn depends on the workload. &lt;span class="caps"&gt;AI&lt;/span&gt;
for example will be weighted towards highly-parallel execution, so is better
suited to a large number of simple processor cores. Extensions to the core can
be added to provide optimised support for specific operations (eg
floating-point arithmetic and for matrix multiplication), support for
concurrency (threading, synchronisation, communication etc) or control over the
memory&amp;nbsp;hierarchy.&lt;/p&gt;
&lt;h3&gt;Memory&amp;nbsp;system&lt;/h3&gt;
&lt;p&gt;One way to improve the way memory is managed is to bring some level of control
of the cache to the processor. In the following diagram, A &lt;span class="caps"&gt;RISC&lt;/span&gt;-V core has
extensions that allows it to control a &amp;#8216;smart cache&amp;#8217;. Such a system could
enable aggressive caching of computations that are frequently recomputed, such
as in the processes of name and function resolution, or from calling a function
with the same arguments, which account for a substantial portion of the
language overhead. A motivating example is caching of the&amp;nbsp;C &lt;code&gt;strlen&lt;/code&gt; function
that is used frequently by the Python interpreter in name resolution. A
difficulty in caching this function entirely in software is that a full string
comparison is required to determine whether to invalidate the cache or not, and
this is roughly as expensive&amp;nbsp;as &lt;code&gt;strlen&lt;/code&gt;. A hardware caching scheme could be
implemented more simply by snooping memory writes and invalidating the cache
entry if any part of the string has changed. To support this, hardware
extensions would be required to place items in the cache, retrieve items in the
cache, monitor ranges of memory and invalidate items in monitored&amp;nbsp;ranges.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/smart-cache.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/smart-cache_1000x1000.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Another memory-system optimisation is to provide garbage collection (&lt;span class="caps"&gt;GC&lt;/span&gt;) as a
hardware-managed function. &lt;span class="caps"&gt;GC&lt;/span&gt; is a technique that has been studied for decades,
including in hardware: it was first introduced in Lisp in the 1950s and
appeared as a hardware extension in the 1981 &lt;a href="https://en.wikipedia.org/wiki/Intel_iAPX_432#Garbage_collection"&gt;Intel iAPX 432&lt;/a&gt; (see
[4] for a literature review of hardware &lt;span class="caps"&gt;GC&lt;/span&gt; techniques and implementations).
Surprisingly, hardware &lt;span class="caps"&gt;GC&lt;/span&gt; has never caught on and this is certainly related to
the &lt;a href="https://www.quora.com/Why-dont-modern-CPUs-offer-hardware-assisted-garbage-collection-and-memory-allocation"&gt;challenges&lt;/a&gt; of a performant solution requiring integration
across many levels of abstraction: microarchitecture, architecture, tooling,
operating systems and languages. However, it seems that this precedent should
be challenged given that &lt;span class="caps"&gt;GC&lt;/span&gt; is central to the way dynamic languages&amp;nbsp;work.&lt;/p&gt;
&lt;h3&gt;Scaling the number of&amp;nbsp;cores&lt;/h3&gt;
&lt;p&gt;Building a system with multiple processing cores can be done in a conventional
way by sharing access to higher levels of cache and adding a coherency
mechanism for lower-level private caches, but this does not scale well past a
few tens or hundreds of cores due to the overheads of maintaining coherency. A
different and more radical approach is to use a distributed-memory architecture
where each core has a private memory and communication between cores or to
external &lt;span class="caps"&gt;DRAM&lt;/span&gt; is performed explicitly using messages. The major benefit of such
an architecture is that is scalable to large numbers of cores, providing more
performance from parallelism, and that processor-memory pairs can flexibly be
used as units of memory or processing dependent on the application. This
approach generalises the concept of a programmable cache hierarchy by using
processor-memory pairs as units of memory with the processor providing access
logic and building arbitrary caching schemes in software, dependent on the
characteristics of the workload. I have previously written about this idea in
my work on &lt;a href="files/emulation.pdf"&gt;emulating large memories&lt;/a&gt;.
Alternatively, processor-memory pairs can be turned over to processing and used
to execute parts of an application in parallel, a great example of which would
be running one or several &lt;span class="caps"&gt;JIT&lt;/span&gt; compiler processes concurrently with the&amp;nbsp;application.&lt;/p&gt;
&lt;p&gt;The following diagram sketches how such a machine might be built. The main
building blocks are a processor-memory &lt;em&gt;tile&lt;/em&gt; and a &lt;em&gt;router&lt;/em&gt;. The tile includes
communication facilities, allowing it to communicate to all other tiles in the
system and to off-chip communication interfaces via routers. The arrangement of
routers and tiles is flexible but the routers have enough links that
high-dimensional topologies can be created to provide communication with
bounded latency and throughput, which is essential for a general-purpose
machine. The operation of the communications fabric could be dynamic allocated
with packet switching, or statically allocated with circuit switching. Special
packet types can be used for accessing external memory or other off-chip &lt;span class="caps"&gt;IO&lt;/span&gt;, or
for implementing shared-memory operations such as direct access to remote tile
memories. Collective operations such as scatters and gathers are likely to be
frequently used, so could be optimised with supporting hardware in the tile and
routers. These are the essential ingredients of a  general-purpose fine-grained
parallel machine. I have previously outlined a similar kind of machine in my
&lt;a href="/scalable-abstractions-for-general-purpose-parallel-computation.html"&gt;PhD thesis&lt;/a&gt;, and I intend to post a note with a revised and fuller
description at some point&amp;nbsp;soon.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/python-processor/parallel-microarchitecture-top.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/parallel-microarchitecture-top_1000x1000.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;Summary &lt;a name="summary" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This note makes the argument that ease of use the critical factor in the
development of new application areas and the adoption of new computer hardware.
Ease of use has in many regards won as the most important factor in software
and programming, but new computer hardware prioritises performance. Closing
this gap would mean that rapidly-developing application areas such as &lt;span class="caps"&gt;AI&lt;/span&gt; would
benefit by moving the boundary away from optimised low-level libraries, making
fuller use of languages such as Python. For computer designers, there is a huge
opportunity for new architectural innovations that support a radically
different workload from conventional low-level compiled languages. Contrary to
conventional wisdom, hardware is easier to innovate rapidly and it is software
that bears the weight of&amp;nbsp;legacy.&lt;/p&gt;
&lt;h2&gt;Acknowledgements &lt;a name="acknowledgements" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The hardware ideas in this note were developed in conversations with &lt;a href="http://www.jpallister.com"&gt;James
Pallister&lt;/a&gt;. Closely related to some of the ideas explored is a new
&lt;span class="caps"&gt;UK&lt;/span&gt; startup &lt;a href="https://www.vypercore.com"&gt;VyperCore&lt;/a&gt; co-founded by &lt;a href="https://ednutting.com"&gt;Ed Nutting&lt;/a&gt; who are
building a &lt;span class="caps"&gt;RISC&lt;/span&gt;-V-based processor that includes facilities for hardware memory
allocation and &lt;span class="caps"&gt;GC&lt;/span&gt; for performance and&amp;nbsp;safety.&lt;/p&gt;
&lt;h2&gt;References &lt;a name="references" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Mohamed Ismail and G. Edward Suh, &lt;em&gt;Quantitative Overhead Analysis for
   Python&lt;/em&gt;, 2018 &lt;span class="caps"&gt;IEEE&lt;/span&gt; International Symposium on Workload Characterization
   (&lt;span class="caps"&gt;IISWC&lt;/span&gt;). [&lt;a href="https://ieeexplore.ieee.org/document/8573512"&gt;&lt;span class="caps"&gt;IEEE&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://www.cs.ucsb.edu/sites/default/files/documents/2010-14.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nagy Mostafa, Chandra Krintz, Calin Cascaval, David Edelsohn, Priya
   Nagpurkar, Peng Wu, &lt;em&gt;Understanding the Potential of Interpreter-based
   Optimizations for Python&lt;/em&gt;. &lt;span class="caps"&gt;UCSB&lt;/span&gt; Technical Report #2010-14 August, 2010.
   [&lt;a href="https://cs.ucsb.edu/research/tech-reports/2010-14"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gergö Barany, &lt;em&gt;Python Interpreter Performance Deconstructed&lt;/em&gt;,
   Proceedings of the Workshop on Dynamic Languages and Applications, June 2014.
   [&lt;a href="https://dl.acm.org/doi/10.1145/2617548.2617552"&gt;&lt;span class="caps"&gt;ACM&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://www.cs.ucsb.edu/sites/default/files/documents/2010-14.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Andres Amaya Garcia, Integrated hardware garbage collection for real-time
   embedded systems, PhD thesis, University of Bristol 2021.
   [&lt;a href="https://research-information.bris.ac.uk/en/studentTheses/integrated-hardware-garbage-collection-for-real-time-embedded-sys"&gt;University of Bristol&lt;/a&gt;, &lt;a href="https://research-information.bris.ac.uk/files/298185781/Final_Copy_2021_09_28_Amaya_Garcia_A_PhD.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;]&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Related links &lt;a name="related-links" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/"&gt;Why Python is Slow: Looking Under the Hood&lt;/a&gt;, Pythonic Perambulations blog&amp;nbsp;(2014).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.intel.com/content/www/us/en/developer/articles/technical/accelerating-python-today.html#gs.35k6hi"&gt;Accelerating Python Today&lt;/a&gt;, Intel technical note, James&amp;nbsp;Reinders.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:python-overheads"&gt;
&lt;p&gt;See [2] and [3] for other similar analyses that [1] builds on.&amp;#160;&lt;a class="footnote-backref" href="#fnref:python-overheads" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="computer-architecture"/></entry><entry><title>Cornish Unit House retrofit insulation</title><link href="https://jameswhanlon.com/cornish-unit-house-retrofit-insulation.html" rel="alternate"/><published>2022-12-29T00:00:00+01:00</published><updated>2022-12-29T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2022-12-29:/cornish-unit-house-retrofit-insulation.html</id><summary type="html">&lt;p&gt;Retrofitting insulation in a timber-framed top&amp;nbsp;floor.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I live in a &lt;a href="https://nonstandardhouse.com/cornish-unit-type-1-precast-reinforced-concrete-house/"&gt;Cornish Unit house (Type
1)&lt;/a&gt;
and have recently had a heat pump installed to replace an ageing gas boiler.
Having lived in the house for several years, I was well aware of significant
thermal issues, particularly upstairs, due to the house being very cold in the
winter and very hot in the summer. Temperature changes in the house were
noticable with cold returning quickly after the heating being on. A
non-invasive &lt;a href="home-thermal-imaging-survey.html"&gt;survey of the building&lt;/a&gt; last
winter showed up various minor issues but didn&amp;#8217;t pinpoint a particular issue.
Further investigation into the upstairs walls revealed there to be virtually no
insulation, only ~50 mm of glass wool insulation hanging behind the
plasterboard, as well as direct routes into the floor cavity (along the joists)
from the eaves. The effective result is a plasterboard tent upstairs with cold
air circulating just behind the walls, and to an extent the floor/ceiling. In
contrast, the ground floor walls are a more modern cavity construction from
them being replaced in the 1980s, and they have, at some point subsequently,
been filled with polystyrene insulation&amp;nbsp;beads.&lt;/p&gt;
&lt;p&gt;Given that the upper part of the house is a timber construction, the walls have
voids between the timbers that new insulation can be fitted into (directly
replacing the glass wool). This seemed like a great opportunity given that it
would be much more difficult to add significant insulation were the walls a
typical masonry construction, since insulation could only be added externally
(expensive) or internally (limited depth). Insulation is often added to Cornish
Unit houses when they are retiled since all of the timbers are exposed.
However, in my case since the roof is fine, installing the insulation from
internal access is simpler and much cheaper, albeit a more messy job. The
detail below shows the planned modification: adding 80 mm of &lt;span class="caps"&gt;PIR&lt;/span&gt; insulation
board between the joists, and 25 mm insulated plasterboard on top with a
sandwiched breathable vapour membrane, providing 105 mm of insulation and an
expected U value of 0.25 W/m$^2$K, in line with the new &lt;a href="https://www.gov.uk/government/publications/conservation-of-fuel-and-power-approved-document-l"&gt;Part L Building
Regulations&lt;/a&gt;.
Note that a short section of insulation is added at the floor level to make the
insulation continuous from the brick wall cavity up to the&amp;nbsp;loft.&lt;/p&gt;
&lt;p&gt;The full description as submitted to Building Control is
as follows. They subsequently inspected and signed off the&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;Upgrading external wall insulation within timber framed wall at first floor
level, which forms lower section of tiled mansard roof on a Cornish Unit Type 1
house. Hanging tiles with breather membrane to remain as existing. Replacing
existing 80mm mineral wool insulation with 80mm rigid &lt;span class="caps"&gt;PIR&lt;/span&gt; insulation board
between studs within the timber frame. Adding a vapour control layer and dry
lining the internal face with 37.5mm insulated plasterboard, plaster and&amp;nbsp;finish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proposed wall build up&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roof tiles hanging (to remain as&amp;nbsp;existing).&lt;/li&gt;
&lt;li&gt;Breather membrane (to remain as&amp;nbsp;existing).&lt;/li&gt;
&lt;li&gt;Ventilated cavity (30mm at high level - 335mm at low&amp;nbsp;level).&lt;/li&gt;
&lt;li&gt;80mm &lt;span class="caps"&gt;PIR&lt;/span&gt; insulation board between studs (Celotex &lt;span class="caps"&gt;GA4000&lt;/span&gt;&amp;nbsp;80mm).&lt;/li&gt;
&lt;li&gt;Combined vapour control &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; air tightness layer, taped (Procheck Adapt &lt;span class="caps"&gt;VCL&lt;/span&gt; with integral&amp;nbsp;tape).&lt;/li&gt;
&lt;li&gt;37.5mm insulated plasterboard (Celotex &lt;span class="caps"&gt;PL4025&lt;/span&gt; 25 +&amp;nbsp;12.5mm).&lt;/li&gt;
&lt;li&gt;Internal finish (plaster and&amp;nbsp;paint).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Method of installation&lt;/strong&gt;: Renovation to be completed from inside the property by
removing plasterboard and existing mineral wool insulation internally to expose
the frame. Mineral wool insulation to be replaced by 80mm &lt;span class="caps"&gt;PIR&lt;/span&gt; insulation boards
between timber studs. Breather membrane and roof tiles to remain as existing.
Timber battens to be installed at high level to form a 30mm ventilated cavity.
Continuous vapour control and air tightness layer to be added on the internal face
of the &lt;span class="caps"&gt;PIR&lt;/span&gt; insulation board and taped. 37.5mm layer of insulated plasterboard
to be installed onto the &lt;span class="caps"&gt;VCL&lt;/span&gt;. Plaster and paint to&amp;nbsp;finish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;: Insulation at lower eaves to be made continuous with existing cavity
wall bead insulation to ground floor masonry wall. Similarly, insulation to be
made continuous at ceiling junction with existing mineral wool insulation
between ceiling joists in roof void, where possible. Estimated U-value of
proposed build-up = 0.25 W/m$^2$K (source: Saint Gobain &lt;span class="caps"&gt;UK&lt;/span&gt; U-value&amp;nbsp;calculator).&lt;/p&gt;
&lt;p&gt;I investigated alternatives to &lt;span class="caps"&gt;PIR&lt;/span&gt; board, such as insulation board constructed
from natural fibres, but these generally seemed twice as expensive per square
metre and offered approximately half the U value. Given that wall depth was
critical, these weren&amp;#8217;t good&amp;nbsp;solutions.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/insulation-stack-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/insulation-stack-1_600x600.jpg" alt="Materials pile: 80 mm PIR top and 37.5 mm insulated plasterboard bottom. A total of 13 80 mm sheets and 16 37.5 mm sheets were used."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Materials pile: 80 mm &lt;span class="caps"&gt;PIR&lt;/span&gt; top and 37.5 mm insulated plasterboard bottom. A total of 13 80 mm sheets and 16 37.5 mm sheets were used.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/insulation-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/insulation-detail_600x600.jpg" alt="Section detail showing additional insulation and it's integration with the existing structure and insulation."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Section detail showing additional insulation and it&amp;#8217;s integration with the existing structure and insulation.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Bedroom&amp;nbsp;1&lt;/h2&gt;
&lt;p&gt;Roofing baton is added at the top of the wall to ensure there is an air gap
behind the insulation board and at the bottom of the wall to prevent the
insulation from pushing into the cavity. Unfortunately there were few
consistent dimensions between the timbers so all boards had to be cut to
measure for each&amp;nbsp;space.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-stripped.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-stripped_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-prepped.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-prepped_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-insulation.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-insulation_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-membrane.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-membrane_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-plasterboard-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-plasterboard-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-plasterboard-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-plasterboard-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;An awkward section was above the windows where the was a steel lintel as well
as a void for the section of roof that protrudes over the window. Liberal
amounts of expanding foam were used to fill gaps as well as&amp;nbsp;possible.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-window-head-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-window-head-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-window-head-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-window-head-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-window-detail-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-window-detail-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed1-window-detail-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed1-window-detail-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Bedroom&amp;nbsp;2&lt;/h1&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-before.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-before_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-stripped.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-stripped_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-stripped-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-stripped-detail_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-baton.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-baton_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-floor-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-floor-detail_600x600.jpg" alt="PIR sections cut to sit on top of the ground floor brick wall, fitting between the floor joists."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;span class="caps"&gt;PIR&lt;/span&gt; sections cut to sit on top of the ground floor brick wall, fitting between the floor joists.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-insulation.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-insulation_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-insulation-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-insulation-detail_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-membrane.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-membrane_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-plasterboard.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-plasterboard_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed2-plasterboard-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed2-plasterboard-detail_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Bedroom&amp;nbsp;3&lt;/h1&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed3-stripped.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed3-stripped_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed3-insulation1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed3-insulation1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed3-insulation2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed3-insulation2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/bed3-plasterboard.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bed3-plasterboard_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Hallway&lt;/h1&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/hallway-stripped1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hallway-stripped1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/hallway-stripped2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hallway-stripped2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/hallway-floor-detail.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hallway-floor-detail_600x600.jpg" alt="Insulation providing continuity between the brick cavity and the new wall insulation, as well as plugging the gap from the eaves into the floor."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Insulation providing continuity between the brick cavity and the new wall insulation, as well as plugging the gap from the eaves into the floor.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/hallway-stripped2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hallway-stripped2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Performance&lt;/h1&gt;
&lt;p&gt;The work was completed in the summer, but the results became evident during a
cold snap in December. Purely from a comfort point of view, the upstairs went
from being the colder part of the house, to the warmer part. I also used a
thermal imaging camera to inspect the insulation. The camera confirmed that the
new insulated sections provide a consistent warm temperature as expected, with
no unexpected temperature changes within these ares. Some minor issues
highlighted were at the intersections with other surfaces and&amp;nbsp;areas.&lt;/p&gt;
&lt;p&gt;The two images below highlight a minor cold bridge effect from the plasterboard&amp;nbsp;fixing.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-plasterboard-fixing1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-plasterboard-fixing1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-plasterboard-fixing2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-plasterboard-fixing2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The image on the left below shows a cold corner section, which was due to cold
ingress on the next door room before that room had been upgraded. The image on
the right below shows a piece of missing insulation (unrelated to the&amp;nbsp;work!).&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-corner-cold.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-corner-cold_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-missing-loft-insulation.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-missing-loft-insulation_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Finally, these two images show intersection of the new insulation with masonry
walls and there being an ingress of cold air, although only a minor temperature
difference of ~1-2&amp;nbsp;degrees.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-wall1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-wall1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/house-insulation/TI-wall2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/TI-wall2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Summary&lt;/h1&gt;
&lt;p&gt;Upgrading the insulation within the upper timber frame of my Cornish Unit house
was relatively straightforward and a cheap way to substantially improve the
thermal performance of the building. The effects of this work are significant,
making the house a much more comfortable and stable environment, and a great
deal more suitable environment to heat using an air-source heat&amp;nbsp;pump.&lt;/p&gt;
&lt;h1&gt;Related&amp;nbsp;links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.epcworks.co.uk/improve-your-epc/mansard-roof"&gt;Mansard Roof, &lt;span class="caps"&gt;EPC&lt;/span&gt;&amp;nbsp;Works&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Home and Sustainability"/><category term="energy-efficiency"/><category term="retrofit"/><category term="sustainability"/></entry><entry><title>From logic gates to a programming language using the Hex architecture</title><link href="https://jameswhanlon.com/from-logic-gates-to-a-programming-language-using-the-hex-architecture.html" rel="alternate"/><published>2022-11-18T00:00:00+01:00</published><updated>2022-11-18T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2022-11-18:/from-logic-gates-to-a-programming-language-using-the-hex-architecture.html</id><summary type="html">&lt;p&gt;A hardware implementation of a Hex processor with some basic tooling,
including a complete compiler for a simple programming&amp;nbsp;language.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This note walks through a hardware implementation of a simple processor and
complete compiler for a programming language targeted at it. The processor
architecture is designed to as simple as possible but provide a sensible target
for the compilation of complex programs using simple strategies. The
implementation of the processor and its supporting tooling is small and self
contained so to be understandable and easily extendable. Besides being an
interesting side project, my motivation was to create a complete example as a
point of reference to explain how programming languages work and correspond to
the underlying hardware of a computer processor, or to provide a useful
reference for compilers and simulators, a starting point for another project or
just a curiosity in&amp;nbsp;itself.&lt;/p&gt;
&lt;p&gt;First, to provide some background. The project is based on the Hex processor
architecture that was designed by &lt;a href="http://people.cs.bris.ac.uk/~dave"&gt;David
May&lt;/a&gt; as a vehicle for teaching about how
computers work at the University of Bristol, whilst being flexible enough to
execute substantial programs and easily extensible. David provided a simulator
written in C and a bootstrapping compiler written in an accompanying simple
imperative programming language called X. The design of Hex draws on the &lt;a href="https://en.wikipedia.org/wiki/Transputer"&gt;Transputer
architecture&lt;/a&gt; and the earlier &lt;a href="http://people.cs.bris.ac.uk/~dave/S42ISA.pdf"&gt;Simple
42&lt;/a&gt;, particularly with the use of
short instruction encodings, a prefixing mechanism for creating larger immediates
and A, B and C registers for expression evaluation. These kind of architectural
features made the silicon implementation of the Simple 42 and Transputers small
enough to fit on a single chip in the technology of the day. X draws on the
basic sequential features of the &lt;a href="https://en.wikipedia.org/wiki/Occam_(programming_language)"&gt;occam programming
language&lt;/a&gt; but it
not dissimilar to a small subset of C, for example. I include some more
historical details &lt;a href="#a-historical-note"&gt;at the end&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my &lt;a href="https://github.com/jameshanlon/hex-processor"&gt;implementation&lt;/a&gt;, I have
created a simple C++ toolchain with a simulator, Hex assembler and X language
compiler, and a Verilog implementation of Hex. Before describing them, the
next two sections introduce Hex and&amp;nbsp;X.&lt;/p&gt;
&lt;h3&gt;Table of&amp;nbsp;contents&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#the-hex-architecture"&gt;The Hex&amp;nbsp;architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-x-language"&gt;The X&amp;nbsp;language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#hex-processor-integrated-circuit"&gt;Hex processor integrated&amp;nbsp;circuit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#hex-tooling"&gt;Hex&amp;nbsp;tooling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#a-historical-note"&gt;A historical&amp;nbsp;note&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#similar-projects"&gt;Similar&amp;nbsp;projects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#further-reading"&gt;Further&amp;nbsp;reading&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The Hex architecture &lt;a name="the-hex-architecture" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Hex architecture is described in detail in &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/hexb.pdf"&gt;a separate
&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;, but I will give a brief summary here
and focus on several important aspects for reference. Hex has four registers:
program&amp;nbsp;counter &lt;code&gt;pc&lt;/code&gt;, operand&amp;nbsp;register &lt;code&gt;oreg&lt;/code&gt; and the A and B&amp;nbsp;registers
&lt;code&gt;areg&lt;/code&gt; and &lt;code&gt;breg&lt;/code&gt; used for expression evaluation. The architecture is
agnostic of a particular word size, but it has to be a minimum of a byte and
multiples of a byte. In the included implementation the word size is 4 bytes.
Hex has sixteen instructions (hence its name!) that are summarised in the
following table. Each instruction has a 4-bit opcode and a 4-bit immediate. The
immediate value can be extended using the prefix instructions to form a wider
value in&amp;nbsp;the &lt;code&gt;oreg&lt;/code&gt;, adding four bits per instruction. Operations beyond the
16 available encodings are made accessible by&amp;nbsp;the &lt;code&gt;OPR&lt;/code&gt; instruction that
encodes the operation type with its immediate. The instructions are grouped
into memory access with absolute or relative addressing modes, loading of
constants, branching, inter-register operations and supervisor&amp;nbsp;calls.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col"&gt;Opcode&lt;/th&gt;
  &lt;th scope="col"&gt;Behaviour&lt;/th&gt;
  &lt;th scope="col"&gt;Description&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDAM&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := mem[oreg]&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load from memory with an absolute address into areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDBM&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;breg := mem[oreg]&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load from memory with an absolute address into breg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;STAM&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;mem[oreg] := areg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Store to absolute address from areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDAC&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load constant into areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDBC&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;breg := oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load constant into breg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDAP&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := pc + oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load program counter-relative address into areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDAI&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := mem[areg + oreg]&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load from memory with base and offset into areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;LDBI&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;breg := mem[breg + oreg]&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Load from memory with base and offset into breg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;STAI&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;mem[breg + oreg] := areg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Store to memory with base and offset from areg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;BR&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;pc := pc + oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Branch relative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;BRZ&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;if areg = 0: pc := pc + oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Conditional branch relative on areg being zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;BRN&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;if areg &lt; 0: pc := pc + oreg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Conditional branch relative on areg being negative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;BRB&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;pc := breg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Absolute branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;PFIX&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;oreg := oreg &lt;&lt; 4&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Positive prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;NFIX&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;oreg = 0xFFFFFF00 | oreg &lt;&lt; 4&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Negative prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;OPR&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;-&lt;/td&gt;
  &lt;td&gt;Inter-register operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;code&gt;ADD&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := areg + breg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Add areg and breg and set areg to the result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;code&gt;SUB&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;areg := areg - breg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Subtract areg and breg and set areg to the result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;code&gt;SVC&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;-&lt;/td&gt;
  &lt;td&gt;Supervisor call&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;h3&gt;Prefixing&lt;/h3&gt;
&lt;p&gt;Prefixing using&amp;nbsp;the &lt;code&gt;PFIX&lt;/code&gt; and &lt;code&gt;NFIX&lt;/code&gt; operations generates operand values&amp;nbsp;in &lt;code&gt;oreg&lt;/code&gt; larger than the 4-bit instruction immediate. For example, the
following instructions generate the value 16&amp;nbsp;in &lt;code&gt;oreg&lt;/code&gt; and&amp;nbsp;use &lt;code&gt;LDAC&lt;/code&gt; to
assign it&amp;nbsp;to &lt;code&gt;areg&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;PFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# oreg = oreg (1) &amp;lt;&amp;lt; 4 (0x000010)&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Prefixes can be chained to extend the operand range, for example, generating the
value 496 requires two positive prefixes before a load constant&amp;nbsp;instruction:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;PFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# oreg = oreg (1) &amp;lt;&amp;lt; 4 (0x000010)&lt;/span&gt;
PFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# oreg = oreg (31) &amp;lt;&amp;lt; 4 (0x0001f0)&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 496&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Negative values always require a negative prefix to fill the top&amp;nbsp;most &lt;code&gt;oreg&lt;/code&gt;
bits with ones, so to load the value -1&amp;nbsp;into &lt;code&gt;oreg&lt;/code&gt; then &lt;code&gt;areg&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# oreg = 0xFFFFFF00 | oreg (15) &amp;lt;&amp;lt; 4 (0xfffffff0)&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 4294967295&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And to load -512, a positive prefix is required to scale the negative&amp;nbsp;value:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# oreg = 0xFFFFFF00 | oreg (14) &amp;lt;&amp;lt; 4 (0xffffffe0)&lt;/span&gt;
PFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# oreg = oreg (4294967264) &amp;lt;&amp;lt; 4 (0xfffffe00)&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 4294966784&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Inter-register&amp;nbsp;operations&lt;/h3&gt;
&lt;p&gt;The inter-register operations use&amp;nbsp;the &lt;code&gt;OPR&lt;/code&gt; opcode and consist only of
addition and subtraction. The group can be extended by implementing additional
immediate opcodes to add new operations to the processor (such as other
arithmetic and bitwise operations). The 4-bit immediate supports up to 16
inter-register operations without the need for prefixing, but many more with
prefixing and the according overhead to form larger immediates. The following
instruction sequence adds two numbers from fixed locations in memory, with the
result written&amp;nbsp;to &lt;code&gt;areg&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;LDAM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = mem[oreg (0x000001)] (7)&lt;/span&gt;
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# breg = mem[oreg (0x000002)] (9)&lt;/span&gt;
OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ADD areg = areg (7) + breg (9) (16)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A special inter-register operation is a supervisor call that transfers
control to the system to complete an action such as read or write from a
file, or to halt the program. The supervisor call type is encoded in&amp;nbsp;the
&lt;code&gt;oreg&lt;/code&gt; and arguments and return values specific to the call type are passed
and returned on the stack using the standard calling convention. An example
code sequence to invoke the exit supervisor call&amp;nbsp;is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Set areg to 0, the exit opcode value.&lt;/span&gt;
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Load the stack pointer in breg.&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Store areg into stack offset two as a parameter.&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Load the exit opcode.&lt;/span&gt;
OPR&lt;span class="w"&gt; &lt;/span&gt;SVC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Perform the supervisor call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the following execution trace, noting that the simulator implements the
system call directly rather than being handled by a kernel&amp;nbsp;routine:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 0&lt;/span&gt;
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# breg = mem[oreg (0x000001)] (16383)&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# mem[breg (16383) + oreg (2) = 0x004001] = areg (0)&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# areg = oreg 0&lt;/span&gt;
OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# exit 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Load-store&amp;nbsp;operations&lt;/h3&gt;
&lt;p&gt;There are two variants of load and store instructions: using absolute addresses
and addresses relative to a base address. Absolute addressing&amp;nbsp;(&lt;code&gt;LDAM&lt;/code&gt;,
&lt;code&gt;LDBM&lt;/code&gt; and &lt;code&gt;STAM&lt;/code&gt;) is intended to access objects in memory that are
allocated at offsets that are fixed with respect to a program, such as constant
values and global variables. Relative-addressing&amp;nbsp;(&lt;code&gt;LDAI&lt;/code&gt;, &lt;code&gt;LDBI&lt;/code&gt; and
&lt;code&gt;STAI&lt;/code&gt;) is typically used to access objects that are relative to a dynamic
position, such as the stack pointer, or index into an array. The particular
variants of load/store instructions is influenced by their targeting from a
compiler. Having pairs of load instructions that can write&amp;nbsp;to &lt;code&gt;areg&lt;/code&gt; or
&lt;code&gt;breg&lt;/code&gt; (such&amp;nbsp;as &lt;code&gt;LDAM&lt;/code&gt; and &lt;code&gt;LDBM&lt;/code&gt;) gives flexibility when generating
operands for binary operations, whereas having only single variants of stores&amp;nbsp;(&lt;code&gt;STAM&lt;/code&gt; and &lt;code&gt;STAI&lt;/code&gt;) fits most cases where expression results generated&amp;nbsp;into
&lt;code&gt;areg&lt;/code&gt; need to be written to&amp;nbsp;memory.&lt;/p&gt;
&lt;h3&gt;Branching&lt;/h3&gt;
&lt;p&gt;For branching, a relative branch is provided&amp;nbsp;with &lt;code&gt;BR&lt;/code&gt;, which can be used, for
example, to reach a label location. Conditional branch&amp;nbsp;versions &lt;code&gt;BRZ&lt;/code&gt; and
&lt;code&gt;BRN&lt;/code&gt; are used to implement logical binary operations (less than, equal etc)&amp;nbsp;and &lt;code&gt;BRB&lt;/code&gt; is an absolute branch that is used, for example, to return to
a calling function using an address retrieved from memory (see example in next&amp;nbsp;section).&lt;/p&gt;
&lt;h3&gt;Address&amp;nbsp;generation&lt;/h3&gt;
&lt;p&gt;A special constant-loading&amp;nbsp;instruction &lt;code&gt;LDAP&lt;/code&gt; is used to generate bytewise
program addresses, relative to the program counter, such as for branch targets.
The following instruction sequence performs a call&amp;nbsp;to &lt;code&gt;foo&lt;/code&gt; but first loads
the return (link) address&amp;nbsp;using &lt;code&gt;LDAP&lt;/code&gt; to use&amp;nbsp;with &lt;code&gt;BR&lt;/code&gt;. The&amp;nbsp;callee &lt;code&gt;foo&lt;/code&gt;
returns to the caller&amp;nbsp;using &lt;code&gt;BRB&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;FUNC&lt;span class="w"&gt; &lt;/span&gt;foo
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Save caller address&lt;/span&gt;
...
LDBI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Restore caller address&lt;/span&gt;
OPR&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Return to caller&lt;/span&gt;

PROC&lt;span class="w"&gt; &lt;/span&gt;main
...
LDAP&lt;span class="w"&gt; &lt;/span&gt;lab2
BR&lt;span class="w"&gt; &lt;/span&gt;foo
lab2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These instructions have the following execution&amp;nbsp;trace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;main+32&lt;span class="w"&gt;  &lt;/span&gt;LDAP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# areg = pc (60) + oreg (2) 62&lt;/span&gt;
main+33&lt;span class="w"&gt;  &lt;/span&gt;NFIX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# oreg = 0xFFFFFF00 | oreg (13) &amp;lt;&amp;lt; 4 (0xffffffd0)&lt;/span&gt;
main+34&lt;span class="w"&gt;  &lt;/span&gt;BR&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# pc = pc + oreg (4294967249) (0x00000f)&lt;/span&gt;
foo+0&lt;span class="w"&gt;    &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# breg = mem[oreg (0x000001)] (199994)&lt;/span&gt;
foo+1&lt;span class="w"&gt;    &lt;/span&gt;STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# mem[breg (199994) + oreg (0) = 0x030d3a] = areg (62)&lt;/span&gt;
...
foo+10&lt;span class="w"&gt;   &lt;/span&gt;LDBI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# breg = mem[breg (199994) + oreg (0) = 0x030d3a] (62)&lt;/span&gt;
foo+11&lt;span class="w"&gt;   &lt;/span&gt;OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# BRB pc = breg (0x00003e)&lt;/span&gt;
main+35&lt;span class="w"&gt;  &lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;The X language &lt;a name="the-x-language" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The X language is defined in &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/xhexnotes.pdf"&gt;a separate
&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;. X is simple enough that it can
be compiled using simple techniques to the Hex architecture, whilst providing
enough flexibility to express complex programs such as its own compiler (more
on that later). X is an imperative language and has features for procedure
calling, composition of statements, looping and conditional statements,
expressions including function calls, and representation of memory with
variables and arrays. To give an indicative example of X programming, the
following program implements Bubblesort to sort an array of four&amp;nbsp;elements:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Limitations of X to note that simplify its implementation&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Arrays are limited to one&amp;nbsp;dimension.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No operator precedence to avoid built-in rules so precedence must be
  indicated explicitly with bracketing (apart from associative&amp;nbsp;operators).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Conditional statements&amp;nbsp;(beginning &lt;code&gt;if&lt;/code&gt;) must always have&amp;nbsp;an &lt;code&gt;else&lt;/code&gt; part
  to simplify&amp;nbsp;parsing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Variables can only be passed by value into&amp;nbsp;procedures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is no block scoping so variable and array declarations can only be made
  at global and procedure scopes. Similarly, nested definitions of procedures
  are not&amp;nbsp;permitted.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other noteworthy features of X&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There are two types of procedure: &lt;strong&gt;processes&lt;/strong&gt; (using&amp;nbsp;the &lt;code&gt;proc&lt;/code&gt; keyword)
  that execute a sequence of steps with possible side effects, and
  &lt;strong&gt;functions&lt;/strong&gt; (using&amp;nbsp;the &lt;code&gt;func&lt;/code&gt;keyword ) that have no side effects and return
  a&amp;nbsp;value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Names in a program are introduced as &lt;strong&gt;definitions&lt;/strong&gt; of processes or functions,
  &lt;strong&gt;declarations&lt;/strong&gt; that represent memory locations, and &lt;strong&gt;abbreviations&lt;/strong&gt; that
  introduce alternative names for expressions, arrays, processes and&amp;nbsp;functions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The scoping and abbreviation rules are defined so that that actual parameters
  act as abbreviations of the supplied formals. This allows processes and
  functions to be compiled by either as closed subroutines or by substitution of
  the body at the call site, either as a source code transformation or compiler
  optimisation. For example, given the&amp;nbsp;definition &lt;code&gt;proc foo(val a, array b) is B&lt;/code&gt;,
  it can be called as a&amp;nbsp;subroutine: &lt;code&gt;foo(x, y)&lt;/code&gt; or&amp;nbsp;substituted: &lt;code&gt;val a = x; array b = y; B&lt;/code&gt;
  providing the names are unique in the&amp;nbsp;procedure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code&gt;valof&lt;/code&gt; element allows processes to be called from expressions to
  generate values, however it is not implemented&amp;nbsp;in &lt;code&gt;xhexb&lt;/code&gt; or &lt;code&gt;xcmp&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Hex processor integrated circuit &lt;a name="hex-processor-integrated-circuit" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A hardware implementation of the Hex processor is written in System Verilog,
&lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/verilog/processor.sv"&gt;&lt;code&gt;processor.sv&lt;/code&gt;&lt;/a&gt;,
in just 150 lines. This implementation is single cycle in that all elements of
instruction execution (ie instruction fetch from memory, decode, instruction
memory access and state writeback) are completed in that time. A separate
memory module,
&lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/verilog/memory.sv"&gt;&lt;code&gt;memory.sv&lt;/code&gt;&lt;/a&gt;
implements a single-cycle random-access memory with two ports: one for
instruction fetch and the other for data access so that they can occur
simultaneously in the same cycle. Note that because memory access time
increases with the memory capacity, a implementation of Hex accessing a large
memory (ie more than a few thousand bytes) would add pipelining to hide the
latency to memory. Some degree of pipelining is standard in processor
implementations. The hardware design is simulated using Verilator, with C++
testbench driver code in &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hextb.cpp"&gt;&lt;code&gt;hextb.cpp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using &lt;a href="https://theopenroadproject.org/"&gt;OpenROAD&lt;/a&gt;, an open-source tool chain
for performing synthesis, optimisation and physical layout of digital circuits,
we can compile Hex into an integrated circuit layout in order that it could be
manufactured into a silicon device. OpenROAD uses the
&lt;a href="https://github.com/google/skywater-pdk"&gt;SkyWater Process Design Kit&lt;/a&gt; (&lt;span class="caps"&gt;PDK&lt;/span&gt;),
for creating designs in 130 nm process technology, which was a technology first
commercialised in 2001. The &lt;span class="caps"&gt;PDK&lt;/span&gt; is a collection of analog and digital cell
libraries, design rules and tooling. Since OpenROAD uses
&lt;a href="https://yosyshq.net/yosys/"&gt;Yosys&lt;/a&gt; for synthesis, and it doesn&amp;#8217;t support
particular SystemVerilog features, I used
&lt;a href="https://github.com/zachjs/sv2v"&gt;sv2v&lt;/a&gt; to convert the implementation to plain
Verilog 2005 (see &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/verilog/processor.v"&gt;&lt;code&gt;processor.v&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The physical design is based on an OpenROAD &lt;a href="https://openroad.readthedocs.io/en/latest/tutorials/FlowTutorial.html"&gt;default
flow&lt;/a&gt;,
which takes a few minutes to be compiled from the source &lt;span class="caps"&gt;RTL&lt;/span&gt;. The final design
has the following&amp;nbsp;characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A die size of ~280x280&amp;nbsp;microns.&lt;/li&gt;
&lt;li&gt;A total of 9,719 standard&amp;nbsp;cells.&lt;/li&gt;
&lt;li&gt;A cell area of 16,706 square microns at 25%&amp;nbsp;utilisation.&lt;/li&gt;
&lt;li&gt;A clock speed of 229&amp;nbsp;MHz.&lt;/li&gt;
&lt;li&gt;Total switching power of 4.12&amp;nbsp;mW.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The OpenROAD &lt;span class="caps"&gt;GUI&lt;/span&gt; provides many ways to visualise and explore the design. The
following images are some examples of the different&amp;nbsp;views.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-stdcells.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-stdcells_600x600.png" alt="Floorplan showing the standard cells only, with the two lowest metal layers (logic and M1)."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Floorplan showing the standard cells only, with the two lowest metal layers (logic and M1).&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-closeup.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-closeup_600x600.png" alt="A zoomed view showing standard cells with logic and M1 layers only."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A zoomed view showing standard cells with logic and M1 layers only.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-clocktree.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-clocktree_600x600.png" alt="A view showing all nets constituting the clock tree."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A view showing all nets constituting the clock tree.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-routing-congestion.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-routing-congestion_600x600.png" alt="A heatmap view representing routing congestion."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A heatmap view representing routing congestion.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-setup-worstpath.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-setup-worstpath_600x600.png" alt="A visualisation of the worst setup path in the design, including the nets and cells on the path as well as the paths for the launch and capture clocks."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;A visualisation of the worst setup path in the design, including the nets and cells on the path as well as the paths for the launch and capture clocks.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/floorplan-hold-worstpath.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorplan-hold-worstpath_600x600.png" alt="The same visualisation for the worst (least slack) hold path in the design."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The same visualisation for the worst (least slack) hold path in the design.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Hex tooling &lt;a name="hex-tooling" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are three tools provided in the Hex toolchain: a Hex instruction set&amp;nbsp;simulator &lt;code&gt;hexsim&lt;/code&gt;, a Hex&amp;nbsp;assembler &lt;code&gt;hexasm&lt;/code&gt; and an X&amp;nbsp;compiler &lt;code&gt;xcmp&lt;/code&gt;.
Instructions on how to build the tools are included in the
&lt;a href="https://jameshanlon.github.io/hex-processor"&gt;documentation&lt;/a&gt;.
The implementation is provided in a small number of source files (with only one
external dependency&amp;nbsp;on &lt;code&gt;boost::format&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;General Hex definitions are provided in
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hex.hpp"&gt;&lt;code&gt;hex.hpp&lt;/code&gt;&lt;/a&gt; and
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hex.cpp"&gt;&lt;code&gt;hex.cpp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Hex simulator is implemented in the headers
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hexsim.hpp"&gt;&lt;code&gt;hexsim.hpp&lt;/code&gt;&lt;/a&gt; and
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hexsimio.hpp"&gt;&lt;code&gt;hexsimio.hpp&lt;/code&gt;&lt;/a&gt;.
  (Note that listings for a complete simulator in C are given in the &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/hexb.pdf"&gt;Hex definition (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Hex assembler is implemented in the header
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hexasm.hpp"&gt;&lt;code&gt;hexasm.hpp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The X compiler is implemented in the header
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/xcmp.hpp"&gt;&lt;code&gt;xcmp.hpp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Driver code for the respective command-line&amp;nbsp;tools &lt;code&gt;hexsim&lt;/code&gt;, &lt;code&gt;hexasm&lt;/code&gt; and
  &lt;code&gt;xcmp&lt;/code&gt; is implemented in
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hexsim.cpp"&gt;&lt;code&gt;hexsim.cpp&lt;/code&gt;&lt;/a&gt;,
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/hexasm.cpp"&gt;&lt;code&gt;hexasm.cpp&lt;/code&gt;&lt;/a&gt; and
  &lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/xcmp.cpp"&gt;&lt;code&gt;xcmp.cpp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;A simple&amp;nbsp;example&lt;/h3&gt;
&lt;p&gt;Taking a most basic example of an assembly program that simply&amp;nbsp;exits:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;tests/asm/exit0.S
BR&lt;span class="w"&gt; &lt;/span&gt;start
DATA&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16383&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# sp&lt;/span&gt;
start
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# areg &amp;lt;- 0&lt;/span&gt;
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# breg &amp;lt;- sp&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# sp[2] &amp;lt;- areg&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
OPR&lt;span class="w"&gt; &lt;/span&gt;SVC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The assembler can display the program layout in memory and computed symbol&amp;nbsp;values:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;hexasm&lt;span class="w"&gt; &lt;/span&gt;tests/asm/exit0.S&lt;span class="w"&gt; &lt;/span&gt;--instrs
&lt;span class="m"&gt;00000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;BR&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x000004&lt;span class="w"&gt; &lt;/span&gt;DATA&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16383&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x000008&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x000008&lt;span class="w"&gt; &lt;/span&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x000009&lt;span class="w"&gt; &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x00000a&lt;span class="w"&gt; &lt;/span&gt;STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x00000b&lt;span class="w"&gt; &lt;/span&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
0x00000c&lt;span class="w"&gt; &lt;/span&gt;OPR&lt;span class="w"&gt; &lt;/span&gt;SVC&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;00000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;PADDING&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And create a 13-byte executable&amp;nbsp;binary:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;hexasm&lt;span class="w"&gt; &lt;/span&gt;tests/asm/exit0.S
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This binary can then be simulated with tracing to show what&amp;#8217;s going on (the
first column is the cycle count and the second is&amp;nbsp;the &lt;code&gt;pc&lt;/code&gt; value):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;-t
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;BR&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pc&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000008&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;areg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;breg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000001&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16383&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;breg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16383&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0x004001&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;areg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;areg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The X compiler can be used to produce more complex Hex programs. Starting with
a similar most basic program  written in&amp;nbsp;X:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;proc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This null program is compiled into Hex assembly, where the entry code&amp;nbsp;calls
&lt;code&gt;main&lt;/code&gt; then exits,&amp;nbsp;and &lt;code&gt;main&lt;/code&gt; does nothing (apart from saving and restoring
the link&amp;nbsp;location):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;xcmp&lt;span class="w"&gt; &lt;/span&gt;tests/x/exit.x&lt;span class="w"&gt; &lt;/span&gt;--insts-lowered
BR&lt;span class="w"&gt; &lt;/span&gt;start
DATA&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;
start
LDAP&lt;span class="w"&gt; &lt;/span&gt;_exit
BR&lt;span class="w"&gt; &lt;/span&gt;main
_exit
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
OPR&lt;span class="w"&gt; &lt;/span&gt;SVC

PROC&lt;span class="w"&gt; &lt;/span&gt;main
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
lab0
LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
LDBI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
OPR&lt;span class="w"&gt; &lt;/span&gt;BRB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And when simulated produces the following trace where execution&amp;nbsp;through
&lt;code&gt;main&lt;/code&gt; can be seen since it is the only labelled portion of the&amp;nbsp;code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;-t
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;BR&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pc&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000008&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;LDAP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;areg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;BR&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pc&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x00000e&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;main+0&lt;span class="w"&gt;       &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;breg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000001&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;main+1&lt;span class="w"&gt;       &lt;/span&gt;STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;breg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0x030d3f&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;areg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;main+2&lt;span class="w"&gt;       &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;breg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000001&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;main+3&lt;span class="w"&gt;       &lt;/span&gt;LDBI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;breg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;breg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0x030d3f&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;main+4&lt;span class="w"&gt;       &lt;/span&gt;OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;BRB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;breg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x00000a&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;LDBM&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;breg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x000001&lt;span class="o"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;LDAC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;areg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;STAI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;mem&lt;span class="o"&gt;[&lt;/span&gt;breg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;199999&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;oreg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0x030d41&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;areg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The program can also be run on the Verilog Hex implementation&amp;nbsp;using &lt;code&gt;hextb&lt;/code&gt;
(which doesn&amp;#8217;t provide as rich instruction tracing&amp;nbsp;as &lt;code&gt;hexsim&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;hextb&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;-t
Wrote&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;memory
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;0x51&lt;span class="w"&gt; &lt;/span&gt;LDAP
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;0x94&lt;span class="w"&gt; &lt;/span&gt;BR
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x11&lt;span class="w"&gt; &lt;/span&gt;LDBM
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x80&lt;span class="w"&gt; &lt;/span&gt;STAI
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x11&lt;span class="w"&gt; &lt;/span&gt;LDBM
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x70&lt;span class="w"&gt; &lt;/span&gt;LDBI
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0xd0&lt;span class="w"&gt; &lt;/span&gt;OPR
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x11&lt;span class="w"&gt; &lt;/span&gt;LDBM
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;27&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x30&lt;span class="w"&gt; &lt;/span&gt;LDAC
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;29&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0x82&lt;span class="w"&gt; &lt;/span&gt;STAI
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;0xd3&lt;span class="w"&gt; &lt;/span&gt;OPR
&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Hello&amp;nbsp;World&lt;/h3&gt;
&lt;p&gt;A more fulsome example is &amp;#8216;Hello World&amp;#8217;, where the main process is&amp;nbsp;simply:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;proc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;prints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello world\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And &lt;code&gt;prints&lt;/code&gt; unpacks the bytewise string representation by using routines for
performing division and remainder by 265. The full program listing&amp;nbsp;is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;tests/x/hello_prints.x
val&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;put&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
val&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bytesperword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
var&lt;span class="w"&gt; &lt;/span&gt;div_x&lt;span class="p"&gt;;&lt;/span&gt;

proc&lt;span class="w"&gt; &lt;/span&gt;main&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;prints&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hello world\n&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

proc&lt;span class="w"&gt; &lt;/span&gt;putval&lt;span class="o"&gt;(&lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;put&lt;span class="o"&gt;(&lt;/span&gt;c,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

func&lt;span class="w"&gt; &lt;/span&gt;lsu&lt;span class="o"&gt;(&lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;x,&lt;span class="w"&gt; &lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;x&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;y&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;x&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;y
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;

func&lt;span class="w"&gt; &lt;/span&gt;div_step&lt;span class="o"&gt;(&lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;b,&lt;span class="w"&gt; &lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;r&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;y&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;~lsu&lt;span class="o"&gt;(&lt;/span&gt;y,&lt;span class="w"&gt; &lt;/span&gt;div_x&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;r&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;r&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_step&lt;span class="o"&gt;(&lt;/span&gt;b&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;b,&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~lsu&lt;span class="o"&gt;(&lt;/span&gt;div_x,&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_x&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_x&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;r&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;r&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;b
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;skip&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;r
&lt;span class="o"&gt;}&lt;/span&gt;

func&lt;span class="w"&gt; &lt;/span&gt;div&lt;span class="o"&gt;(&lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;n,&lt;span class="w"&gt; &lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;m&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_x&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;n&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;lsu&lt;span class="o"&gt;(&lt;/span&gt;n,&lt;span class="w"&gt; &lt;/span&gt;m&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_step&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;m&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

func&lt;span class="w"&gt; &lt;/span&gt;rem&lt;span class="o"&gt;(&lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;n,&lt;span class="w"&gt; &lt;/span&gt;val&lt;span class="w"&gt; &lt;/span&gt;m&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;x&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;x&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div&lt;span class="o"&gt;(&lt;/span&gt;n,&lt;span class="w"&gt; &lt;/span&gt;m&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div_x
&lt;span class="o"&gt;}&lt;/span&gt;

proc&lt;span class="w"&gt; &lt;/span&gt;prints&lt;span class="o"&gt;(&lt;/span&gt;array&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;n&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;w&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;l&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;var&lt;span class="w"&gt; &lt;/span&gt;b&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;n&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;w&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="o"&gt;[&lt;/span&gt;p&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;l&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rem&lt;span class="o"&gt;(&lt;/span&gt;w,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;w&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div&lt;span class="o"&gt;(&lt;/span&gt;w,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;b&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;n&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;l&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;putval&lt;span class="o"&gt;(&lt;/span&gt;rem&lt;span class="o"&gt;(&lt;/span&gt;w,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;w&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;div&lt;span class="o"&gt;(&lt;/span&gt;w,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;n&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;n&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;b&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;b&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytesperword&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;b&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;w&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="o"&gt;[&lt;/span&gt;p&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;skip
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Compiling and running this shows that it takes ~50K cycles to execute and
inspecting the trace is clear to see that most time is spent in the arithmetic&amp;nbsp;routines.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;xcmp&lt;span class="w"&gt; &lt;/span&gt;tests/x/hello_prints.x
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out
hello&lt;span class="w"&gt; &lt;/span&gt;world
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;-t
...
&lt;span class="m"&gt;48902&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;61&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;OPR&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Building an X compiler and&amp;nbsp;bootstrapping&lt;/h3&gt;
&lt;p&gt;A third example is a complete compiler for X, written in X:
&lt;a href="https://github.com/jameshanlon/hex-processor/blob/master/tests/x/xhexb.x"&gt;&lt;code&gt;xhexb.x&lt;/code&gt;&lt;/a&gt;
written by David May in ~3,000 lines of X. This serves as a challenging program
to compile, and interesting that it can bootstrap itself. Using the notation
X(Y) to mean compile source Y using binary X, we can first create&amp;nbsp;an &lt;code&gt;xhexb&lt;/code&gt;
binary by&amp;nbsp;running &lt;code&gt;xcmp&lt;/code&gt;(&lt;code&gt;xhexb.x&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt; &lt;/span&gt;xcmp&lt;span class="w"&gt; &lt;/span&gt;-S&lt;span class="w"&gt; &lt;/span&gt;tests/x/xhexb.x
...
&lt;span class="m"&gt;20739&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can then&amp;nbsp;use &lt;code&gt;xcmp&lt;/code&gt;(&lt;code&gt;xhexb.x&lt;/code&gt;) to compile Hello World&amp;nbsp;as
&lt;code&gt;xcmp&lt;/code&gt;(&lt;code&gt;xhexb.x&lt;/code&gt;)(&lt;code&gt;hello_prints.x&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create an xhexb compiler binary.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;xcmp&lt;span class="w"&gt; &lt;/span&gt;tests/x/xhexb.x

&lt;span class="c1"&gt;# Compile Hello World.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;tests/x/hello_prints.x
tree&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;602&lt;/span&gt;
program&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;414&lt;/span&gt;
size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;414&lt;/span&gt;

&lt;span class="c1"&gt;# Run it.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;simout2
hello&lt;span class="w"&gt; &lt;/span&gt;world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Similarly, we can&amp;nbsp;use &lt;code&gt;xcmp&lt;/code&gt;(&lt;code&gt;xhexb.x&lt;/code&gt;) to bootstrap itself by&amp;nbsp;running
&lt;code&gt;xcmp&lt;/code&gt;(&lt;code&gt;xhexb.x&lt;/code&gt;)(&lt;code&gt;xhexb.x&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create an xhexb compiler binary.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;xcmp&lt;span class="w"&gt; &lt;/span&gt;tests/x/xhexb.x

&lt;span class="c1"&gt;# Use xhexb binary to compile xhexb.x.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;a.out&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;tests/x/xhexb.x
tree&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18631&lt;/span&gt;
program&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17093&lt;/span&gt;
size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;177097&lt;/span&gt;

&lt;span class="c1"&gt;# Use the bootstrapped xhexb binary to compile Hello World.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;simout2&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;tests/x/hello_prints.x
tree&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;602&lt;/span&gt;
program&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;414&lt;/span&gt;
size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;414&lt;/span&gt;

&lt;span class="c1"&gt;# Run it.&lt;/span&gt;
➜&lt;span class="w"&gt; &lt;/span&gt;hexsim&lt;span class="w"&gt; &lt;/span&gt;simout2
hello&lt;span class="w"&gt; &lt;/span&gt;world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Implementation&amp;nbsp;details&lt;/h3&gt;
&lt;p&gt;Both the assembler and compiler are based on&amp;nbsp;the &lt;code&gt;xhexb.x&lt;/code&gt; bootstrapping
compiler for X discussed&amp;nbsp;above.&lt;/p&gt;
&lt;p&gt;The assembler works in two main&amp;nbsp;phases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parsing the program to form a list of directives (instructions, labels, data&amp;nbsp;etc).&lt;/li&gt;
&lt;li&gt;Code generation to iterate through the directives and emit binary&amp;nbsp;output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before emission, the value of labels must be determined, which involves solving two
problems. The first is that for a given relative reference, the length of the
encoding (ie number of prefixes) depends on the value of the reference and vice
versa. This is solved by iteratively increasing the encoding length until it
meets the required range&amp;nbsp;(see &lt;code&gt;instrLen()&lt;/code&gt;). The second problem is that the
value of a relative reference depends on the length of any relative encodings
contained within the range. This is solved by iteratively updating label values
until they reach a stable state&amp;nbsp;(see &lt;code&gt;resolveLabels()&lt;/code&gt;). The assembler adds
additional rudimentary debug information to the binary, with a mapping of
instruction ranges to symbol values. This allows the simulator to display the
current symbol and&amp;nbsp;offset.&lt;/p&gt;
&lt;p&gt;The compiler works a traditional way, structured as a sequence of phases, first
creating a parse tree, then performing passes on the tree to optimise it and
then lowering the tree to machine&amp;nbsp;instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parse the program to form an abstract syntax&amp;nbsp;tree.&lt;/li&gt;
&lt;li&gt;Walk the tree to populate a symbol table with names occurring in the&amp;nbsp;program.&lt;/li&gt;
&lt;li&gt;Walk the tree to propagate constant values within&amp;nbsp;expressions.&lt;/li&gt;
&lt;li&gt;Walk the tree to transform expressions into a canonical&amp;nbsp;form.&lt;/li&gt;
&lt;li&gt;Walk the tree to generate a sequence of intermediate machine&amp;nbsp;instructions.&lt;/li&gt;
&lt;li&gt;Lower the intermediate instructions to machine&amp;nbsp;instructions.&lt;/li&gt;
&lt;li&gt;Optimise the machine instruction&amp;nbsp;sequence.&lt;/li&gt;
&lt;li&gt;Assemble and emit the machine instruction&amp;nbsp;sequence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Command line options such&amp;nbsp;as &lt;code&gt;--tree&lt;/code&gt; are available to inspect the internal
representation of the program in between these&amp;nbsp;stages.&lt;/p&gt;
&lt;p&gt;Compared with a more sophisticated compiler, Hex and X afford two significant
simplifications. First, the small set of features in X make it straightforward
to map to directly to machine instructions rather than an intermediate
machine-independent representation. Secondly, the register architecture of Hex
means that allocation of registers can be handled easily during mapping to
machine instructions, rather than having to allocate physical registers to a
virtual set as is typical in machines with more&amp;nbsp;registers.&lt;/p&gt;
&lt;p&gt;More details of&amp;nbsp;the &lt;code&gt;xhexb&lt;/code&gt; compiler implementation are included in the &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/hex-processor/xhexnotes.pdf"&gt;X
and Hex notes &lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;, with aspects such as the
calling convention, handling of operators and arithmetic and memory layout
being shared&amp;nbsp;in &lt;code&gt;xcmp&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;A historical note &lt;a name="a-historical-note" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hex, apart from being related to the Transputer, has some other interesting
historical roots. David May learned about languages and compilers from &lt;a href="https://www.cl.cam.ac.uk/~mr10/"&gt;Martin
Richards&lt;/a&gt; who was a young lecturer when David
completed his final-year Computer Science course as a student at King&amp;#8217;s College
Cambridge (the first student to do so). Martin was the designer of the
influential language &lt;span class="caps"&gt;BCPL&lt;/span&gt; and its portable compiler technology. &lt;span class="caps"&gt;BCPL&lt;/span&gt; &lt;a href="https://arstechnica.com/features/2020/12/a-damn-stupid-thing-to-do-the-origins-of-c/"&gt;found its
way&lt;/a&gt;
to Bell Labs where &lt;span class="caps"&gt;UNIX&lt;/span&gt; was being developed. &lt;span class="caps"&gt;BCPL&lt;/span&gt; was the direct precursor to C
and so led to the portability of &lt;span class="caps"&gt;UNIX&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;When David moved from Cambridge to Warwick, the only useful language on the
Modular One minicomputer that was available was &lt;span class="caps"&gt;BCPL&lt;/span&gt; but the compiler was
incomplete. So David completed the compiler and ported &lt;span class="caps"&gt;BCPL&lt;/span&gt; to other
computers, including some microprocessors. Using techniques similar to &lt;span class="caps"&gt;BCPL&lt;/span&gt;&amp;#8217;s
bootstrapping compiler and interpreter, David designed and implemented a
concurrent language (&lt;span class="caps"&gt;EPL&lt;/span&gt;), bringing him into contact with Tony Hoare and Iann
Barron (founder of the company that designed the Modular One and also of&amp;nbsp;Inmos).&lt;/p&gt;
&lt;p&gt;David employed the same techniques again at Inmos to build the first implementation of
Occam in the 1980s and then again in 2008 for the project that led to the founding
of &lt;span class="caps"&gt;XMOS&lt;/span&gt; (incidentally, I used this compiler in my PhD work to demonstrate
techniques of compiling message-passing programs). Hex and X follow directly from
the &lt;span class="caps"&gt;BCPL&lt;/span&gt;-derived approaches, used by David as a tool to teach students about
instruction sets, compilers, bootstrapping&amp;nbsp;etc.&lt;/p&gt;
&lt;h2&gt;Summary &lt;a name="summary" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Modern processors, languages, compilers, and tooling are complex and difficult
to understand. This note walks through possibly the simplest processor
architecture that allows a compact implementation of rudimentary tooling and a
complete high-level programming language to be targeted at it. The definitions
and implementations are contained in a single repository and just a small set
of source files, making it an excellent project to use to explore processors
and&amp;nbsp;compilers.&lt;/p&gt;
&lt;h2&gt;Similar projects &lt;a name="similar-projects" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://bighexmachine.github.io"&gt;The Big Hex Machine&lt;/a&gt; is a giant hands-on
implementation of a Hex processor. It was designed and built by students and
staff at the University of Bristol&amp;#8217;s Computer Science&amp;nbsp;Department.&lt;/p&gt;
&lt;p&gt;Here are some other related projects that include simple implementations of
processors and/or their&amp;nbsp;toolchains.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.cl.cam.ac.uk/~mr10/VSPL.html"&gt;&lt;span class="caps"&gt;VSPL&lt;/span&gt;&lt;/a&gt;, is a very simple
  programming language designed by Martin Richards to be used as a case study
  for comparing compiler implementations. The provided source distribution
  includes several implementations of &lt;span class="caps"&gt;VSPL&lt;/span&gt; in different&amp;nbsp;languages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://people.inf.ethz.ch/wirth/FPGA-relatedWork/ComputerSystemDesign.pdf"&gt;Experiments in Computer System
  Design&lt;/a&gt;
  is a walk through of an implementation of a Tiny Register Machine (&lt;span class="caps"&gt;TRM&lt;/span&gt;) in
  Verilog with serial communication, &lt;span class="caps"&gt;DRAM&lt;/span&gt; access and multiprocessing (Niklaus
  Wirth,&amp;nbsp;2010).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/cksystemsteaching/selfie"&gt;Selfie&lt;/a&gt; is an educational
  platform for teaching programming languages and runtime systems. It is based
  on a simplified &lt;span class="caps"&gt;RISC&lt;/span&gt;-V architecture and includes a self-contained self-hosting
  compiler for a subset of C, an emulator, a hypervisor and a small standard
  library for the language. These tools are implemented in a single file (~12K
  lines of&amp;nbsp;code).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/eliben/luz-cpu"&gt;Luz &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/a&gt;, a simulator, assembler and
  linker for the Luz processor architecture written by Eli&amp;nbsp;Bendersky.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bigmessowires.com/nibbler/"&gt;Nibbler 4 Bit &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/a&gt; is a complete
  description of a processor that has been implemented in discreet logic&amp;nbsp;chips.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://imihajlov.tk/blog/posts/ccpu/"&gt;Discrete logic &lt;span class="caps"&gt;IC&lt;/span&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/a&gt; us an
  architecture, discrete-logic implementation and basic tooling including a
  programming&amp;nbsp;language.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Further reading &lt;a name="further-reading" class="anchor"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.gamezero.com/team-0/articles/math_magic/micro/"&gt;Processor Design: An
  Introduction&lt;/a&gt; a
  ground-up explanation of how processors&amp;nbsp;work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://releases.llvm.org/9.0.0/docs/tutorial/LangImpl01.html"&gt;&lt;span class="caps"&gt;LLVM&lt;/span&gt; Kaleidoscope
  Tutorial&lt;/a&gt;
  which walks through an implementation of a simple programming language using
  &lt;span class="caps"&gt;LLVM&lt;/span&gt; as a backend for code generation and just-in-time&amp;nbsp;compilation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="computer-architecture"/><category term="microelectronics"/></entry><entry><title>Seeding parallel xoroshiro128+ generators</title><link href="https://jameswhanlon.com/seeding-parallel-xoroshiro128-generators.html" rel="alternate"/><published>2022-10-01T00:00:00+02:00</published><updated>2022-10-01T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2022-10-01:/seeding-parallel-xoroshiro128-generators.html</id><summary type="html">&lt;p&gt;Choosing seeds for parallel xoroshiro128+ generators using fixed
offsets produces correlated&amp;nbsp;outputs.&lt;/p&gt;</summary><content type="html">&lt;p&gt;As part of the &lt;a href="/the-hardware-pseudorandom-number-generator-of-the-graphcore-ipu"&gt;statistical quality
analysis&lt;/a&gt; I
did of the of&amp;nbsp;the &lt;code&gt;xoroshiro128aox&lt;/code&gt; &lt;span class="caps"&gt;PRNG&lt;/span&gt;, I looked at interleaved parallel
generators (where a single generator is created by round-robin interleaving the
output $n$ identical generators with different seeds) as a way to test its
suitability for parallel processing. Against my intuition, I found that simple
seeding schemes produce poor interleaved generators, and even when the
subsequences are disjoint. These findings equally apply&amp;nbsp;to &lt;code&gt;xoroshiro128+&lt;/code&gt; as
we will&amp;nbsp;see.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;xoroshiro128+&lt;/code&gt; creators &lt;a href="https://prng.di.unimi.it"&gt;recommend using a jump
function&lt;/a&gt; to seed parallel generators to
deterministically move to disjoint parts of the sequence. However, computing
jumps is expensive to do in hardware because it involves 128-bit arithmetic and
so it is preferable to compute seed values based on a simpler function of a
machine&amp;#8217;s state, such as an integer identifier for a process/thread. Since the
probability of any two randomly-chosen sequences overlap is very small even
with a large number of sequences, it seems reasonable to assume that a simple
seed generator will perform okay in practice. Note also that the creators
separately recommend &amp;#8220;that initialization must be performed with a generator
radically different in nature from the one initialized to avoid correlation on
similar seeds&amp;#8221;, based on &lt;a href="https://dl.acm.org/citation.cfm?doid=1276927.1276928"&gt;research from
2007&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To investigate the use of simple seeding schemes, I ran tests against
interleaved generators with three representative options (the source code is
available on &lt;a href="https://github.com/jameshanlon/prng-testing"&gt;GitHub&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;With equidistant intervals from 1 in the natural number sequence [Scheme A],
defined in Python notation&amp;nbsp;as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With equidistant intervals starting from a random offset [Scheme&amp;nbsp;B]:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By adding a fixed offset to a initial state of balanced 0s and 1s [Scheme&amp;nbsp;C]:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_SEEDS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x55555555555555555555555555555555&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And, as&amp;nbsp;baselines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using&amp;nbsp;the &lt;code&gt;xoroshiro128&lt;/code&gt; jump function, jumping $2^{64}$ steps [Scheme&amp;nbsp;D].&lt;/li&gt;
&lt;li&gt;Using a minimum-size jump for the number of generators to pass PractRand [Scheme E]
  (for example, the distance for 1000 generators is 4398046511&amp;nbsp;= &lt;code&gt;(32 * 1024**4) / (8 * 1000)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Using a non-linear &lt;span class="caps"&gt;PRNG&lt;/span&gt; to choose seeds (&lt;span class="caps"&gt;PCG64&lt;/span&gt;) [Scheme&amp;nbsp;F].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To test these seeding schemes, I ran each generator against the standard
PractRand test battery. PractRand is a good choice for these tests since it reports
results at intermediate points and consumes much more output than Big Crush or Gjrand:
32 &lt;span class="caps"&gt;TB&lt;/span&gt; by default. A pass is achieved if no overtly suspicious $p$-values are&amp;nbsp;flagged.&lt;/p&gt;
&lt;p&gt;The results are summarised in the following&amp;nbsp;table:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Seeding scheme&lt;/th&gt;
      &lt;th scope="col"&gt;Number of generators&lt;/th&gt;
      &lt;th scope="col"&gt;Output seen&lt;/th&gt;
      &lt;th scope="col"&gt;Failing tests&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme A&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;DC6&lt;/code&gt;, &lt;code&gt;FPF&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme A&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;DC6&lt;/code&gt;, &lt;code&gt;FPF&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme A&lt;/td&gt;
      &lt;td&gt;1000&lt;/td&gt;
      &lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;BCFN&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme B&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;FPF&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme B&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;DC6&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme B&lt;/td&gt;
      &lt;td&gt;1000&lt;/td&gt;
      &lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;BCFN&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme C&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;DC6&lt;/code&gt;, &lt;code&gt;Gap&lt;/code&gt;, &lt;code&gt;FPF&lt;/code&gt;, &lt;code&gt;mod3&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme C&lt;/td&gt;
      &lt;td&gt;100&lt;/td&gt;
      &lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;BCFN&lt;/code&gt;, &lt;code&gt;DC6&lt;/code&gt;, &lt;code&gt;Gap&lt;/code&gt;, &lt;code&gt;FPF&lt;/code&gt;, &lt;code&gt;mod3n&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme C&lt;/td&gt;
      &lt;td&gt;1000&lt;/td&gt;
      &lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;BCFN&lt;/code&gt;, &lt;code&gt;DC6&lt;/code&gt;, &lt;code&gt;Gap&lt;/code&gt;, &lt;code&gt;Brank&lt;/code&gt;, &lt;code&gt;FPF&lt;/code&gt;, &lt;code&gt;mod3n&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme D&lt;/td&gt;
      &lt;td&gt;10,100,1000&lt;/td&gt;
      &lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Pass&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme E&lt;/td&gt;
      &lt;td&gt;10,100,1000&lt;/td&gt;
      &lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Pass&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scheme F&lt;/td&gt;
      &lt;td&gt;10,100,1000&lt;/td&gt;
      &lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Pass&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Note&amp;nbsp;that &lt;code&gt;DC6&lt;/code&gt; and &lt;code&gt;BCFN&lt;/code&gt; are both tests for linearity. For the failing
generators (schemes A-C), I checked there are no duplicate values between the
different generators to establish that no two sequences overlap (using&amp;nbsp;the
&lt;code&gt;analyse&lt;/code&gt; mode). This means that the above failures are due to correlations
between disjoint&amp;nbsp;sequences.&lt;/p&gt;
&lt;p&gt;For reference, below is sample output for running the Scheme A generator with
10 parallel streams against PractRand. There are comprehensive failures within
the first 256 &lt;span class="caps"&gt;MB&lt;/span&gt; of&amp;nbsp;output.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./build/xoroshiro128plus_il_equia_10&lt;span class="w"&gt; &lt;/span&gt;stdout&lt;span class="w"&gt; &lt;/span&gt;std64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./install/PractRand-pre0.95/RNG_test&lt;span class="w"&gt; &lt;/span&gt;stdin64&lt;span class="w"&gt; &lt;/span&gt;-a
RNG_test&lt;span class="w"&gt; &lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;PractRand&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.95
&lt;span class="nv"&gt;RNG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RNG_stdin64,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;seed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unknown
&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;core,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;folding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;standard&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bit&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;RNG_stdin64,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;seed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;unknown
&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;megabytes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;^28&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.3&lt;span class="w"&gt; &lt;/span&gt;seconds
&lt;span class="w"&gt;  &lt;/span&gt;Test&lt;span class="w"&gt; &lt;/span&gt;Name&lt;span class="w"&gt;                         &lt;/span&gt;Raw&lt;span class="w"&gt;       &lt;/span&gt;Processed&lt;span class="w"&gt;     &lt;/span&gt;Evaluation
&lt;span class="w"&gt;  &lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+0,13-2,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.494&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+1,13-2,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+4.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.050&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+2,13-3,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.484&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+3,13-3,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.292&lt;span class="w"&gt;     &lt;/span&gt;normal
...
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+12,13-9,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-2.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.849&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;DC6-9x1Bytes-1&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.332&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:A&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.523&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:B&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+4.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.3e-3&lt;span class="w"&gt;   &lt;/span&gt;normalish
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,14-0&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.434&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low16/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,14-0&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.061&lt;span class="w"&gt;     &lt;/span&gt;normal
...
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+9,13-9,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.310&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+10,13-9,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.372&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;DC6-9x1Bytes-1&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+88.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.9e-51&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:A&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+4.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.6e-3&lt;span class="w"&gt;   &lt;/span&gt;normalish
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:B&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.656&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,14-1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.759&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,14-2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-3.7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;-4.2e-3&lt;span class="w"&gt;   &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;,14-2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.9&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.738&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,14-3&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.189&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;,14-4&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.134&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,14-5&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.206&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;,14-5&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.166&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;,14-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.877&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;,14-7&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.681&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;,14-8&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.187&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;,14-8&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+19.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.5e-14&lt;span class="w"&gt;    &lt;/span&gt;FAIL
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;,14-9&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+12.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0e-8&lt;span class="w"&gt;   &lt;/span&gt;suspicious
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;,14-10&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+12.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.0e-7&lt;span class="w"&gt;   &lt;/span&gt;mildly&lt;span class="w"&gt; &lt;/span&gt;suspicious
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;,14-11&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+5.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.8e-3&lt;span class="w"&gt;   &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;,14-11&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+8.8&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1e-4&lt;span class="w"&gt;   &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:all&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.435&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:cross&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.032&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:128&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.8&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.670&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:256&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.6&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.168&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:384&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.8&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.146&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:512&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.2&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.554&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:768&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.7&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.689&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+14.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.3e-5&lt;span class="w"&gt;   &lt;/span&gt;mildly&lt;span class="w"&gt; &lt;/span&gt;suspicious
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.451&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.492&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.781&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.433&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.353&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.742&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.9&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.152&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.731&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.540&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.585&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low4/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.322&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+0,13-6,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+7.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.5e-3&lt;span class="w"&gt;   &lt;/span&gt;normalish
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+1,13-6,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-3.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.926&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+2,13-6,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.716&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+3,13-6,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.238&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+4,13-7,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.212&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+5,13-8,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.8&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.304&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+6,13-8,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.403&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+7,13-9,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.257&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BCFN&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;+8,13-9,T&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.8&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.790&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;DC6-9x1Bytes-1&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+1379&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.6e-777&lt;span class="w"&gt;   &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:A&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+4863&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;5e-3914&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;Gap-16:B&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+11222&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;6e-8467&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,14-2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+10120&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;5e-8851&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,14-3&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+7164&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;2e-6279&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;,14-4&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+5071&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;9e-4144&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,14-5&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+3567&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;1e-2956&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;,14-5&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+2180&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;7e-1807&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,14-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+1535&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;1e-1174&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;,14-7&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+350.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;.0e-279&lt;span class="w"&gt;   &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;,14-8&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+255.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1e-183&lt;span class="w"&gt;   &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;,14-8&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+235.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.7e-169&lt;span class="w"&gt;   &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;,14-9&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+152.7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.0e-96&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;,14-10&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+87.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.7e-47&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;,14-11&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+58.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.6e-26&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;,14-11&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+58.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.9e-26&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:all&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+14029&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;FPF-14+6/16:cross&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+3119&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;3e-2681&lt;span class="w"&gt;    &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:128&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.2&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.554&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:256&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.0&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.744&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:384&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.7&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.689&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;BRank&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:512&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+0.4&lt;span class="w"&gt;  &lt;/span&gt;p~&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.366&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+322.9&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.1e-111&lt;span class="w"&gt;   &lt;/span&gt;FAIL&lt;span class="w"&gt; &lt;/span&gt;!!!!!
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.563&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.1&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.129&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+5.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.016&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.5&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.099&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-0.8&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.614&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;-1.4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.757&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+1.7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.167&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.111&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Low1/64&lt;span class="o"&gt;]&lt;/span&gt;mod3n&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;,9-6&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;R&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;+2.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.125&lt;span class="w"&gt;     &lt;/span&gt;normal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When choosing seeds for PRNGs operating in parallel, it might seem sufficient
to ensure that the sequences they range over are disjoint, provably or with
high probability. However, correlations between disjoint subsequences do exist
in PRNGs based on&amp;nbsp;the &lt;code&gt;xoroshiro128&lt;/code&gt; linear engine. It is known that these
correlations can manifest when sequences are chosen by a linear generator.
Based on the findings in this note, these correlations also occur when seeds
are created using non-linear operations such as addition. The safest course of
action to take is to follow the guidance of&amp;nbsp;the &lt;code&gt;xoroshiro128&lt;/code&gt; authors and
either use the jump function to traverse the state space or use a high-quality
non-linear &lt;span class="caps"&gt;PRNG&lt;/span&gt; to generate random&amp;nbsp;seeds.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;My &lt;a href="https://github.com/jameshanlon/prng-testing"&gt;&lt;span class="caps"&gt;PRNG&lt;/span&gt; testing&lt;/a&gt; source&amp;nbsp;code.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://prng.di.unimi.it/"&gt;xoshiro / xoroshiro generators and the &lt;span class="caps"&gt;PRNG&lt;/span&gt; shootout&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pracrand.sourceforge.net"&gt;PractRand&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Makoto Matsumoto, Isaku Wada, Ai Kuramoto, and Hyo Ashihara. 2007.
  Common defects in initialization of pseudorandom number generators.
  &lt;a href="https://doi.org/10.1145/1276927.1276928"&gt;&lt;span class="caps"&gt;ACM&lt;/span&gt; Transactions on Modeling and Computer Simulation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="PRNGs"/></entry><entry><title>The hardware pseudorandom number generator of the Graphcore IPU</title><link href="https://jameswhanlon.com/the-hardware-pseudorandom-number-generator-of-the-graphcore-ipu.html" rel="alternate"/><published>2022-09-21T00:00:00+02:00</published><updated>2022-09-21T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2022-09-21:/the-hardware-pseudorandom-number-generator-of-the-graphcore-ipu.html</id><summary type="html">&lt;p&gt;A short summary of an investigation into the statisitical quality and
implementation cost in hardware of the xoroshiro128aox &lt;span class="caps"&gt;PRNG&lt;/span&gt;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This note is a short summary of my &lt;a href="https://ieeexplore.ieee.org/document/9875973"&gt;&lt;span class="caps"&gt;IEEE&lt;/span&gt; Transactions on Computers journal
paper&lt;/a&gt; and was originally written
to appear on the Graphcore&amp;nbsp;blog.&lt;/p&gt;
&lt;p&gt;The Graphcore &lt;span class="caps"&gt;IPU&lt;/span&gt; contains a novel pseudorandom number generator (&lt;span class="caps"&gt;PRNG&lt;/span&gt;) that
was designed to produce high-quality statistical randomness, whist also being
cheap to implement in hardware. Having an efficient hardware &lt;span class="caps"&gt;RNG&lt;/span&gt; means
randomness can be used frequently: the IPUs generator can produce 64-bits of
unique randomness from all of its 1,216 tiles every clock cycle. This, for
example, makes it possible to perform on-the-fly stochastic rounding of
low-precision floating-point&amp;nbsp;numbers.&lt;/p&gt;
&lt;p&gt;We needed a new &lt;span class="caps"&gt;PRNG&lt;/span&gt; because typical state-of-the-art generators are designed
to be performant when run as software routines, but operations that are cheap
to execute on a processor may not be cheap to implement in hardware as is the
case for multiplication or division. Our&amp;nbsp;generator &lt;code&gt;xoroshiro128aox&lt;/code&gt; is based
on &lt;a href="https://vigna.di.unimi.it/"&gt;Sebastiano&amp;nbsp;Vigna’s&lt;/a&gt; &lt;code&gt;xoroshiro128&lt;/code&gt;
linear-feedback shift register (&lt;span class="caps"&gt;LFSR&lt;/span&gt;), which is attractive because it uses 128
bits of state and is cheap to implement in hardware. The &lt;span class="caps"&gt;LFSR&lt;/span&gt; operates by
performing &lt;span class="caps"&gt;XOR&lt;/span&gt; and fixed-distance shift and rotate operations on the state.
Following Vigna’s approach of adding a function to ‘scramble’ the &lt;span class="caps"&gt;LFSR&lt;/span&gt; state,
we have devised a function consisting of &lt;span class="caps"&gt;AND&lt;/span&gt;, &lt;span class="caps"&gt;OR&lt;/span&gt; and &lt;span class="caps"&gt;XOR&lt;/span&gt; operations (called &lt;span class="caps"&gt;AOX&lt;/span&gt;
for short). An C implementation&amp;nbsp;of &lt;code&gt;xoroshiro128aox&lt;/code&gt; is as&amp;nbsp;follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// State vectors&lt;/span&gt;

&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Calculate the result, the &amp;#39;AOX&amp;#39; step.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// xoroshiro128 state update&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;s0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rotl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To determine that this new &lt;span class="caps"&gt;PRNG&lt;/span&gt; provides a good source of randomness, we took
the conventional approach of subjecting the generator to batteries of
statistical tests, that aim to detect correlations over large portions of the
generator’s output. Given that any &lt;span class="caps"&gt;PRNG&lt;/span&gt; is inherently non-random because they
produce numbers according to a fixed sequence, statistical testing is only as
good as the tests that they run, and their performance can only be judged on
their ability to distinguish existing good generators from bad ones. Indeed, a
novel statistical test could immediately raise the bar for all&amp;nbsp;PRNGs.&lt;/p&gt;
&lt;p&gt;Within the field of &lt;span class="caps"&gt;PRNG&lt;/span&gt; design,
&lt;a href="http://simul.iro.umontreal.ca/testu01/tu01.html"&gt;TestU01’s&lt;/a&gt; BigCrush battery
is accepted as the gold-standard statistical test, however it is not always
clear exactly what methodology has been used to obtain a pass/fail result. In
particular, the choice of initial state (the seed) is important because
different parts of a sequence may have different properties, and TestU01 has
known biases in the way it uses bits from a generator’s output. To mitigate
these issues, we run every generator from 100 unique seeds and supply six
permutations of the output bits. And as well as running TestU01, we also run
&lt;a href="http://pracrand.sourceforge.net/"&gt;PractRand&lt;/a&gt; and
&lt;a href="http://gjrand.sourceforge.net/"&gt;Gjrand&lt;/a&gt; with the same 100 seeds, which are the
two other most well-regarded test sets. This gives us a comprehensive testing
methodology that goes beyond the typical level of&amp;nbsp;analysis.&lt;/p&gt;
&lt;p&gt;To provide a point of comparison, we include the following&amp;nbsp;PRNGs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;32-bit Mersenne&amp;nbsp;Twister, &lt;code&gt;mt32&lt;/code&gt;, since it is one of the most widely used
    software PRNGs (although it has 19,937 bits of&amp;nbsp;state!).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;xoroshiro128+&lt;/code&gt;, which is Vigna’s closest variant&amp;nbsp;of &lt;code&gt;xoroshiro128&lt;/code&gt;,
    using 64-bit addition to scramble 128-bit &lt;span class="caps"&gt;LFSR&lt;/span&gt;&amp;nbsp;states.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And to represent the current state-of-the-art 128-bit generators, we&amp;nbsp;include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;philox4x32-10&lt;/code&gt;, a counter-based generator whose transition between states
    is a 128-bit increment and output scrambling function is 10 rounds of 32-bit
  multiplications and&amp;nbsp;XORs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pcg64&lt;/code&gt;, a linear-congruential generator (&lt;span class="caps"&gt;LCG&lt;/span&gt;) that uses multiplication and
    addition by 128-bit constants for the state-transition function, and &lt;span class="caps"&gt;XOR&lt;/span&gt; and
  variable rotation operations to produce&amp;nbsp;outputs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The table below summarises the TestU01 BigCrush results, where the six output
columns correspond to different permutations of the generators bits (eg 1 is
unchanged, 2 is swapping the most and least significant 32 bits) and the
numbers are total failures. Since a true random number generator has a
probability of failing, the expected number of failures can be calculated.
BigCrush runs 160 individual tests (and consumes approximately 1 &lt;span class="caps"&gt;TB&lt;/span&gt; of random
data), so in this case the expected number is 32. A generator is considered to
fail only when it fails on the same test over all seeds, which can be seen in
the entries highlighted in red. The Mersenne Twister consistently fails,
whereas xoroshiro128+ fails on a particular output permutation where the lower
32 bits are discarded (this is a known deficiency of the&amp;nbsp;generator).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col"&gt;Generator&lt;/th&gt;
  &lt;th scope="col"&gt;Output 1&lt;/th&gt;
  &lt;th scope="col"&gt;Output 2&lt;/th&gt;
  &lt;th scope="col"&gt;Output 3&lt;/th&gt;
  &lt;th scope="col"&gt;Output 4&lt;/th&gt;
  &lt;th scope="col"&gt;Output 5&lt;/th&gt;
  &lt;th scope="col"&gt;Output 6&lt;/th&gt;
  &lt;th scope="col"&gt;Total failures&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;mt32&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;236&lt;/td&gt;
  &lt;td&gt;237&lt;/td&gt;
  &lt;td&gt;233&lt;/td&gt;
  &lt;td&gt;238&lt;/td&gt;
  &lt;td&gt;246&lt;/td&gt;
  &lt;td&gt;237&lt;/td&gt;
  &lt;td&gt;1427&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;pcg64&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;34&lt;/td&gt;
  &lt;td&gt;30&lt;/td&gt;
  &lt;td&gt;38&lt;/td&gt;
  &lt;td&gt;37&lt;/td&gt;
  &lt;td&gt;38&lt;/td&gt;
  &lt;td&gt;27&lt;/td&gt;
  &lt;td&gt;204&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;philox4x32-10&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;33&lt;/td&gt;
  &lt;td&gt;32&lt;/td&gt;
  &lt;td&gt;32&lt;/td&gt;
  &lt;td&gt;32&lt;/td&gt;
  &lt;td&gt;28&lt;/td&gt;
  &lt;td&gt;38&lt;/td&gt;
  &lt;td&gt;195&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128+&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;33&lt;/td&gt;
  &lt;td&gt;29&lt;/td&gt;
  &lt;td&gt;28&lt;/td&gt;
  &lt;td&gt;40&lt;/td&gt;
  &lt;td&gt;353&lt;/td&gt;
  &lt;td&gt;42&lt;/td&gt;
  &lt;td&gt;525&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128aox&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;31&lt;/td&gt;
  &lt;td&gt;32&lt;/td&gt;
  &lt;td&gt;41&lt;/td&gt;
  &lt;td&gt;30&lt;/td&gt;
  &lt;td&gt;44&lt;/td&gt;
  &lt;td&gt;32&lt;/td&gt;
  &lt;td&gt;210&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The table below summarises the Gjrand results, which just runs 13 tests and by
default consumes approximately 10 &lt;span class="caps"&gt;TB&lt;/span&gt; of data. Unlike BigCrush and TestU01,
xoroshiro128aox fails Gjrand on both versions of its z9 test, which looks for
dependencies in the Hamming Weight of successive outputs. Although BigCrush and
PractRand include similar tests that analyse Hamming Weight dependencies, they
do not detect correlations. What this shows is that the scrambling of the
xoroshiro128 &lt;span class="caps"&gt;LFSR&lt;/span&gt;’s state serves to hide correlations due to the linear
operations only to an extent, and a particular test will be sensitive enough to
detect them. Given that BigCrush and PractRand did not, xoroshiro128aox
represents a significant improvement over xoroshiro128+, whilst still being
cheap to implement in hardware as we show in the next&amp;nbsp;section.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col"&gt;Generator&lt;/th&gt;
  &lt;th scope="col"&gt;Total failures&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;mt32&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;pcg64&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;philox4x32-10&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128+&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;210&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128aox&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;205&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;To demonstrate that xoroshiro128aox is indeed cheap to implement in hardware,
we compare physical implementations of the generators (excluding Mersenne
Twister because of its considerable state size) after they have been fully
synthesised and placed and routed using Graphcore’s 7 nm cell library and a
target clock period of 1 GHz. The table below summarises the&amp;nbsp;results.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col"&gt;Generator&lt;/th&gt;
  &lt;th scope="col"&gt;Total cells (state update)&lt;/th&gt;
  &lt;th scope="col"&gt;Logic depth (state update)&lt;/th&gt;
  &lt;th scope="col"&gt;Total cells (output)&lt;/th&gt;
  &lt;th scope="col"&gt;Logic depth (output)&lt;/th&gt;
  &lt;th scope="col"&gt;Total cells&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128aox&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;331 &lt;/td&gt;
  &lt;td&gt;4   &lt;/td&gt;
  &lt;td&gt;353 &lt;/td&gt;
  &lt;td&gt;4   &lt;/td&gt;
  &lt;td&gt;684 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;xoroshiro128+&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;331 &lt;/td&gt;
  &lt;td&gt;3   &lt;/td&gt;
  &lt;td&gt;906 &lt;/td&gt;
  &lt;td&gt;13  &lt;/td&gt;
  &lt;td&gt;1237&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;pcg64&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;9564 &lt;/td&gt;
  &lt;td&gt;26   &lt;/td&gt;
  &lt;td&gt;658  &lt;/td&gt;
  &lt;td&gt;7    &lt;/td&gt;
  &lt;td&gt;10222&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;philox4x32-10&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;1003 &lt;/td&gt;
  &lt;td&gt;13   &lt;/td&gt;
  &lt;td&gt;29553&lt;/td&gt;
  &lt;td&gt;89   &lt;/td&gt;
  &lt;td&gt;30556&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Key takeaways from these results&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;That &lt;span class="caps"&gt;AOX&lt;/span&gt; is approximately one third of the cost of a full 64-bit addition and
  the cheapest option overall by a factor of&amp;nbsp;two.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;code&gt;pcg64&lt;/code&gt; the cost is dominated by the 128-bit arithmetic for its state&amp;nbsp;update.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;code&gt;philox4x32-10&lt;/code&gt; the cost is dominated by the output function composed of 10
  stages of 32-bit&amp;nbsp;arithmetic.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following are illustrations of the four &lt;span class="caps"&gt;PRNG&lt;/span&gt; circuit floorplans, which make
clear the differences in implementation complexity (left to&amp;nbsp;right:
&lt;code&gt;xoroshiro128aox&lt;/code&gt;, &lt;code&gt;xoroshiro128+&lt;/code&gt;, &lt;code&gt;pcg64&lt;/code&gt;, &lt;code&gt;philox4x32-10&lt;/code&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/plus.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/plus_600x600.png" alt="xoroshiro128+"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;xoroshiro128+&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/aox.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/aox_600x600.png" alt="xoroshiro128aox"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;xoroshiro128aox&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/pcg64.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/pcg64_600x600.png" alt="pcg64"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;pcg64&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/philox.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/philox_600x600.png" alt="philox4x32-10"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;philox4x32-10&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;And scaled to relative&amp;nbsp;sizes:&lt;/p&gt;
&lt;!--
%          h      w         Scale
% plus     25.8   12.992    1
% aox      23.1   11.648    0.896551724
% pcg      63.9   32        2.463054187
% philox   115.8  57.984    4.463054187
--&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/plus.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/plus_100x100.png" alt="xoroshiro128+"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;xoroshiro128+&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/aox.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/aox_90x90.png" alt="xoroshiro128aox"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;xoroshiro128aox&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/pcg64.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/pcg64_246x246.png" alt="pcg64"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;pcg64&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
  &lt;td&gt;&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/prng-quality/philox.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/philox_446x446.png" alt="philox4x32-10"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;philox4x32-10&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This note has provided an overview of the methodology and results of the
analysis we conducted into the statistical quality of our novel &lt;span class="caps"&gt;PRNG&lt;/span&gt;
&lt;code&gt;xoroshiro128aox&lt;/code&gt;. This has established that our generator mitigates known
existing weaknesses&amp;nbsp;of &lt;code&gt;xoroshiro128+&lt;/code&gt; on which it is based, and delivers
comparable levels of statistical quality on the gold-standard BigCrush test set
as two contemporary fast PRNGs&amp;nbsp;: &lt;code&gt;pcg64&lt;/code&gt; and &lt;code&gt;philox4x32-10&lt;/code&gt;. Extending
testing by using PractRand and Gjrand, we do eventually find that a weakness is
detectable by Gjrand. Since this is not systematic across the test suites, as
we have seen for the Mersenne Twister, we can&amp;nbsp;consider &lt;code&gt;xoroshiro128aox&lt;/code&gt; to
provide an excellent tradeoff between quality and implementation cost in&amp;nbsp;hardware.&lt;/p&gt;
&lt;p&gt;Full details of the investigation can be found in the &lt;a href="https://arxiv.org/abs/2203.04058"&gt;preprint paper on
arXiv&lt;/a&gt;, and the &lt;a href="https://github.com/jameshanlon/prng-testing"&gt;source
code&lt;/a&gt; for the experiments on&amp;nbsp;GitHub.&lt;/p&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="PRNGs"/></entry><entry><title>Garden workshop</title><link href="https://jameswhanlon.com/garden-workshop.html" rel="alternate"/><published>2021-10-04T00:00:00+02:00</published><updated>2021-10-04T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2021-10-04:/garden-workshop.html</id><summary type="html">&lt;p&gt;Design and construction of a office and&amp;nbsp;workshop.&lt;/p&gt;</summary><content type="html">&lt;p&gt;During the summer of 2021 I built a garden workshop. This was a joint endeavour
with my partner, who designed and specified the form and finish (credit for the
&lt;a href="#drawings"&gt;&lt;span class="caps"&gt;CAD&lt;/span&gt; drawings&lt;/a&gt; goes to her). The basic construction follows the methodology of
&lt;a href="https://www.oakwoodgardenrooms.com/"&gt;Oakwood Garden Rooms&lt;/a&gt; who&amp;#8217;s
&lt;a href="https://www.youtube.com/channel/UChqWFbSX8STP_c8W0RVW1Xw"&gt;YouTube channel&lt;/a&gt; proved
invaluable guidance through the process. I also bought from them parts for the
rod system for the footings, and a &amp;#8216;build pack&amp;#8217; that crucially
provided a preliminary materials list.  This note documents the process of the
design and build, but making sure not to reveal any of the details supplied in the
Oakwood Garden Rooms build&amp;nbsp;pack.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/3D.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/3D_600x600.png" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/corner-windows.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/corner-windows_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Groundworks&lt;/h2&gt;
&lt;p&gt;After clearing and levelling the workshop site, holes were dug for each of the
steel rod footings. The setting out of these was carefully determined with
string lines since the base timbers slot directly onto the rods with a
relatively small amount of tolerance, and determining the overall size and
shape of the&amp;nbsp;base.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/levelled.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/levelled_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/setting-out.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/setting-out_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/post-holes.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/post-holes_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/rods.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/rods_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Base&lt;/h2&gt;
&lt;p&gt;The base is constructed with a frame bolted down onto the 24 mm threaded rod
piles and joists supported with hangars bridge between the frame timbers. 100
mm insulation is cut and inserted between the joists, and supported below from
falling by treated batten fastened to the joists. All gaps were filled with
expanding foam. A layer of breathable roofing sheet is laid over the base
before the 22 mm chipboard floor sheets are glued and fastened&amp;nbsp;down.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/base-frame.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/base-frame_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/base-joists.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/base-joists_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/base-insulation.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/base-insulation_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/base-floor.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/base-floor_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Structure&lt;/h1&gt;
&lt;p&gt;The walls are constructed using 50 x 100 mm studwork timbers and covered with 12 mm &lt;span class="caps"&gt;OSB&lt;/span&gt;
sheet. The roof is constructed with 47 x 125 mm timbers, doubled up to span the
wall-to-wall gap, and covered in 18 mm &lt;span class="caps"&gt;OSB&lt;/span&gt; tongue-and-groove roofing&amp;nbsp;sheets.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/back-walls.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-walls_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/all-walls.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/all-walls_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/osb-walls.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/osb-walls_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-osb.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-osb_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Waterproof wrap and&amp;nbsp;batons&lt;/h1&gt;
&lt;p&gt;The walls are covered in a breathable waterproof membrane (standard roofing
sheet) and two perpendicular layers of roofing batten to support the vertical&amp;nbsp;cladding.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/first-battons.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/first-battons_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/membrane-and-battons.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/membrane-and-battons_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Cladding&lt;/h1&gt;
&lt;p&gt;The cladding is made from rough-sawn cedar, sourced from &lt;a href="https://gladstonesawmills.co.uk/"&gt;Gladstone
Sawmills&lt;/a&gt; in South Wales. The vertical
pattern is 150 mm widths separated by a 25 mm gap, fastened to 75 mm widths
sitting&amp;nbsp;behind.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/cladding-mockup.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-mockup_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/cladding-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/cladding-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/cladding-3.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-3_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/vertical-cladding-complete.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/vertical-cladding-complete_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/cladding-complete.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-complete_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Warm roof and&amp;nbsp;rooflights&lt;/h1&gt;
&lt;p&gt;The roof is built up following a warm roof construction. On the bottom deck of
18 mm &lt;span class="caps"&gt;OSB&lt;/span&gt;, a 100 mm perimeter is built around the edge and roof light openings.
A damp-proof membrane is laid in the resulting area, and 100 mm insulation
boards laid on top and packed tightly. The roof is covered with a
&lt;a href="https://www.bauder.co.uk/roof-systems/waterproofing-systems/bituminous-systems/bauder-total-roof-system"&gt;Bauder single-ply roofing system&lt;/a&gt;,
installed by &lt;a href="https://countyflatroofing.co.uk/"&gt;County Flat Roofing&lt;/a&gt;. The roof
lights measure 1,200 x 900 mm external&amp;nbsp;dimensions.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-insulation-perimiter.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-insulation-perimiter_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-insulation-install.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-insulation-install_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-insulation-complete.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-insulation-complete_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-light-upstands.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-light-upstands_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Buildups&lt;/h1&gt;
&lt;p&gt;The following two images show the buildups of the roof and wall. The roof
buildup consists of (starting inside) 125 mm structural timber, 18 mm &lt;span class="caps"&gt;OSB&lt;/span&gt;
bottom deck, 100 mm insulation perimeter, 18 mm &lt;span class="caps"&gt;OSB&lt;/span&gt; top deck, roofing felt,
Bauder membrane, roof light upstand and rooflight. The wall buildup consists of (starting
inside) 100 mm studwork, 12 mm &lt;span class="caps"&gt;OSB&lt;/span&gt;, waterproof membrane, two layers of 25 mm
roofing batten, two layers of 20 mm Cedar board. Both buildups do not show the
15 mm internal plywood panelling that was installed&amp;nbsp;later.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/roof-buildup.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-buildup_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/wall-buildup.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/wall-buildup_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Windows&lt;/h1&gt;
&lt;p&gt;The two windows are 1,040 x 1,040 mm double-glazed aluminium casement, supplied by
&lt;a href="https://www.panoramicwindows.co.uk/"&gt;Panoramic Windows&lt;/a&gt;.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/corner-windows.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/corner-windows_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/window-face-on.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/window-face-on_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Internal fit&amp;nbsp;out&lt;/h1&gt;
&lt;h2&gt;Socket and switch&amp;nbsp;positions&lt;/h2&gt;
&lt;p&gt;Positions of sockets, lights and wiring was marked out using&amp;nbsp;tape.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/socket-positions-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/socket-positions-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/socket-positions-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/socket-positions-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Wall&amp;nbsp;insulation&lt;/h2&gt;
&lt;p&gt;The wall carcassing was filled with 80 mm sheet insulation, into which channels
were created for the wiring. In order to create a moisture barrier, all sheets
were taped together with aluminium foil to create a single air-tight surface.
Special attention was paid to the interaction between the roof and walls, where
otherwise it would have been easy to have areas of missing or shallow&amp;nbsp;insulation.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/insulation-windows.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/insulation-windows_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/insulation-back-corner.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/insulation-back-corner_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Wiring and first-fix&amp;nbsp;electrics&lt;/h2&gt;
&lt;p&gt;Wiring for electrical and data sockets and all the lighting was pulled though
holes in the carcassing. We created two separate socket circuits (right and
left), and a circuit for wall-mounted heaters. The lighting is divided into
three ceiling circuits branched off the switches, plus an outdoor&amp;nbsp;light.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/wiring-channels-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/wiring-channels-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/wiring-channels-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/wiring-channels-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/inside-first-fix.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/inside-first-fix_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/inside-first-fix-and-floor.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/inside-first-fix-and-floor_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Boarding&lt;/h2&gt;
&lt;p&gt;The internal finish is done with 15 mm &lt;span class="caps"&gt;WISA&lt;/span&gt;-Spruce Special boards fixed to the
walls and&amp;nbsp;ceiling.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/back-wall-taped.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-wall-taped_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/back-wall-first-board.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-wall-first-board_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/boarding-complete-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boarding-complete-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/boarding-complete-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boarding-complete-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/ceiling-boarding-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/ceiling-boarding-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/ceiling-boarding-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/ceiling-boarding-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Second-fix&amp;nbsp;electrics&lt;/h2&gt;
&lt;p&gt;With the second-fix electrics completed, the workshop was&amp;nbsp;operational.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/lighting.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/lighting_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;More details of the final details to be added as they are&amp;nbsp;completed&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;a name="drawings" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Drawings&lt;/h2&gt;
&lt;p&gt;The following drawings are taken from the Revit model of the&amp;nbsp;workshop.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/plans.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/plans_1000x1000.png" alt="Plan views."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Plan views.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/elevations.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/elevations_1000x1000.png" alt="Elevation views."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Elevation views.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/garden-workshop/section.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/section_1000x1000.png" alt="Section view showing
buildups of the roof, walls and floor. and intersections between them."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Section view showing
buildups of the roof, walls and floor. and intersections between them.&lt;/figcaption&gt;
&lt;/figure&gt;</content><category term="Physical Projects"/><category term="sheds"/><category term="construction"/></entry><entry><title>Home thermal-imaging survey</title><link href="https://jameswhanlon.com/home-thermal-imaging-survey.html" rel="alternate"/><published>2021-03-31T00:00:00+02:00</published><updated>2021-03-31T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2021-03-31:/home-thermal-imaging-survey.html</id><summary type="html">&lt;p&gt;Investigation of thermal faults using a thermal-imaging&amp;nbsp;camera.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently moved into a &lt;a href="https://nonstandardhouse.com/cornish-unit-type-1-precast-reinforced-concrete-house/"&gt;Cornish Unit Type 1 house&lt;/a&gt;, and
with my involvement with &lt;a href="https://cheeseproject.co.uk"&gt;The &lt;span class="caps"&gt;CHEESE&lt;/span&gt; Project&lt;/a&gt; I was keen to
perform a thermal-imaging survey to better understand how well the building
performs thermally. Also, with the first few months in the house being in
winter and it feeling very cold in places, I had extra motivation to find out
where heat was being lost, and to try and resolve some faults. I have written
this note to record what I found as a case study that others may find useful,
from the point of view of understanding the benefits of using thermal imaging
to assess building performance, and to see the kinds of thermal faults that are
standard among domestic buildings. Included also are some simple remedial
measures that I took to address thermal faults. The emphasis of these were low
cost and low effort to improve the house in the short term, and particularly
during the winter. With plans to renovate and extend in the next couple of
years, the survey would also provide guidance on where more significant
interventions could be&amp;nbsp;targeted.&lt;/p&gt;
&lt;p&gt;I followed the methodology of The &lt;span class="caps"&gt;CHEESE&lt;/span&gt; Project to perform the survey (more
details about &lt;a href="https://cheeseproject.co.uk/home-surveys"&gt;home surveys&lt;/a&gt; and the
&lt;a href="https://cheeseproject.co.uk/pre-survey-guide"&gt;process&lt;/a&gt;). To summarise: the best thermal imaging results
are obtained when there is a good temperature differential (at least 10
degrees) between inside the building and outside. For this reason, winter is
the best period, with the building heated for 24 hours to warm up the fabric
rather than just the air inside it. A blower door fitted to an external door is
used to reduce the internal air pressure and accentuate any draughts. Once the
heating is switched off, the house will start to cool down by thermal
conduction through materials and ingress of cold air through draughts. While
this is happening the thermal camera is used to capture the effects of any
areas of rapid cooling, ie &amp;#8216;thermal&amp;nbsp;faults.&lt;/p&gt;
&lt;h2&gt;External&lt;/h2&gt;
&lt;p&gt;I did the survey in December, and the external temperature was close to 0
degrees. The images below show the back of the house in infra red (thermal) and
visible light. There is little to learn from the thermal picture, and note that
the windows will be reflecting some of the cool night&amp;nbsp;sky.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/external/back-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/external/back-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;There are a few things to remember when inspecting the thermal images. The
thermal image is overlaid on the larger visible-light image, the temperature
value is the measurement taken at the cross hairs, and often each image is
taken with a particular temperature range to give the best contrast to the
subject of the image. The temperature range is given in the top left-hand
corner, and the black and white squares show the degree increments along the
colour scale. In the thermal image above left, the range is centred on 20
degrees plus and minus 23 degrees. All the thermal images in this note use a
colour palette called &amp;#8216;ironbow&amp;#8217;, which I find most intuitive, there are however
other choices such as rainbow and&amp;nbsp;greyscale.&lt;/p&gt;
&lt;h2&gt;Front&amp;nbsp;door&lt;/h2&gt;
&lt;p&gt;The area by the front door was noticeably cold when walking past it. The thermal
images reveal cold single glazed glass sections (at ~15 degrees compared with
~22 degrees ambient temperature of the hallway), and draughts, particularly at
the bottom where the temperature drops to 10&amp;nbsp;degrees.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/front-door/front-door-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/front-door-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/front-door/front-door-bottom-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/front-door-bottom-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;To tackle the leakiness of the front door, I added some acrylic secondary
glazing to the glass sections and blocked up the letter box with glass fibre
insulation and a wooden plug (there is another letter box in the porch). I
admit this was not an elegant solution, but it was quick and cheap. The look of
acrylic could have been improved by using magnetic strip for attaching it, also
allowing for it to be removed. But since the door will be replaced in the next
18 months, I was not too&amp;nbsp;worried.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/front-door/secondary-glazing-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/secondary-glazing-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/front-door/letter-box-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/letter-box-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Windows&lt;/h2&gt;
&lt;p&gt;The house has uPVC double glazing throughout (installed within the last 10
years), but a main finding of the survey was the windows had some significant
thermal&amp;nbsp;faults.&lt;/p&gt;
&lt;h3&gt;Leaking&amp;nbsp;trim&lt;/h3&gt;
&lt;p&gt;The most obvious fault was draughts around the edges of the frames, from behind a
plastic trim. In the left-hand images, the cold area is a draught emerging from
a section of silicon sealant that had&amp;nbsp;detached.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/leaking-trim-1-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/leaking-trim-1-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/leaking-trim-1-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/leaking-trim-1-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/leaking-trim-2-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/leaking-trim-2-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/leaking-trim-2-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/leaking-trim-2-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;When I removed the trim to investigate, I found the frames had not been sealed
to the wall in any way (left), so there was a gap all around where air could
penetrate. On several windows, daylight was visible without the trim. Mostly
the plastic trims were doing a good job preventing draughts, but they were not
providing much insulation against air circulating behind them. I fixed the
issue by using expanding foam to fill the gaps, and used filler to address any
smaller gaps and make it flush with the window&amp;nbsp;reveals.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/removed-trim-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/removed-trim-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/filled-gap-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/filled-gap-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Leaking&amp;nbsp;sill&lt;/h3&gt;
&lt;p&gt;Related to the lack of sealing of the window frames to the wall was draughts
emerging from under the window sill. In the thermal picture below this is
particularly visible being above a warm radiator. With the blower door running,
it is also easy to feel these with the back of a&amp;nbsp;finger.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/sill-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/sill-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/sill-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/sill-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Leaking&amp;nbsp;seals&lt;/h3&gt;
&lt;p&gt;Two opening panes had leaks along part of their seals, where the window did not
shut tight to the frame to make it airtight. This was not a significant source
of a draught, but a problem that is commonly found with uPVC windows. Often the
hinges can be adjusted to remedy this issue, or foam insulation tape could be&amp;nbsp;added.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/seal-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/seal-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/dining-room-window-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/dining-room-window-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Missing&amp;nbsp;insulation&lt;/h3&gt;
&lt;p&gt;An interesting aspect of the house is that the upper floor has a &lt;a href="https://en.wikipedia.org/wiki/Mansard_roof"&gt;Mansard
roof&lt;/a&gt; and is timber construction. The first-floor walls have had
insulation inserted behind the tiles, but the thermal picture below shows
clearly no insulation has been added above the window. This is the case for all
the upstairs&amp;nbsp;windows.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/top-insulation-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/top-insulation-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/windows/top-insulation-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/top-insulation-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;First floor&amp;nbsp;walls&lt;/h2&gt;
&lt;p&gt;The images below of the first-floor walls show clearly the timber sub structure
of the roof and the voids between where insulation has been added. Below the
window in the top-left image, there is evidence of air ingress from around the
frame into the wall. In the bottom-right image, there is evidence of air
ingress from the loft space into the wall, due to missing or lacking insulation
at that intersection. In the same picture, you can see a rectangle of missing
insulation in the corner. In the bottom-left image, you can see warm walls,
the cold window frames and the missing insulation at the&amp;nbsp;top.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/upper-walls/below-window-landing-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/below-window-landing-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/upper-walls/bedroom-2-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bedroom-2-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/upper-walls/bedroom-1-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bedroom-1-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/upper-walls/bedroom-3-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bedroom-3-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;By coincidence, a near by Cornish Unit Type 1 house was undergoing some extension
work, and has its upper timbers exposed. The picture below shows clearly the
construction, and notably the wall voids contained no&amp;nbsp;insulation.&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/upper-walls/upper-wall-construction.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/upper-wall-construction_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;Ground&amp;nbsp;wall&lt;/h2&gt;
&lt;p&gt;The Mansard roof construction means that the interface between the roof and
masonry walls is at the top of the ground floor walls (rather than more
conventionally at the top of the upper floor walls). The images below show
ingress of cold air from the eaves and into the surrounding wall, stairs and
floor. Note also the shape of the block work in the ground floor&amp;nbsp;wall.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/ground-wall/blockwork-stairs-1-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/blockwork-stairs-1-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/ground-wall/blockwork-stairs-2-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/blockwork-stairs-2-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/ground-wall/floorboard-leak-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorboard-leak-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/ground-wall/floorboard-leak-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floorboard-leak-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Air&amp;nbsp;brick&lt;/h2&gt;
&lt;p&gt;The building has one air brick that vents into the wall cavity. This is
particularly visible inside, as a cascade of cold air down the wall. Presumably
the ventilation is necessary to prevent moisture buildup in the&amp;nbsp;cavity.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/air-brick/air-brick-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/air-brick-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/air-brick/air-brick-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/air-brick-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Loft&amp;nbsp;hatch&lt;/h2&gt;
&lt;p&gt;One of the first jobs after moving in was to install a loft ladder for better
access to the loft space for storage. The job still requires some finishing
touches, but the thermal image shows there is only one main area that requires
some additional sealing. Otherwise, I packed more insulation around the frame
to resolve the more minor cold&amp;nbsp;patches.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-hatch/hatch-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hatch-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-hatch/hatch-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/hatch-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Loft&amp;nbsp;insulation&lt;/h2&gt;
&lt;p&gt;Due to my work boarding out the loft, there was another piece of missing
insulation in the corner (here in the bathroom). These images clearly show the
value of loft insulation, and it extending to the&amp;nbsp;edges.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-insulation/missing-bathroom-1-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/missing-bathroom-1-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-insulation/missing-bathroom-2-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/missing-bathroom-2-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Installing boarding in the loft for storage was a good opportunity to
redistribute and top up insulation, and make sure it extended into corners
(whilst maintaining space for airflow from the roof). In the right-hand
picture, the black columns are stilts that boarding is attached&amp;nbsp;to.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-insulation/loft-insulation-bare.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/loft-insulation-bare_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/loft-insulation/loft-insulation-stilts.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/loft-insulation-stilts_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Kitchen&lt;/h2&gt;
&lt;p&gt;Another particularly cold spot in the house was in a corner of the kitchen, and
inside the corner cupboard. This was due to a soil pipe running up through the
house to avoid the angle of the Mansard roof, and the boxing carrying it up
through the kitchen channelling cold air from the outside. As you can see, the
internal temperature of the cupboard was about 10 degrees lower than the
ambient room temperature, similar to the front door. I tackled this issue by
sealing as much as possible around the boxing and stuffing fibre insulation in
all of the remaining gaps. This made a big difference, but a complete fix would
require taking the cabinets out and redoing the&amp;nbsp;boxing.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/kitchen/cold-cupboard-1-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cold-cupboard-1-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/kitchen/cold-cupboard-2-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cold-cupboard-2-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Bathroom&lt;/h2&gt;
&lt;p&gt;The thermal images in the bathroom did not reveal any significant draughts, but
they do show cold air circulating behind the walls. This was confirmed when the
bathroom was reorganised, revealing a void behind the sink with plenty of
daylight visible through the eaves. Note also in the image of the toilet, the
cold water sitting in the&amp;nbsp;cistern.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/bathroom/bathroom-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bathroom-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/bathroom/sink-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/sink-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/bathroom/toilet-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/toilet-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/bathroom/toilet-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/toilet-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Central&amp;nbsp;heating&lt;/h2&gt;
&lt;p&gt;It was interesting for the thermal images to reveal the workings of the
central heating system. The condensing boiler and its pipework is clearly
visible in the top two images. The hot water tank is middle-left, a radiator
middle-right and otherwise hidden pipework in the bottom two&amp;nbsp;images.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/boiler-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boiler-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/boiler-visible.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boiler-visible_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/water-tank-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/water-tank-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/radiator-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/radiator-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/pipe-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/pipe-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/central-heating/pipe-ceiling-thermal.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/pipe-ceiling-thermal_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Kit&lt;/h2&gt;
&lt;p&gt;The left-hand image show the the &lt;span class="caps"&gt;CHEESE&lt;/span&gt; blower door installed on the side door,
which precludes that door from being inspected, but it was less of a worry than
the front door. The right-hand image shows the &lt;span class="caps"&gt;CHEESE&lt;/span&gt; camera kit, with the
iPhone and Flir camera&amp;nbsp;attachment.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/kit/blower-door.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/blower-door_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/thermal-survey/kit/cheese-camera-kit.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cheese-camera-kit_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;</content><category term="Home and Sustainability"/><category term="energy-efficiency"/><category term="retrofit"/><category term="sustainability"/></entry><entry><title>Reflections on the state of nature</title><link href="https://jameswhanlon.com/reflections-on-the-state-of-nature.html" rel="alternate"/><published>2020-12-04T00:00:00+01:00</published><updated>2020-12-04T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2020-12-04:/reflections-on-the-state-of-nature.html</id><summary type="html">&lt;p&gt;A review of human impacts on nature as a way to reflect and navigate
environmental bad&amp;nbsp;news.&lt;/p&gt;</summary><content type="html">&lt;p&gt;For a long time I have been deeply worried about the looming threat of climate
change and its broad consequences. But greenhouse gas emissions from human
activities are just one part of a complex picture in which we (human beings)
are damaging our environment so severely that the future of our life on Earth
uncertain, and this uncertainty is within the timescale of our children&amp;#8217;s
lifetimes. Indeed, there is some degree of consensus that we are heading for
some form of &lt;a href="https://jembendell.com/2019/05/15/deep-adaptation-versions/"&gt;societal collapse&lt;/a&gt;. In this note, I wanted to try
and articulate the complex picture of human impacts on nature as a way to
reflect on the situation in which we find ourselves in, and provide something to
navigate the stream of environmental bad news that we receive. The information
in this note is drawn primarily from recent significant reports that focus on
global impacts, linked at the&amp;nbsp;end.&lt;/p&gt;
&lt;h2&gt;Nature&amp;#8217;s biodiversity and ecosystem&amp;nbsp;services&lt;/h2&gt;
&lt;!-- Species / biodiversity loss
- Since 1970, 81% of inland wetland species populations and 36% of coastal and marine species have declined.
- pollinators: &gt;75% global food crop types rely on animal pollination
- TODO: level of insect extinction?
--&gt;

&lt;p&gt;Nature is the rich variety of life and environments found on Earth, but because
of human impacts it is in&amp;nbsp;decline.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;The &lt;a href="https://ipbes.net/global-assessment"&gt;2019 &lt;span class="caps"&gt;UN&lt;/span&gt; Global Assessment Report on Biodiversity and Ecosystem
Services&lt;/a&gt; is the work of an intergovernmental body and represents the
&lt;a href="https://www.un.org/sustainabledevelopment/blog/2019/05/nature-decline-unprecedented-report/"&gt;most comprehensive assessment&lt;/a&gt; of life on earth ever completed.
The report finds that human activities have caused huge declines in
terrestrial, freshwater and marine environments. Across an estimated eight
million known animal and plant species, approximately one million are currently
threatened with extinction. This rate of extinction is estimated to be 10 to
100 times higher than any of the previous known five mass extinction events in
the history of Earth, thus it has been named the &lt;a href="https://en.wikipedia.org/wiki/Holocene_extinction"&gt;Holocene
extinction&lt;/a&gt;, characterising the current geological&amp;nbsp;epoch.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://livingplanet.panda.org/en-us/"&gt;&lt;span class="caps"&gt;WWF&lt;/span&gt; Living Planet Report 2020&lt;/a&gt; provides a similarly
stark assessment of the state of the world&amp;#8217;s ecosystems and lifeforms: between
1970 to 2016 there was been an average decline of 68% in populations of
mammals, birds, amphibians, reptiles and fish according to the &amp;#8216;Living Planet
Index&amp;#8217;, which aggregates data from 20,811 populations representing 4,392 species
globally and does not include insects. Rates of decline vary significantly by
region, with the highest average declines in tropical regions (94% of
vertebrate populations in Latin America and the&amp;nbsp;Caribbean).&lt;/p&gt;
&lt;p&gt;A &lt;a href="https://www.pnas.org/content/115/25/6506"&gt;2018 study&lt;/a&gt; &lt;a href="https://www.theguardian.com/environment/2018/may/21/human-race-just-001-of-all-life-but-has-destroyed-over-80-of-wild-mammals-study"&gt;found&lt;/a&gt; that
of all mammals on Earth, 96% are livestock, 36% are humans and only 4% are wild
animals. Of birds, 70% are poultry and 30% are wild. These proportions
correspond to intensification of animal agriculture with losses of 83% of wild
terrestrial mammals, 80% of marine mammals, 50% of plants and 15% of&amp;nbsp;fish.&lt;/p&gt;
&lt;p&gt;The issues of biodiversity and ecosystems are central to the functioning of our
planet and to our health and wellbeing. Biodiversity relates to the variety of
genes, species and functional traits in an &lt;a href="https://en.wikipedia.org/wiki/Ecosystem"&gt;ecosystem&lt;/a&gt;, which is
defined as a community of living things in an environment, all interacting as a
system. It is recognised that biodiversity affects the functioning of
ecosystems, the flows of energy, materials, minerals, and water. At a &lt;a href="http://uknea.unep-wcmc.org/EcosystemAssessmentConcepts/EcosystemFunctioning/tabid/100/Default.aspx"&gt;high
level&lt;/a&gt;, all ecosystems are powered by the sun&amp;#8217;s energy
that is captured by photosynthesis, and this energy is transferred upwards
through the food web. The movement of nutrients occurs as living organisms
exchange them though their interactions with the physical&amp;nbsp;environment.&lt;/p&gt;
&lt;p&gt;Humans too are part of an ecosystem, depending on plants and organisms to
capture the sun&amp;#8217;s energy and convert it into edible products. However, human
activities such as agriculture and forestry management can be seen as ways of
manipulating our ecosystems to increase the output of particular provisions.
Unfortunately, such interventions have effects that are detrimental to other
aspects of ecosystem&amp;nbsp;functioning.&lt;/p&gt;
&lt;p&gt;Apart from the wonder and beauty of the natural world and a sense that it
should be respected and preserved, biodiversity can be viewed through a more
functional lens as &lt;a href="https://pub.epsilon.slu.se/10240/7/wardle_d_etal_130415.pdf"&gt;providing services&lt;/a&gt; for the
benefit of humans, and indeed our survival. These ecosystem services can be
&lt;a href="http://www.fao.org/ecosystem-services-biodiversity/en/"&gt;broken down into four groups&lt;/a&gt;: provisioning, regulating,
support and cultural, summarised in the following table. According to the
Global Assessment Report, the trend of 16 of these 19 categories is that
decline over the last 50 years. Only energy, food, and raw materials have seen
increases in the level of provisioning to humans. However, these service
benefits directly impact other services due to dramatic changes in land use and
associated air, water and soil&amp;nbsp;pollution.&lt;/p&gt;
&lt;table&gt;
  &lt;caption&gt;
  Summary of nature&amp;#8217;s ecosystem services it provides to humans
  &lt;/caption&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th class="w-25"&gt;Group&lt;/th&gt;
      &lt;th&gt;Service&lt;/th&gt;
      &lt;th&gt;Historical 50-year trend&lt;/th&gt;
      &lt;th&gt;Details/examples&lt;/th&gt;
    &lt;tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td rowspan="6"&gt;&lt;strong&gt;Provisioning services&lt;/strong&gt; that support the production of renewable resources.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Food and feed&lt;/td&gt;
      &lt;td class="text-success"&gt;Increase&lt;/td&gt;
      &lt;td&gt;Such as crops and fisheries, feeding humans directly and indirectly with livestock.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Energy&lt;/td&gt;
      &lt;td class="text-success"&gt;Increase&lt;/td&gt;
      &lt;td&gt;Such as biofuels.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Raw materials&lt;/td&gt;
      &lt;td class="text-success"&gt;Increase&lt;/td&gt;
      &lt;td&gt;Such as wood for construction and natural fibres for clothing.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Freshwater&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Water is essential for human life and for the cultivation of crops.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Medicinal, biochemical and genetic resources&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;For example, new antibiotics are discovered in nature, rather than being created artifically.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;!-- --&gt;
    &lt;tr&gt;&lt;td rowspan="9"&gt;&lt;strong&gt;Regulating services&lt;/strong&gt; that lessen environmental change.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regulation of climate&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline*&lt;/td&gt;
      &lt;td&gt;By sequestration of carbon dioxide to reduce the effects of global warming.
          *The capacity of the oceans to do this has remained constant in this period.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regulation of local climate and air quality&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Examples including shade from trees, forests influencing rainfall and plants regulating air quality by removing pollutants.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Moderation of extreme events and natural disasters&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Such as floods, storms, tsunamis, landslides and droughts.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regulation of freshwater and coastal water quality&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Such as treatment of waste water to eliminate harmful pathogens.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regulation of freshwater flow&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Which affects the quantity, location and timing of freshwater.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Regulation of soil fertility and prevention of soil erosion.&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Fertility refers to the ability of soil to sustain plant growth, and erosion is the displacement of soil, most immediately impacting crop production.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Biological control of disease and pests&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Such as by the control of the population of a species that acts as a vector for a disease by another, perhaps predatory, species.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pollination of plants&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;To enable reproduction of many plants.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;!-- --&gt;
    &lt;tr&gt;&lt;td rowspan="3"&gt;&lt;strong&gt;Supporting services&lt;/strong&gt; that provide a basis for all ecosystems and their biodiversity with habitats and genetic diversity.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Soil formation&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;To provide a habitat for many types of plant.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Nutrient cycling&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;To provide the necessary mineral nutrients, including water, to organisms.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;!-- --&gt;
    &lt;tr&gt;&lt;td rowspan="5"&gt;&lt;strong&gt;Cultural services&lt;/strong&gt; are non-material human benefits.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Recreation and mental and physical health in natural spaces&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Such as walking, running or sports in a park.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tourism though the enjoyment of nature&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Benefiting those experiencing nature, as well as providing income for those facilitating it.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Aesthetic appreciation and inspiration for culture, art and design&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Much of culture, art and design draws on the natural world.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Spiritual experience and sense of place&lt;/td&gt;
      &lt;td class="text-danger"&gt;Decline&lt;/td&gt;
      &lt;td&gt;Nature is a common element of most religions.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;!-- Summary of drivers and impacts of declining nature --&gt;

&lt;!-- Increasing consumption --&gt;

&lt;p&gt;Since 1970, the global population has more than doubled (3.7 billion to 7.6
billion), global trade has increased ten fold and average &lt;span class="caps"&gt;GDP&lt;/span&gt; has increased
four fold. It is estimated there has been a 15% per-capita increase in
consumption globally and this is compounded by increasing levels of
long-distance goods transportation. Increased consumption, along with
technological development, has driven increased production of food, materials
and fuels, and has driven urbanisation, which is reflected in global&amp;nbsp;statistics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crop production has increased 300% since&amp;nbsp;1970.&lt;/li&gt;
&lt;li&gt;Timber production has increased by 50% since&amp;nbsp;1970.&lt;/li&gt;
&lt;li&gt;Extraction of resources has almost doubled since&amp;nbsp;1980.&lt;/li&gt;
&lt;li&gt;Urban areas have more than doubled since&amp;nbsp;1992.&lt;/li&gt;
&lt;/ul&gt;
&lt;!--
Drivers:
 Land use change (agriculture, degradation)
 Direct exploitation
 Climate change
 pollution
 invasive species
--&gt;

&lt;p&gt;Consequently, the primary driver of biodiversity loss in terrestrial and
freshwater ecosystems is &lt;strong&gt;land-use change&lt;/strong&gt;, closely followed by &lt;strong&gt;direct
exploitation&lt;/strong&gt; through harvesting, logging and hunting. In marine ecosystems,
direct exploitation through fishing is the primary driver, followed by
land-/sea-use change. Together these issues account for more than 50% of the
global impact on nature, but approximately 30% is this is attributable to three
other significant factors: &lt;strong&gt;climate change&lt;/strong&gt;, &lt;strong&gt;pollution&lt;/strong&gt; and &lt;strong&gt;invasive
alien species&lt;/strong&gt;.&lt;/p&gt;
&lt;!-- UN summary --&gt;
&lt;p&gt;The &lt;span class="caps"&gt;UN&lt;/span&gt; Global Assessment Report summarises human impact thus: 75% of the
earth&amp;#8217;s land surface is now significantly altered, 66% of the oceans are
significantly altered, and global indicators of the condition of biodiversity
and ecosystems indicate a 47% decrease from before human impacts, with a
continuing decline of approximately 4% per&amp;nbsp;decade.&lt;/p&gt;
&lt;p&gt;A &lt;a href="https://www.swissre.com/media/news-releases/nr-20200923-biodiversity-and-ecosystems-services.html"&gt;recent report by the Swiss Re global insurance company&lt;/a&gt;
concludes that 20% of the world&amp;#8217;s countries are at risk of their ecosystems
collapsing due to a decline in biodiversity and consequent ecosystem services
decline. (Ecosystem &lt;a href="https://en.wikipedia.org/wiki/Ecosystem_collapse"&gt;collapse&lt;/a&gt; is when processes and
features supporting life are reduced or disappear, typically leading to a
drastic reduction in the number of organisms living in an environment, and
often mass extinction.) Swiss Re frame this decline as a critical issue because
they estimate 55% of global &lt;span class="caps"&gt;GDP&lt;/span&gt; depends on high-functioning biodiversity and
ecosystem services. The graphic below summarises the global distribution of the
problem with an index developed by Swiss Re to compare biodiversity and
ecosystem services by aggregating data across indicators. Included &lt;a href="https://www.swissre.com/institute/research/topics-and-risk-dialogues/climate-and-natural-catastrophe-risk/expertise-publication-biodiversity-and-ecosystems-services.html"&gt;in the
index&lt;/a&gt; are habitat intactness, pollination, air quality and
local climate, water security, soil fertility, erosion control, coastal
protection, food provision and timber&amp;nbsp;provision.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/Swiss-Re-biodiversity-ecosystems-services.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/Swiss-Re-biodiversity-ecosystems-services_w=650.jpg" alt="Swiss Re Institute global biodiversity index."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Swiss Re Institute global biodiversity index.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2&gt;Terrestrial and freshwater&amp;nbsp;ecosystems&lt;/h2&gt;
&lt;div class="float-right" width="400px"&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/glo-land-use.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/glo-land-use_w=400.png" alt="Transformation of land use over the last 8,000 years, from UN Global Land Outlook 2017."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Transformation of land use over the last 8,000 years, from &lt;span class="caps"&gt;UN&lt;/span&gt; Global Land Outlook 2017.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;/div&gt;

&lt;!-- Agriculture --&gt;

&lt;p&gt;Growth in consumption has driven land-use change and now 33% of the Earth&amp;#8217;s
land surface is dedicated to crop and animal agriculture. Such is the scale of
this production, that it is responsible for 25% of greenhouse emissions (18%
for animals and 7% for plants), and it consumes 75% of global freshwater
resources. Destruction of habitats is a primary driver for  biodiversity loss
and the expansion of agriculture has mainly replaced tropical forests, wetlands
and grasslands, which are home to the highest levels of biodiversity, as well
as providing huge carbon sinks, protecting against extreme weather events and
are difficult or impossible to&amp;nbsp;replace.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;Compared with pre-industrial times, it is estimated that 30% of global habitats
have lost the ability to support long-term survival for the species they&amp;nbsp;accommodate.&lt;/p&gt;
&lt;!-- Forests --&gt;

&lt;p&gt;&lt;strong&gt;Forests&lt;/strong&gt; cover 31% of the Earth&amp;#8217;s land area and harbour most of terrestrial
biodiversity, but are distributed unequally.
Tropical and subtropical forest accounts for 42% of global cover, of the
remaining cover, 24% is in boreal regions and 22% in temperate regions (see the
&lt;a href="http://www.fao.org/3/ca8985en/CA8985EN.pdf"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; The State of the World&amp;#8217;s Forests report&lt;/a&gt; graphic&amp;nbsp;below).&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;Globally, &lt;a href="https://www.nature.com/articles/nature14967"&gt;it is estimated&lt;/a&gt; that there has been a 46%
reduction in the number of trees prior to human impacts, and approximately 10
billion trees are now felled annually. This deforestation is driven primarily
by agriculture, with secondary factors accounting for &amp;lt;20% of total
deforestation being urban, infrastructure and mining&amp;nbsp;expansion.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;In Latin America for example, 100 million hectares (or 1 million square km, or
four times the land area of the &lt;span class="caps"&gt;UK&lt;/span&gt;) of tropical forest were lost in the period
1980 to 2000, mainly to cattle and palm oil plantations, and this ecosystem
destruction continues today, pushing areas of the Amazon to a tipping point
where &lt;a href="https://www.theguardian.com/environment/2020/oct/05/amazon-near-tipping-point-of-switching-from-rainforest-to-savannah-study"&gt;rainforest is converted to open savannah&lt;/a&gt;. There is
also a &lt;a href="https://www.theguardian.com/environment/2020/aug/30/rampant-destruction-of-forests-will-unleash-more-pandemics"&gt;strong link&lt;/a&gt; between deforestation and the
emergence of dangerous novel&amp;nbsp;viruses.&lt;/p&gt;
&lt;p&gt;Of the remaining forests, 66% have been &lt;a href="http://www.fao.org/3/ca8985en/CA8985EN.pdf"&gt;subject to human impacts&lt;/a&gt;
causing significant changes to their ecological processes and ability to
naturally regenerate. Forests are being degraded primarily by logging for raw
material and fuel, with secondary factors accounting for &amp;lt;20% of total
degradation being forest fires and&amp;nbsp;livestock.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;Due to the expansion of new forest area, the net rate of forest loss has
decreased by 50% since 1990 (an estimated 16 million hectares per year,
compared with 10 million between 2015 to 2020), which is encouraging but still
falls short of increasing forest cover in the near term to mitigate climate
change and to preserve biodiversity. Replacement of old growth forests is not
one-for-one: the ability of trees to absorb carbon dioxide &lt;a href="https://www.sciencedaily.com/releases/2008/09/080910133934.htm"&gt;improves with
age&lt;/a&gt; and establishment of new forests also takes&amp;nbsp;decades.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/fao-global-tree-cover-ecological-zone.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/fao-global-tree-cover-ecological-zone_w=500.png" alt="Forests by ecological zone."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Forests by ecological zone.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/fao-deforestation-drivers.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/fao-deforestation-drivers_w=500.png" alt="Drivers of deforestation and degradation."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Drivers of deforestation and degradation.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;From the &lt;span class="caps"&gt;UN&lt;/span&gt; The State of the World&amp;#8217;s Forests report 2020&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;!-- Wetlands --&gt;

&lt;p&gt;&lt;strong&gt;Wetlands&lt;/strong&gt; are inland areas of water such as lakes, rivers, floodplains,
swamps, marshes, peatlands, mangroves and coral reefs, and include artificial
areas such as reservoirs and rice paddies. Wetlands provide additional
important ecosystem services: water purification and a source of food. More
than 85% have been lost between 1700 (pre-industrial times) to 2000, and this
has accelerated: the rate of destruction has been approximately three times
faster than that of forests with 30% lost between 1970 and 2008. This
destruction is driven primarily by land-use change due to agriculture, but also
climate change, direct extraction and pollution. Globally, there are &lt;a href="https://www.ramsar.org/sites/default/files/documents/library/info2007-01-e.pdf"&gt;now
approximately&lt;/a&gt; 5.7 million square kilometres of wetlands, or 6%
of global land area. Creation of artificial wetlands has also accelerated,
accounting for 12% of the total area, with &lt;a href="https://academic.oup.com/bioscience/article/65/4/346/255153"&gt;mixed impacts&lt;/a&gt;
on&amp;nbsp;wildlife.&lt;/p&gt;
&lt;!-- Land degradation, soils --&gt;

&lt;p&gt;Once land has been converted to agricultural purposes from pristine habitats,
it is further subject to &lt;strong&gt;degradation&lt;/strong&gt;, primarily from intensive practices
that do not allow soil to naturally regenerate between harvests and abundantly
use chemicals for fertilisation and pest control. Secondary drivers are
urbanisation, development of infrastructure, production of energy and mining.
The &lt;span class="caps"&gt;UN&lt;/span&gt;&amp;#8217;s &lt;a href="https://knowledge.unccd.int/glo/GLO_first_edition"&gt;Global Land Outlook report&lt;/a&gt; states that over the
last 20 years, approximately 20% of land supporting the growth of plants shows
persistent declining trends in productivity (16% of forests, 19% of grasslands
and 27% of rangeland). The impacts vary significantly by region, with Africa
and Europe having some of the highest levels of land degradation, with effects
of future food production insecurity, water insecurity and reduced protection
against extreme weather&amp;nbsp;events.&lt;/p&gt;
&lt;!-- Pollution --&gt;

&lt;p&gt;Although land-use change and direct exploitation are dominant factors in the
decline of terrestrial nature, the combined &lt;strong&gt;pollution&lt;/strong&gt; of harmful
substances and introduction of invasive alien species account for more than 20%
of the declines in&amp;nbsp;nature.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;Anthropogenic pollution that negatively impacts nature takes numerous forms:
chemicals released into the air (including greenhouse gasses causing global
warming), contamination of soil and water with chemicals including
hydrocarbons, heavy metals, fertilisers and pesticides, as well as raw sewage.
Every year into the world&amp;#8217;s waters, more than 80% of global untreated
wastewater and 300-400 million tons of industrial waste is&amp;nbsp;discharged.&lt;/p&gt;
&lt;!----&gt;
&lt;p&gt;The introduction of invasive terrestrial species have risen approximately 70%
since 1970, due mainly to the growth of long-distance transport of goods and
people, but increasingly from changing climates enabling habitation in new
areas. Alien species can have significant direct effects on new ecosystems because
of a lack of natural predators, because they carry diseases and because they
outcompete native wildlife or prey on them. They can case indirect detrimental effects
through impacting the ecosystem by, for example, changing soil chemistry or the
intensity of wildfires. Alien species are a particular problem in marine
ecosystems and are discussed in the next&amp;nbsp;section.&lt;/p&gt;
&lt;p&gt;Climate change, which is discussed in the final section, has a relatively
smaller impact, but one that is increasing rapidly, and simultaneously
exacerbating other&amp;nbsp;drivers.&lt;/p&gt;
&lt;h2&gt;The oceans and marine&amp;nbsp;ecosystems&lt;/h2&gt;
&lt;p&gt;The oceans cover approximately 70% of the earth&amp;#8217;s surface, account for 90% of
the earth&amp;#8217;s ecosystems and hold 97% of the earth&amp;#8217;s water. In marine ecosystems
the primary driver of biodiversity loss is fishing, closely followed by sea and
coastal land-use change. Only 3% of the ocean is now considered to be free from
human&amp;nbsp;impacts.&lt;/p&gt;
&lt;!-- Carbon sequestration and acidification --&gt;

&lt;p&gt;The vastness of the oceans have provided a significant buffer against the
effects global warming by absorbing huge quantities of &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; and heat.
Between 2009-2018, the oceans absorbed 23% of global &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; emissions,
however absorption of &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; comes at the cost of &lt;strong&gt;acidification&lt;/strong&gt;,
meaning a decrease in the pH level. Since the 1980s, pH has been decreasing by
0.017-0.027 pH units per decade. Acidification is known to reduce the ability
of marine organisms to form hard parts such as shells and skeletons, affecting
their ability to grow and reproduce, but the exact effects on different species
and their ecosystems is not yet well understood. This situation is not easy to
remedy: if &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; emissions were to stop today, we would see a lag of
one or more decades where acidification would continue and it is expected that
it would take tens to hundreds of thousands of years for the oceans to return
to a normal pH level. As a point of comparison, the largest extinction event of
marine life &lt;a href="https://en.wikipedia.org/wiki/Paleocene%E2%80%93Eocene_Thermal_Maximum"&gt;occurred approximately 55 million years ago&lt;/a&gt; when global
temperatures increased by 5-8 C with a rate of carbon emissions 16 times less
than we have now, and over a course of 30,000&amp;nbsp;years.&lt;/p&gt;
&lt;!-- Heat sink --&gt;

&lt;p&gt;The oceans are also estimated to have absorbed &lt;a href="http://www.climatechange2013.org/images/report/WG1AR5_SPM_FINAL.pdf"&gt;90% of the energy accumulation
from global warming between 1971 and 2010&lt;/a&gt;, which equates to a
0.11 C rise in the upper 75 m of water from 0.09-0.13 C. The effects of &lt;strong&gt;ocean
heating&lt;/strong&gt; are thermal expansion causing sea level rise (accounting for ~30% of
the observed rise), increased melting of sea ice, increased &lt;strong&gt;stratification&lt;/strong&gt;,
reduced sequestering of atmospheric &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; and altering of ocean
currents and storm tracks. In 2019, the global average sea temperature reached
the highest recorded value, and more than &lt;a href="https://www.aljazeera.com/news/2020/03/state-oceans-200310152317671.html"&gt;84% of the ocean&lt;/a&gt;
experienced at least one abnormally high temperature&amp;nbsp;event.&lt;/p&gt;
&lt;!-- Stratification --&gt;

&lt;p&gt;Stratification occurs when the sea&amp;#8217;s surface warms but the water underneath
does not, or because runoff from ice melt leads to a layer of less-salty water.
Such a differential prevents &lt;strong&gt;nutrient-rich water&lt;/strong&gt; from upwelling and mixing
with the warmer, lighter water that supports more biodiversity, depriving
marine life such as corals and algae, from&amp;nbsp;food.&lt;/p&gt;
&lt;!-- Deoxygenation --&gt;

&lt;p&gt;Ocean heating also causes the upper layer to be &lt;strong&gt;deoxygenated&lt;/strong&gt; because oxygen
is less soluble as water warms, making it harder for marine organisms that
depend on oxygen to survive. Water with oxygen saturation between 1-30% is
called &lt;a href="https://en.wikipedia.org/wiki/Hypoxia_(environmental)"&gt;&lt;strong&gt;hypoxic&lt;/strong&gt;&lt;/a&gt; which leads to the death of fish and
invertebrates such as worms and clams. Water with oxygen below 1% is called
anoxic. In 2008, it was estimated that there were 400 hypoxic or anoxic &amp;#8216;dead
zones&amp;#8217;, totalling 245,000 km$2$. Compounding these issues are feedback effects:
warming water increases the metabolic rate of marine organisms that produce
oxygen causing them to respire more and generate less oxygen; additionally, the
lack of nutrients due to stratification inhibits photosynthesis by organisms
such as &lt;a href="https://en.wikipedia.org/wiki/Phytoplankton"&gt;phytoplankton&lt;/a&gt; (microscopic organisms that create
organic compounds including oxygen from dissolved &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;).&lt;/p&gt;
&lt;!-- Oxygenated waters --&gt;

&lt;p&gt;Because the oceans are so vast, it might not seem that deoxygenation and
hypoxic areas pose a significant threat to marine ecosystems, but the area in
which oxygen-rich waters occur is bounded by a naturally-occurring
&lt;strong&gt;oxygen-minimum zone&lt;/strong&gt; located beyond the continental shelves. The result is a
narrow region of water on the coast of the continents, with only the upper
part of the water column suitable for supporting most marine life. As hypoxic
and anoxic regions grow, the part of the ocean supporting most marine life is
shrinking, and the combination of deoxygenation and decreased nutrient supply is
destabilising the base of complex food webs and&amp;nbsp;ecosystems.&lt;/p&gt;
&lt;p&gt;As if the effects of climate change on marine ecosystems were not bad enough,
they are under attack from other issues including overfishing, eutrophication
and pollution, and foreign&amp;nbsp;species.&lt;/p&gt;
&lt;!-- Fishing --&gt;

&lt;p&gt;&lt;strong&gt;Fishing&lt;/strong&gt; &lt;a href="https://www.fishforward.eu/en/topics/facts-figures/"&gt;accounts&lt;/a&gt; for the extraction of
approximately 110 million tonnes of fish and invertebrates every year, having
increased from 28 million tonnes in 1950, and is the primary driver of
biodiversity loss in oceans. Peak catches were in 1996 at 130 million tonnes,
and have been declining at 1.2 million tonnes annually since then. Of these
quantities, approximately 35% is bycatch and discarded and 12-18% is illegal
and unregulated. More than 55% of ocean area is now subject to industrial
fishing. Destructive and poorly-regulated practices like &lt;a href="bottom-trawling"&gt;bottom
trawling&lt;/a&gt; further cause almost irreparable habitat destruction
for reefs, sponges and shellfish. These factors have led to a situation
where 33% of fish stocks are caught at unsustainable levels, 60% are maximally
sustainably fished and only 7% are underfished. Global populations of sharks and
rays have &lt;a href="https://www.ecowatch.com/shark-population-overfishing-2650168793.html"&gt;declined by 71% since 1970&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/Global-Fishing-Watch-Fishing-activity.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/Global-Fishing-Watch-Fishing-activity_w=600.png" alt="Global fishing activity 2016 (Global Fishing Watch)"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Global fishing activity 2016 (Global Fishing Watch)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Eutrophication&lt;/strong&gt; is a particular kind of pollution where excess nutrients
  are deposited in water, typically by land runoff or direct discharge of
nitrogen and phosphorus from fertilisers used in agriculture, in industry or
from sewage. The effect is that water becomes stratified into a layer where
phytoplankton and other algaes rapidly multiply to create huge blooms. These
blooms lower the oxygen levels in the water, can produce toxins and reduce the
sunlight entering the water. Blooms can last days to months, and when they die
their decomposition further deoxygenates the water, creating longer-lasting
effects. Globally, algal blooms due to eutrophication are becoming more
frequent and more toxic, in 2018 there were &lt;a href="https://www.theguardian.com/environment/2020/jan/04/lethal-algae-blooms-an-ecosystem-out-of-balance"&gt;300 reported
incidents&lt;/a&gt; reported&amp;nbsp;worldwide.&lt;/p&gt;
&lt;!-- Non-nutrient pollution --&gt;

&lt;p&gt;There are many other forms of &lt;strong&gt;non-nutrient marine pollution&lt;/strong&gt;, including any
substance or object introduced that has a harmful effect on ecosystems. There
are a vast array of non-nutrient pollutants, each with their own harmful
effects, but including pesticides, herbicides, fungicides, hydrocarbons, oil
spills, plastics, heavy metals, radioactive waste and hot water from power
stations. Like nutrient pollution, non-nutrient pollutants typically come from
diffuse sources such as land runoff, wind-blown debris, atmospheric emissions,
shipping, and oil extraction. These sources include waste material or chemicals
from industrial, agricultural and residential activities. Industrial activities
that do discharge contaminants directly into waterways or by incineration,
discharge them as airborne particles that eventually settle. For example:
pesticides are widely used in plant agriculture and antibiotics and growth
hormones in livestock agriculture, transport produces substantial oil and
rubber residues, and domestic use of a variety of chemicals and medicines leads
to contaminants eventually finding their way into watercourses. To give one
example it is estimated that the amount of plastic pollution has increased
tenfold since 1980, and that 4 to 12 million tonnes of plastic entered the
oceans in just one year in 2010. The &lt;a href="https://marinedebris.noaa.gov/movement/great-pacific-garbage-patch"&gt;Great Pacific Garbage Patch&lt;/a&gt; is
estimated to be 700,000 square km and containing 80,000 tonnes of&amp;nbsp;waste.&lt;/p&gt;
&lt;!-- Foreign species --&gt;

&lt;p&gt;The introduction of &lt;strong&gt;foreign species&lt;/strong&gt; into non-native habitats is another
form of ocean pollution that has dramatic, negative effects on marine
ecosystems and biodiversity. The movement happens primarily via the ballast
water of ships. When a ship is docked, it will fill internal water reservoirs to
counterbalance cargo. When the ship arrives at its destination and has
unloaded, it will discharge its ballast, along with whatever stowaways it
contains, from fish to microscopic organisms. Plastics are being recognised as
another vector for species movement, with organisms that can attach themselves
to floating plastic debris such as jellyfish polyps and algae. Recorded
invasive species have doubled in the last 50 years, and the threat posed is
acknowledged to be one of the &lt;a href="https://www.oceanprotect.org/resources/issue-briefs/invasive-species/"&gt;main drivers impacting global
biodiversity&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Global&amp;nbsp;warming&lt;/h2&gt;
&lt;p&gt;Global warming induced climate change has a broad impact on nature and
interacts with many of the other drivers discussed, exacerbating the negative
impacts. With an accelerating rate of climate change, it poses a significant
and growing risk to nature and&amp;nbsp;humans.&lt;/p&gt;
&lt;p&gt;There are clear indicators of the drivers and effects of global warming due to
anthropogenic emissions (hazardous emissions caused by humans), as shown by the
charts below. Atmospheric concentration of carbon dioxide (&lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;) is
at 408 parts per million and 147% more than pre-industrial levels (&lt;span class="caps"&gt;PIL&lt;/span&gt;, of
which 1750 is used as a representative baseline); methane (&lt;span class="caps"&gt;CH&lt;/span&gt;&lt;sub&gt;4&lt;/sub&gt;) is
at 1,870 parts per billion and 259% more than &lt;span class="caps"&gt;PIL&lt;/span&gt;; and nitrous oxide
(N&lt;sub&gt;2&lt;/sub&gt;O) is at 331 parts per billion and 123% of &lt;span class="caps"&gt;PIL&lt;/span&gt;. As a consequence,
the global mean temperature and the global mean sea level are 1.2C and 20 cm
higher respectively than &lt;span class="caps"&gt;PIL&lt;/span&gt; with year-on-year records being set. Temperature
and sea-level rises are variable across the globe, for instance the Arctic has
been experiencing sustained higher-than-average temperatures. The global oxygen
(O&lt;sub&gt;2&lt;/sub&gt;) level has been declining since it was first measured in 1991,
approximately 0.05% higher than the present&amp;nbsp;day.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/Climate-levels.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/Climate-levels_w=800.png" alt="Climate Levels (2 Degrees Institute)."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Climate Levels (2 Degrees Institute).&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The 2018 &lt;a href="https://www.ipcc.ch/sr15"&gt;&lt;span class="caps"&gt;IPCC&lt;/span&gt; &amp;#8216;Global Warming of 1.5C&amp;#8217; report&lt;/a&gt; sets
out the current status and trajectory of planetary temperature. Humans have
caused approximately 1.2C of global warming since pre industrial levels.
Historical emissions of greenhouse gasses are likely to cause further warming
of 0.5C over the next two to three decades, with effects persisting for
millennia. In other words, the possibility of avoiding 1.5C warming is now
vanishingly small, even if there was an immediate halt of anthropogenic
emissions. This puts us on a pathway of warming from 1-2 C warming and beyond,
which is predicted to have significantly worse effects compared with 1.5C until
the end of the century, &lt;a href="https://www.ipcc.ch/sr15/chapter/chapter-3/"&gt;including&lt;/a&gt;:&lt;/p&gt;
&lt;div class="float-right" width="400px"&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/NSIDC-arctic-sea-ice-extent-2012.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/NSIDC-arctic-sea-ice-extent-2012_w=300.png" alt="Sea ice extent Sep 2012, National Snow and Ice Data Center Boulder."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Sea ice extent Sep 2012, National Snow and Ice Data Center Boulder.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;More frequent &lt;strong&gt;extreme weather events&lt;/strong&gt; including heatwaves, heavy precipitation,
   severe drought, with effects including large-scale wild fires and&amp;nbsp;flooding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Higher average temperatures&lt;/strong&gt;, with increases being 2 to 3 times greater
   in some&amp;nbsp;regions.&lt;/li&gt;
&lt;li&gt;More frequent &lt;strong&gt;ice-free Arctic&lt;/strong&gt;, once per decade rather than once per century, with
   consequences for ocean circulation and more warming due to less reflection
   of heat (see 2012 ice extent image, showing a 12% loss per decade since 1979).
   2020 has continued the trend with a &lt;a href="https://www.theguardian.com/world/2020/oct/22/alarm-as-arctic-sea-ice-not-yet-freezing-at-latest-date-on-record"&gt;later than ever&lt;/a&gt; ice-free
   arctic. Similar reductions in ice affect polar mountain glaciers and ice&amp;nbsp;sheets.&lt;/li&gt;
&lt;li&gt;Increased &lt;strong&gt;sea level rise&lt;/strong&gt; driven by ocean warming and melting ice: 10cm
   more by 2100, affecting approximately 10.4 million more&amp;nbsp;people.&lt;/li&gt;
&lt;li&gt;Potential to trigger &lt;strong&gt;instabilities in the Greenland and Antarctic ice
   sheets&lt;/strong&gt;, which would result in multi-meter sea-level&amp;nbsp;rises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These effects have consequent impacts in terrestrial&amp;nbsp;ecosystems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Species habitat loss&lt;/strong&gt; through reduction in their climatically determined
   geographic range, a total of 6% to 18% loss for insects, 8% to 16% loss for
   plants and 4% to 8% loss for vertebrates. Some species will adapt by moving
   further north, but some will not be able to. Other species will exploit the
   opportunity, to move into areas once too cold, often with detrimental&amp;nbsp;effects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transformation of terrestrial and wetland ecosystems&lt;/strong&gt;, such as the expansion
   of desert, is 13% globally, vs 4% at&amp;nbsp;1.5C.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thawing of permafrost&lt;/strong&gt; with an area of 1.5 to 2.5 million km$^2$, which is
   approximately 40% of the arctic&amp;#8217;s&amp;nbsp;permafrost.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In ocean&amp;nbsp;ecosystems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tropical coral reef loss&lt;/strong&gt; is almost total at &amp;gt;99%, compared with 70-90% lost at&amp;nbsp;1.5C.&lt;/li&gt;
&lt;li&gt;Substantial &lt;strong&gt;changes to ocean chemistry&lt;/strong&gt; leading to acidification, hypoxia and dead&amp;nbsp;zones.&lt;/li&gt;
&lt;li&gt;Increasing numbers of jellyfish, particularly in&amp;nbsp;blooms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On water&amp;nbsp;resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increase in &lt;strong&gt;water scarcity&lt;/strong&gt; by up to&amp;nbsp;50%.&lt;/li&gt;
&lt;li&gt;Reduced &lt;strong&gt;food security&lt;/strong&gt; caused by reduced crop yields, reduced fisheries
   (twice the level of decline compared with 1.5C) and reduced production&amp;nbsp;livestock.&lt;/li&gt;
&lt;li&gt;Substantial &lt;strong&gt;decline in fisheries productivity&lt;/strong&gt; at low&amp;nbsp;latitudes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And impact humans as&amp;nbsp;well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Substantial increase in human exposure to &lt;strong&gt;flooding&lt;/strong&gt;, affecting 10 million
   more&amp;nbsp;people.&lt;/li&gt;
&lt;li&gt;Increased negative consequences to &lt;strong&gt;human health&lt;/strong&gt; due to heat, diseases
   and malnutrition, with greater risks in urban&amp;nbsp;areas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pest species&lt;/strong&gt; such as mosquitos and ticks that spread disease, and locusts
   and beetles that ruin&amp;nbsp;crops.&lt;/li&gt;
&lt;li&gt;Increased &lt;strong&gt;poverty&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limiting global warming to 1.5-2 C requires nothing short of immediate and
dramatic reductions in global emissions to reach net zero &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; and
similar reductions in gasses such as methane, but policy and aspirations fall
short of the change necessary. The charts below illustrate the different
pathways that can be taken, and this stark contrast: current pledges and
targets fall 50% short of the expected reduction of emissions to limit warming
to 1.5 C under the Paris agreement and 30% of the expected emissions for 2 C.
By the end of the century, we will end up with around 4 C of warming if we
carry on as normal, but still almost 3 C with the realisation of current policy
and&amp;nbsp;pledges.&lt;/p&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/CAT-Graph-2030EmissionsGaps-2020.09.original.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/CAT-Graph-2030EmissionsGaps-2020.09.original_w=500.png" alt="Climate Action Tracker 2030 emissions gaps."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Climate Action Tracker 2030 emissions gaps.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/nature/CAT-2100WarmingProjectionsGraph-2020.09.original.png" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/CAT-2100WarmingProjectionsGraph-2020.09.original_w=500.png" alt="Climate Action Tracker 2100 warming projections."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Climate Action Tracker 2100 warming projections.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;!--
https://www.ipcc.ch/sr15/chapter/chapter-3/
https://www.wri.org/blog/2018/10/half-degree-and-world-apart-difference-climate-impacts-between-15-c-and-2-c-warming
https://www.carbonbrief.org/scientists-compare-climate-change-impacts-at-1-5c-and-2c
https://nymag.com/intelligencer/2017/07/climate-change-earth-too-hot-for-humans.html
--&gt;

&lt;h2&gt;Final&amp;nbsp;thoughts&lt;/h2&gt;
&lt;p&gt;This note attempts to concisely and objectively summarise the issues
surrounding human impact on nature. Since I&amp;#8217;m not an expert, it necessarily
skims along the top of what are hugely complex issues. What I do hope however
is that it conveys the magnitude and gravity of the situation for nature on
earth and how the contributing issues are deeply&amp;nbsp;interconnected.&lt;/p&gt;
&lt;!--I also hope that it serves as a resource to aid understanding and as a
contemporaneous reference for those taking part in related discussions.--&gt;

&lt;p&gt;Climate change is now beginning to be taken more seriously and is increasingly
becoming part of normal discourse. But the declines in biodiversity and
ecosystem services are generally poorly understood and regarded as risks, but
currently have a disproportionately greater impact on humans with issues such
as access to freshwater, air pollution and protection from extreme weather.
The &lt;span class="caps"&gt;UN&lt;/span&gt; Global Assessment Report finds that negative trends in nature will
continue until 2050 and beyond due to the projected impacts of increasing land-use
change, exploitation of organisms and climate change under current
trajectories. These impacts will also be distributed unevenly and will affect
many of the world&amp;#8217;s indigenous people and poorest communities&amp;nbsp;first.&lt;/p&gt;
&lt;p&gt;The ongoing assessment of the state of nature and modelling of the future are
imperfect and we cannot fully understand the consequences of human actions.
What we can be sure about however is that our situation is unprecedented in
history. Measured against the earth&amp;#8217;s history, the time frame for these effects
to become catastrophic is just a blink of an eye. Should things change
dramatically tomorrow, many of these impacts are locked in for decades.
Momentum to mitigate these issues is building but will it be enough, and in&amp;nbsp;time?&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;UN&lt;/span&gt; report concludes that avoiding such a scenario requires systematic,
transformative change across across economic, social, political and
technological factors. Everyone has a part to&amp;nbsp;play.&lt;/p&gt;
&lt;!--
World fails to meet a single target to stop destruction of nature – UN report
https://www.theguardian.com/environment/2020/sep/15/every-global-target-to-stem-destruction-of-nature-by-2020-missed-un-report-aoe
'Lost decade for nature' as UK fails on 17 of 20 UN biodiversity targets
https://www.theguardian.com/global-development/2020/sep/14/lost-decade-for-nature-as-uk-fails-on-17-of-20-un-biodiversity-targets-aoe
--&gt;

&lt;h2&gt;References / further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://climateactiontracker.org/global/cat-emissions-gaps"&gt;Climate Action Tracker&lt;/a&gt;, 2030 emissions&amp;nbsp;gaps.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.climatelevels.org/"&gt;Climate Levels&lt;/a&gt;, live graphs of atmospheric concentrations of greenhouse gasses and global mean temperature, sea level and oxygen&amp;nbsp;level.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jembendell.com/2019/05/15/deep-adaptation-versions/"&gt;Deep Adaptation: A Map for Navigating Climate Tragedy&lt;/a&gt;, Jem Bendell,&amp;nbsp;2018.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cbd.int/gbo5"&gt;Global biodiversity outlook 5&lt;/a&gt;, Secretariat of the Convention on Biological Diversity&amp;nbsp;2020.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://globalfishingwatch.org/"&gt;Global Fishing&amp;nbsp;Watch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.globalforestwatch.org/"&gt;Global Forest&amp;nbsp;Watch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skepticalscience.com/argument.php"&gt;Global Warming &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Climate Change&amp;nbsp;Myths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.global-wetland-outlook.ramsar.org/outlook"&gt;Global Wetland Outlook: State of the World&amp;#8217;s Wetlands and their services to people&lt;/a&gt;, Ramsar Convention on Wetlands&amp;nbsp;2018.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://deepoceanfacts.com/ocean-pollution"&gt;Ocean Pollution: Causes and Effects&lt;/a&gt;, Deep Ocean&amp;nbsp;Facts.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oceanprotect.org/resources/issue-briefs/"&gt;One Ocean Project, issue&amp;nbsp;briefs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fao.org/documents/card/en/c/ca8985en"&gt;State of the World&amp;#8217;s Forests 2020. In&amp;nbsp;brief&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stung! On Jellyfish Blooms and the Future of the Ocean, &lt;a href="http://lisagershwin.com"&gt;Lisa-ann Gershwin&lt;/a&gt;,&amp;nbsp;2013.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.swissre.com/institute/research/topics-and-risk-dialogues/climate-and-natural-catastrophe-risk/expertise-publication-biodiversity-and-ecosystems-services.html"&gt;Swiss Re Institute&amp;#8217;s report on Biodiversity and Ecosystem Services: A business case for re/insurance&lt;/a&gt; (&lt;a href="https://www.theguardian.com/environment/2020/oct/12/fifth-of-nations-at-risk-of-ecosystem-collapse-analysis-finds"&gt;Guardian coverage&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@cache_86525/the-future-is-grim-27ca6f7ab07b"&gt;The future is grim&lt;/a&gt;, Cache Baba,&amp;nbsp;2019.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://uknea.unep-wcmc.org/"&gt;&lt;span class="caps"&gt;UK&lt;/span&gt; National Ecosystem Assessment&lt;/a&gt;&amp;nbsp;(2014).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ipbes.net/global-assessment"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; Global Assessment Report on Biodiversity and Ecosystem Services&lt;/a&gt; (&lt;a href="https://www.un.org/sustainabledevelopment/blog/2019/05/nature-decline-unprecedented-report/"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; blog article with good summary of facts&lt;/a&gt;) (&lt;a href="https://www.theguardian.com/environment/2019/may/06/human-society-under-urgent-threat-loss-earth-natural-life-un-report"&gt;Guardian coverage&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.unenvironment.org/resources/global-environment-outlook-6"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; Global Environment Outlook 6&lt;/a&gt;,&amp;nbsp;2019.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knowledge.unccd.int/glo/GLO_first_edition"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; Global Land Outlook&lt;/a&gt;, &lt;span class="caps"&gt;UN&lt;/span&gt; Convention to Combat Desertification (&lt;span class="caps"&gt;UNCCD&lt;/span&gt;), 2017. (&lt;a href="https://www.theguardian.com/environment/2017/sep/12/third-of-earths-soil-acutely-degraded-due-to-agriculture-study"&gt;Guardian coverage&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fao.org/state-of-forests/en/"&gt;&lt;span class="caps"&gt;UN&lt;/span&gt; State of The World&amp;#8217;s Forests 2020 report&lt;/a&gt;, &lt;span class="caps"&gt;UN&lt;/span&gt; Food and Agriculture&amp;nbsp;Organization.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wwf.panda.org/knowledge_hub/all_publications/living_planet_report_2018/"&gt;&lt;span class="caps"&gt;WWF&lt;/span&gt; Living Planet Report 2018: Aiming Higher&lt;/a&gt; (&lt;a href="https://www.theguardian.com/environment/2018/oct/30/humanity-wiped-out-animals-since-1970-major-report-finds"&gt;Guardian coverage&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://livingplanet.panda.org/en-us/"&gt;&lt;span class="caps"&gt;WWF&lt;/span&gt; Living Planet Report 2020: Bending the Curve of Biodiversity Loss&lt;/a&gt; (&lt;a href="https://www.theguardian.com/environment/2020/sep/10/humans-exploiting-and-destroying-nature-on-unprecedented-scale-report-aoe"&gt;Guardian coverage&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://library.wmo.int/doc_num.php?explnum_id=10211"&gt;World Meteorological Organization, Statement on the State of the Global Climate in&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://earthobservatory.nasa.gov/world-of-change"&gt;World of Change&lt;/a&gt;, satellite imagery of the changing Earth surface from &lt;span class="caps"&gt;NASA&lt;/span&gt; Earth&amp;nbsp;Observatory.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Perspectives"/><category term="climate-change"/><category term="sustainability"/></entry><entry><title>Error-correcting codes</title><link href="https://jameswhanlon.com/error-correcting-codes.html" rel="alternate"/><published>2020-05-02T00:00:00+02:00</published><updated>2020-05-02T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2020-05-02:/error-correcting-codes.html</id><summary type="html">&lt;p&gt;Using Hamming Codes for single error correction and double error&amp;nbsp;detection.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Error correcting codes (ECCs) are used in computer and communication systems to
improve resiliency to bit flips caused by permanent hardware faults or
transient conditions, such as neutron particles from cosmic rays, known
generally as &lt;a href="https://en.wikipedia.org/wiki/Soft_error"&gt;soft errors&lt;/a&gt;. This note
describes the principles of Hamming codes that underpin &lt;span class="caps"&gt;ECC&lt;/span&gt; schemes, &lt;span class="caps"&gt;ECC&lt;/span&gt; codes
are constructed, focusing on single-error correction and double error
detection, and how they are&amp;nbsp;implemented.&lt;/p&gt;
&lt;p&gt;ECCs work by adding additional redundant bits to be stored or transported with
data. The bits are encoded as a function of the data in such a way that it is
possible to detect erroneous bit flips and to correct them. The ratio of the
number of data bits to the total number of bits encoded is called the &lt;em&gt;code
rate&lt;/em&gt;, with a rate of 1 being a an impossible encoding with no&amp;nbsp;overhead.&lt;/p&gt;
&lt;h2&gt;Simple&amp;nbsp;ECCs&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Parity coding&lt;/strong&gt; adds a single bit that indicates whether the number of set
bits in the data is odd or even. When the data and parity bit is accessed or
received, the parity can be recomputed and compared. This is sufficient to
detect any odd number of bit flips but not to correct them. For applications
where the error rate is low, so that only single bit flips are likely and
double bit flips are rare enough to be ignored, parity error detection is
sufficient and desirable due to it&amp;#8217;s low overhead (just a single bit) and
simple&amp;nbsp;implementation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Repetition coding&lt;/strong&gt; simply repeats each data bit a fixed number of times. When
the encoded data is received, if each of the repeated bits are non identical,
an error has occurred. With a repetition of two, single-bit errors can be
detected but not corrected. With a repetition of three, single bit flips can be
corrected by determining each data bit as the majority value in each triple,
but double bit flips are undetectable and will cause an erroneous correction.
Repetition codes are simple to implement but have a high&amp;nbsp;overhead.&lt;/p&gt;
&lt;h2&gt;Hamming&amp;nbsp;codes&lt;/h2&gt;
&lt;p&gt;Hamming codes are an efficient family of codes using additional redundant bits to
detect up to two-bit errors and correct single-bit errors (technically, they are
&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Linear_code"&gt;linear error-correcting codes&lt;/a&gt;&lt;/em&gt;).
In them, &lt;em&gt;check bits&lt;/em&gt; are added to data bits to form a &lt;em&gt;codeword&lt;/em&gt;, and the
codeword is &lt;em&gt;valid&lt;/em&gt; only when the check bits have been generated from the data
bits, according to the Hamming code. The check bits are chosen so that there is
a fixed &lt;em&gt;Hamming distance&lt;/em&gt; between any two valid codewords (the number of
positions in which bits&amp;nbsp;differ).&lt;/p&gt;
&lt;p&gt;When valid codewords have a Hamming distance of two, any single bit flip will
invalidate the word and allow the error to be detected. For example, the valid&amp;nbsp;codewords &lt;code&gt;00&lt;/code&gt; and &lt;code&gt;11&lt;/code&gt; are separated for single bit flips by the invalid&amp;nbsp;codewords &lt;code&gt;01&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt;. If either of the invalid words is obtained an error
has occurred, but neither can be associated with a valid codeword. Two bit
flips are undetectable since they always map to a valid codeword. Note that
parity encoding is an example of a distance-two Hamming&amp;nbsp;code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;00 &amp;lt; Valid codeword
|
10 &amp;lt; Invalid codeword (obtained by exactly 1 bit flip)
|
11 &amp;lt; Valid codeword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With Hamming distance three, any single bit flip in a valid codeword makes an
invalid one, and the invalid codeword is Hamming distance one from exactly one
valid codeword. Using this, the valid codeword can be restored, enabling single
error correction. Any two bit flips map to an invalid codeword, which would
cause correction to the wrong valid&amp;nbsp;codeword.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;000 &amp;lt; Valid codeword
 |
001
 |
011
 |
111 &amp;lt; Valid codeword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With Hamming distance four, two bit flips moves any valid codeword Hamming
distance two from exactly two valid codewords, allowing detection of two flips
but not correction. Single bit flips can be corrected as they were for distance
three. Distance-four codes are widely used in computing, where is it often the
case where single errors are frequent, double errors are rare and triple errors
occur so rarely they can be ignored. These codes are referred to as &amp;#8216;&lt;span class="caps"&gt;SECDED&lt;/span&gt;
&lt;span class="caps"&gt;ECC&lt;/span&gt;&amp;#8217; (single error correction, double error&amp;nbsp;detection).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;0000 &amp;lt; Valid codeword
 |
0001
 |
0011 &amp;lt; Two bit flips from either codeword.
 |
0111
 |
1111 &amp;lt; Valid codeword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Double errors can be corrected with a distance-five code, as well as enabling
the detection of triple errors. In general, if a Hamming code can detect $d$
errors, it must have a minimum distance of $d+1$ so there is no way $d$ errors
can change one valid codeword into another one. If a code can correct $d$
errors, it must have a minimum distance of $2d+1$ so that the originating code
is always the closest one. The following table summarises Hamming&amp;nbsp;codes.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th scope="col"&gt;Distance&lt;/th&gt;
    &lt;th scope="col"&gt;Max bits corrected&lt;/th&gt;
    &lt;th scope="col"&gt;Max bits detected&lt;/th&gt;
    &lt;th scope="col"&gt;&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;Single error detection (eg parity code)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;Single error correction (eg triple repetition code)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;4&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;Single error correction, double error detection (a &amp;#8216;&lt;span class="caps"&gt;SECDED&lt;/span&gt;&amp;#8217; code)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;5&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;Double error correction&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;6&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;3&lt;/td&gt;
    &lt;td&gt;Double error correction, triple error detection&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;Creating a Hamming&amp;nbsp;code&lt;/h2&gt;
&lt;p&gt;A codeword includes the data bits and checkbits. Each check bit corresponds to
a subset of the data bits and it is set when the parity of those data bits is
odd. To obtain a code with a particular Hamming distance, the number of check
bits and their mapping to data bits must be chosen&amp;nbsp;carefully.&lt;/p&gt;
&lt;p&gt;To build a single-error correcting (&lt;span class="caps"&gt;SEC&lt;/span&gt;) code that requires Hamming distance
three between valid codewords, it is necessary&amp;nbsp;for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The mapping of each data bit to check bits is&amp;nbsp;unique.&lt;/li&gt;
&lt;li&gt;Each data bit to map to at least two check&amp;nbsp;bits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see why this works, consider two distinct codewords that necessarily
must have different data bits. If the data bits differ&amp;nbsp;by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;1 bit&lt;/strong&gt;, at least two check bits are flipped, giving a total of three
  different&amp;nbsp;bits.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;2 bits&lt;/strong&gt;, these will cause at least one flip in the check bits since any two
  data bits cannot share the same check-bit mapping (ie by taking the &lt;span class="caps"&gt;XOR&lt;/span&gt; of
  the two check bit patterns). This also gives a total of three different bits as&amp;nbsp;required.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;3 bits&lt;/strong&gt;, this is already sufficient to give a Hamming distance of&amp;nbsp;three.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To build a &lt;span class="caps"&gt;SECDED&lt;/span&gt; code that requires Hamming distance of four between valid
codewords, it is necessary&amp;nbsp;for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The mapping of each data bit to check bits is&amp;nbsp;unique.&lt;/li&gt;
&lt;li&gt;Each data bit to map to at least three check&amp;nbsp;bits.&lt;/li&gt;
&lt;li&gt;Each check bit pattern to have an odd number of bits&amp;nbsp;set.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following a similar argument, consider two distinct codewords, data differing&amp;nbsp;by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;1 bit&lt;/strong&gt; flips three check bits, giving a total of four different&amp;nbsp;bits.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;2 bits&lt;/strong&gt; flip check bits in two patterns, and since any two odd-length patterns
  must have at least two non-overlapping bits, the results is at least two
  flipped bits, giving a total of four different bits. For&amp;nbsp;example:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Check bits:  0 1 2 3
data[a]      x x x
data[b]        x x x
-----------  --------
Flips        x     x

Check bits:  0 1 2 3 4
data[a]      x x x
data[b]      x x x x x
----------   ---------
Flips              x x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;3 bits&lt;/strong&gt; flip check bits in three patterns, and this time it is possible to
  overlap odd-length patterns in such a way that a minimum of 1 bit is flipped.
  For&amp;nbsp;example:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Check bits:  0 1 2 3 4
data[a]      x x x
data[b]        x x x
data[c]      x     x x
-----------  ---------
Flips                x

Check bits:  0 1 2 3 4
data[a]      x x x x x
data[b]      x x x
data[c]      x     x x
-----------  ---------
Flips        x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;4 bits&lt;/strong&gt; is already sufficient to provide a Hamming distance of&amp;nbsp;four.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example &lt;span class="caps"&gt;SEC&lt;/span&gt; code for eight data bits with four parity&amp;nbsp;bits:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Check bits:  0 1 2 3
data[0]      x x x
data[1]        x x x
data[2]      x   x x
data[3]      x x   x
data[4]      x x
data[5]        x x
data[6]          x x
data[7]      x     x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;An example &lt;span class="caps"&gt;SECDED&lt;/span&gt; code for eight data bits with five parity&amp;nbsp;bits:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Check bits:  0 1 2 3 4
data[0]      x x x
data[1]      x x   x
data[2]      x   x x
data[3]        x x x
data[4]      x x     x
data[5]      x   x   x
data[6]        x x   x
data[7]      x     x x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that mappings of data bits to check bits can be chosen flexibly, providing
they maintain the rules that set the Hamming distance. This flexibility is
useful when implementing &lt;span class="caps"&gt;ECC&lt;/span&gt; to reduce the cost of calculating the check bits.
In contrast, many descriptions of &lt;span class="caps"&gt;ECC&lt;/span&gt; that I have found in text books and on
&lt;a href="https://en.wikipedia.org/wiki/Hamming_code"&gt;Wikipedia&lt;/a&gt; describe a specific
encoding that does not acknowledge this freedom. The encoding they describe
allows the syndrome to be interpreted as the bit index of the single bit error,
by the check bit in position $i$ covering data bits in position $i$.
Additionally, they specify that parity bits are positioned in the codeword at
power-of-two positions, for no apparent&amp;nbsp;benefit.&lt;/p&gt;
&lt;h2&gt;Implementing &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Given data bits and check bits, and mapping of data bits to check bits, &lt;span class="caps"&gt;ECC&lt;/span&gt;
encoding works by calculating the check bits from the data bits, then combining
data bits and check bits to form the codeword. Decoding works by taking the
data bits from a codeword, recalculating the check bits, then calculating the
bitwise &lt;span class="caps"&gt;XOR&lt;/span&gt; between the original check bits and the recalculated ones. This
value is called the &lt;em&gt;syndrome&lt;/em&gt;. By inspecting the number of bits set in the
syndrome, it is possible to determine whether there has been an error,
whether it is correctable, and how to correct&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Using the &lt;span class="caps"&gt;SEC&lt;/span&gt; check-bit encoding above, creating a codeword&amp;nbsp;from &lt;code&gt;data[7:0]&lt;/code&gt;,
the check bits are calculated as follows (using Verilog&amp;nbsp;syntax):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;6&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the codeword formed by concatenating the check bits and&amp;nbsp;data:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;codeword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Decoding of a codeword, splits it into the checkword and data bits, recomputes
the check bits and calculates the&amp;nbsp;syndrome:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;old_check_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;codeword&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_check_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_check_word&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_check_word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When single bit errors occur, the syndrome will have the bit pattern
corresponding to a particular data bit, so a correction can be applied by
creating a mask to flip the bit in that&amp;nbsp;position:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1110&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0111&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1011&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1101&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1100&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0110&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0011&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And using it to generate the corrected&amp;nbsp;data:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;corrected_data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The value of the syndrome can be further inspected to signal what action has
been taken. If the syndrome&amp;nbsp;is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Equal to zero, no error&amp;nbsp;occurred.&lt;/li&gt;
&lt;li&gt;Has one bit set, then this is a flip of a check bit and can be&amp;nbsp;ignored.&lt;/li&gt;
&lt;li&gt;Has a value matching a pattern (three bits set or two bits in the adjacent positions), a correctable error&amp;nbsp;occurred.&lt;/li&gt;
&lt;li&gt;Has a value not matching a pattern (two bits set in the other non-adjacent&amp;nbsp;positions: &lt;code&gt;4'b1010&lt;/code&gt;, &lt;code&gt;4'b0101&lt;/code&gt;), or four bits set, a multi-bit uncorrectable error&amp;nbsp;occurred.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above &lt;span class="caps"&gt;SECDED&lt;/span&gt; check-bit encoding can be implemented in a similar way, but
since it uses only three-bit patterns, mapping syndromes to correction masks
can be done with three-input &lt;span class="caps"&gt;AND&lt;/span&gt;&amp;nbsp;gates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;syndrome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;                                   &lt;/span&gt;&lt;span class="n"&gt;correction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And any syndromes with one or two bits set are correctable, and otherwise&amp;nbsp;uncorrectable.&lt;/p&gt;
&lt;h2&gt;References / further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Error_correction_code"&gt;Error correction code&lt;/a&gt;,&amp;nbsp;Wikipedia.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Hamming_code"&gt;Hamming code&lt;/a&gt;,&amp;nbsp;Wikipedia.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/ECC_memory"&gt;&lt;span class="caps"&gt;ECC&lt;/span&gt; memory&lt;/a&gt;,&amp;nbsp;Wikipedia.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://signallake.com/innovation/hamming.pdf"&gt;Error detecting and error correcting codes (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;,
  &lt;span class="caps"&gt;R. W.&lt;/span&gt; Hamming, in The Bell System Technical Journal, vol. 29, no. 2, pp. 147-160, April&amp;nbsp;1950.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pages.cs.wisc.edu/~david/courses/cs552/S12/handouts/ecc-phelps.pdf"&gt;Constructing an Error Correcting Code (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;,
  Andrew E. Phelps, University of Wisconsin, Madison, November&amp;nbsp;2006.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/></entry><entry><title>Recycled allotment shed</title><link href="https://jameswhanlon.com/recycled-allotment-shed.html" rel="alternate"/><published>2019-11-10T00:00:00+01:00</published><updated>2019-11-10T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2019-11-10:/recycled-allotment-shed.html</id><summary type="html">&lt;p&gt;Low-cost construction of a shed out of reclaimed&amp;nbsp;materials.&lt;/p&gt;</summary><content type="html">&lt;p&gt;A friend was in need of a shed on her allotment to store tools and as a place
to shelter in the rain, so I helped her to build one. The aim was to build
something solid that would stand up to the elements (unlike most allotment
sheds), to use recycled materials as far as possible, and ideally to fit within
a £100&amp;nbsp;budget.&lt;/p&gt;
&lt;p&gt;The main costs were the structural timber, which was sourced from the &lt;a href="https://www.bwrp.org.uk/"&gt;Bristol Wood Recycling
Project&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;~15m of 2x3&amp;#8221; softwood&amp;nbsp;timber;&lt;/li&gt;
&lt;li&gt;~60m of 1.5x2.5&amp;#8221; softwood&amp;nbsp;timber.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also from the &lt;span class="caps"&gt;BWRP&lt;/span&gt; were: sheets of 12mm ply for the floor and roof, solid wood
planks for the door, an odd piece of shelving which worked brilliantly as a big
window sill, baton for the window frame. Other costs were: two boxes of screws
and roofing nails (Screwfix), acrylic sheet for the window (Wickes). Everything
else was sourced for free, from friends or found on the streets of Bristol:
breeze blocks for the base, pallet wood for the cladding, miscellaneous timber
for the frame, roof felt and felt glue and hinges and shackles for the&amp;nbsp;door.&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t keep details of all the money spent, but the final cost was
approximately £150 and the end result was a sturdy shed that should last quite a
few&amp;nbsp;years.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/previous.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/previous_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/previous-side.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/previous-side_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The existing structure that was intended to become a shed but never did.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/cleared.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cleared_600x600.jpg" alt="The site with the old shed cleared."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The site with the old shed cleared.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/footings.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/footings_600x600.jpg" alt="Breeze blocks in position for a base."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Breeze blocks in position for a base.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/base-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/base-1_600x600.jpg" alt="The floor in position."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The floor in position.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/frame-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/frame-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/frame-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/frame-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/frame-3.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/frame-3_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Progress of the frame construction, finally with the roof in place.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/roof-detail-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-detail-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/roof-detail-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/roof-detail-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Details of the roof notches to sit level on the frame.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/cladding-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/cladding-3.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-3_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/cladding-side.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cladding-side_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Details of the pallet-wood cladding.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/window-frame.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/window-frame_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/window-frame-inside.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/window-frame-inside_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;With the window frame installed (now looking more like a shed, rather than a ticket office).&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/back.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/allotment-shed/complete-door-and-window.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/complete-door-and-window_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The completed shed, with window and door installed. One final job is to install guttering on the back edge of the roof, which can feed a water butt.&lt;/figcaption&gt;
&lt;/figure&gt;</content><category term="Physical Projects"/><category term="sheds"/><category term="construction"/></entry><entry><title>New chips for machine intelligence</title><link href="https://jameswhanlon.com/new-chips-for-machine-intelligence.html" rel="alternate"/><published>2019-10-04T00:00:00+02:00</published><updated>2019-10-04T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2019-10-04:/new-chips-for-machine-intelligence.html</id><summary type="html">&lt;p&gt;Details of new chips that have been built recently to accelerate
machine intelligence&amp;nbsp;workloads.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This note summarises details of some of the new silicon chips for machine
intelligence. Its aim is to distil the most important implementation and
architectural details (at least that are currently available), to highlight the
main differences between them. I&amp;#8217;m focusing on chips designed for training
since they represent the frontier in performance and capability. There are many
chips designed for inference, but these are typically intended for use in
embedded or edge&amp;nbsp;deployments.&lt;/p&gt;
&lt;p&gt;In&amp;nbsp;summary:&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;
*Speculated&lt;br&gt;
&amp;dagger; Figures given for a single chip
&lt;/caption&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th scope="col"&gt;Chip&lt;/th&gt;
    &lt;th scope="col"&gt;Process&lt;/th&gt;
    &lt;th scope="col"&gt;Die size&lt;br&gt;mm&lt;sup&gt;2&lt;/sup&gt;&lt;/th&gt;
    &lt;th scope="col"&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;br&gt;(W)&lt;/th&gt;
    &lt;th scope="col"&gt;On-chip &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;br&gt;(&lt;span class="caps"&gt;MB&lt;/span&gt;)&lt;/th&gt;
    &lt;th scope="col"&gt;Peak &lt;span class="caps"&gt;FP32&lt;/span&gt;&lt;br&gt;(TFLOPs)&lt;/th&gt;
    &lt;th scope="col"&gt;Peak &lt;span class="caps"&gt;FP16&lt;/span&gt;&lt;br&gt;(TFLOPs)&lt;/th&gt;
    &lt;th scope="col"&gt;Mem b/w&lt;br&gt;(&lt;span class="caps"&gt;GB&lt;/span&gt;/s)&lt;/th&gt;
    &lt;th scope="col"&gt;&lt;span class="caps"&gt;IO&lt;/span&gt; b/w&lt;br&gt;(&lt;span class="caps"&gt;GB&lt;/span&gt;/s)&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#cerebras"&gt;Cerebras &lt;span class="caps"&gt;WSE&lt;/span&gt;&lt;sup&gt;&amp;dagger;&lt;/sup&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 16nm&lt;/td&gt;
    &lt;td&gt;510&lt;/td&gt;
    &lt;td&gt;180&lt;/td&gt;
    &lt;td&gt;225&lt;/td&gt;
    &lt;td&gt;40.6&lt;/td&gt;
    &lt;td&gt;n/a&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#google-tpu-1"&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt; v1&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;28nm&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;75&lt;/td&gt;
    &lt;td&gt;28&lt;/td&gt;
    &lt;td&gt;n/a&lt;/td&gt;
    &lt;td&gt;23 (&lt;span class="caps"&gt;INT16&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;30 (&lt;span class="caps"&gt;DDR3&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;14&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#google-tpu-2"&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt; v2&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;20nm*&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;200*&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;45&lt;/td&gt;
    &lt;td&gt;600 (&lt;span class="caps"&gt;HBM&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;8*&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#google-tpu-3"&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt; v3&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;16/12nm*&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;200*&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;90&lt;/td&gt;
    &lt;td&gt;1200 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)*&lt;/td&gt;
    &lt;td&gt;8*&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#graphcore-c2-ipu"&gt;Graphcore &lt;span class="caps"&gt;IPU&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;16nm&lt;/td&gt;
    &lt;td&gt;800*&lt;/td&gt;
    &lt;td&gt;150&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;125&lt;/td&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;384&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#habana-gaudi"&gt;Habana Gaudi&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 16nm&lt;/td&gt;
    &lt;td&gt;500*&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;1000 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;250&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#huawei-ascend"&gt;Huawei Ascend 910&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;7nm+ &lt;span class="caps"&gt;EUV&lt;/span&gt;&lt;/td&gt;
    &lt;td&gt;456&lt;/td&gt;
    &lt;td&gt;350&lt;/td&gt;
    &lt;td&gt;64&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;256&lt;/td&gt;
    &lt;td&gt;1200 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;115&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#intel-nnp-t"&gt;Intel &lt;span class="caps"&gt;NNP&lt;/span&gt;-T&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; &lt;span class="caps"&gt;16FF&lt;/span&gt;+&lt;/td&gt;
    &lt;td&gt;688&lt;/td&gt;
    &lt;td&gt;250&lt;/td&gt;
    &lt;td&gt;60&lt;/td&gt;
    &lt;td&gt;Unknown&lt;/td&gt;
    &lt;td&gt;110&lt;/td&gt;
    &lt;td&gt;1220 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;447&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#nvidia-volta"&gt;Nvidia Volta&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 12nm &lt;span class="caps"&gt;FFN&lt;/span&gt;&lt;/td&gt;
    &lt;td&gt;815&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;21.1&lt;/td&gt;
    &lt;td&gt;15.7&lt;/td&gt;
    &lt;td&gt;125&lt;/td&gt;
    &lt;td&gt;900 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="#nvidia-turing"&gt;Nvidia Turing&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 12nm &lt;span class="caps"&gt;FFN&lt;/span&gt;&lt;/td&gt;
    &lt;td&gt;754&lt;/td&gt;
    &lt;td&gt;250&lt;/td&gt;
    &lt;td&gt;24.6&lt;/td&gt;
    &lt;td&gt;16.3&lt;/td&gt;
    &lt;td&gt;130.5&lt;/td&gt;
    &lt;td&gt;672 (&lt;span class="caps"&gt;HBM2&lt;/span&gt;)&lt;/td&gt;
    &lt;td&gt;100&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;a name="cerebras" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Cerebras Wafer-Scale&amp;nbsp;Engine&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/cerebras-wse_220x220.png" alt="Cerebras chip"&gt;&lt;/p&gt;
&lt;p&gt;The Cerebras Wafer-Scale Engine (&lt;span class="caps"&gt;WSE&lt;/span&gt;) is undoubtedly the most bold and
innovative design to appear recently. Wafer-scale integration is not a new
idea, but integration issues to do with yield, power delivery and thermal
expansion have made it difficult to commercialise (see the 1989 &lt;a href="http://www.computinghistory.org.uk/det/3043/Anamartic-Wafer-Scale-160MB-Solid-State-Disk/"&gt;Anamartic 160
&lt;span class="caps"&gt;MB&lt;/span&gt; solid state disk&lt;/a&gt;). Cerebras use this approach to integrate 84
chips with high-speed interconnect, uniformly scaling the 2D-mesh based
interconnect to huge proportions. This provides a machine with a large amount
of memory (18 &lt;span class="caps"&gt;GB&lt;/span&gt;) distributed among a large amount of compute (3.3 Peta FLOPs
peak). It is unclear how this architecture scales beyond single WSEs; the
current trend in neural nets is to larger networks with billions of weights,
which will necessitate such&amp;nbsp;scaling.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced August&amp;nbsp;2019.&lt;/li&gt;
&lt;li&gt;46,225 mm&lt;sup&gt;2&lt;/sup&gt; wafer-scale integrated system (215 mm x 215 mm) om &lt;span class="caps"&gt;TSMC&lt;/span&gt; 16&amp;nbsp;nm.&lt;/li&gt;
&lt;li&gt;1.2T&amp;nbsp;transistors.&lt;/li&gt;
&lt;li&gt;Many individual chips: a total of 84 (12 wide by 7&amp;nbsp;tall).&lt;/li&gt;
&lt;li&gt;18 &lt;span class="caps"&gt;GB&lt;/span&gt; total of &lt;span class="caps"&gt;SRAM&lt;/span&gt; memory, distributed among&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;426,384 simple compute&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;Silicon defects can be repaired by using redundant cores and links to bypass a faulty area. It appears that each column includes one redundant core, leaving 410,592 functional&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;Speculated clock speed of ~1 GHz and 15 kW power&amp;nbsp;consumption.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interconnect and &lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interconnections between chips, across scribe lines, with wiring added in post-processing steps after conventional wafer&amp;nbsp;manufacturing.&lt;/li&gt;
&lt;li&gt;IOs brought out on east and west edges of wafer, which is limited by the pad density on each edge. It is unlikely there are any high-speed SerDes since these would need to be integrated in every chip, making a sizeable part of the wafer area redundant apart from chips with edges on the&amp;nbsp;periphery.&lt;/li&gt;
&lt;li&gt;2D mesh-based interconnect, supports single-word messages. According to their whitepaper: &amp;#8220;The Cerebras software configures all the cores on the &lt;span class="caps"&gt;WSE&lt;/span&gt; to support the precise communication required&amp;#8221; indicating that the interconnect is statically configured to support a fixed communication&amp;nbsp;pattern.&lt;/li&gt;
&lt;li&gt;Interconnect requires static configuration to support specific patterns of&amp;nbsp;communication.&lt;/li&gt;
&lt;li&gt;Zeros not transmitted on the interconnect to optimise for&amp;nbsp;sparsity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is ~0.1 mm&lt;sup&gt;2&lt;/sup&gt; of&amp;nbsp;silicon.&lt;/li&gt;
&lt;li&gt;Has 47 kB &lt;span class="caps"&gt;SRAM&lt;/span&gt;&amp;nbsp;memory.&lt;/li&gt;
&lt;li&gt;Zeros not loaded from memory and zeros not&amp;nbsp;multiplied.&lt;/li&gt;
&lt;li&gt;Assumed &lt;span class="caps"&gt;FP32&lt;/span&gt; precision and scalar execution (can&amp;#8217;t filter zeros from memory with &lt;span class="caps"&gt;SIMD&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;FMAC&lt;/span&gt; datapath (peak 8 operations per&amp;nbsp;cycle).&lt;/li&gt;
&lt;li&gt;Tensor control unit to feed the &lt;span class="caps"&gt;FMAC&lt;/span&gt; datapath with strided accesses from memory or inbound data from&amp;nbsp;links.&lt;/li&gt;
&lt;li&gt;Has four 8 &lt;span class="caps"&gt;GB&lt;/span&gt;/s bidirectional links to its&amp;nbsp;neighbours.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each&amp;nbsp;die:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is 17 mm x 30 mm = 510 mm&lt;sup&gt;2&lt;/sup&gt; of&amp;nbsp;silicon.&lt;/li&gt;
&lt;li&gt;Has 225 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;SRAM&lt;/span&gt;&amp;nbsp;memory.&lt;/li&gt;
&lt;li&gt;Has 54 x 94 = 5,076 cores (two cores per row/column possibly unused due to repair scheme leaving 4,888 usable&amp;nbsp;cores).&lt;/li&gt;
&lt;li&gt;Peak &lt;span class="caps"&gt;FP32&lt;/span&gt; performance of 40 Tera&amp;nbsp;FLOPs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/14758/hot-chips-31-live-blogs-cerebras-wafer-scale-deep-learning"&gt;AnandTech report from &lt;span class="caps"&gt;HC31&lt;/span&gt;, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cerebras.net/wp-content/uploads/2019/08/Cerebras-Wafer-Scale-Engine-Whitepaper.pdf"&gt;Cerebras white paper, August 2019 (no longer&amp;nbsp;available)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cerebras.net/cerebras-wafer-scale-engine-why-we-need-big-chips-for-deep-learning/"&gt;Cerebras Wafer Scale Engine: Why we need big chips for Deep&amp;nbsp;Learning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="google-tpu-3" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt;&amp;nbsp;v3&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/google-tpu3_220x220.png" alt="TPU-3 board"&gt;&lt;/p&gt;
&lt;p&gt;With few details available on the specifications of the &lt;span class="caps"&gt;TPU&lt;/span&gt; v3, it is likely an
incremental improvement to the &lt;span class="caps"&gt;TPU&lt;/span&gt; v2: doubling the performance, adding &lt;span class="caps"&gt;HBM2&lt;/span&gt;
memory to double the capacity and&amp;nbsp;bandwidth.&lt;/p&gt;
&lt;p&gt;General details (per&amp;nbsp;chip):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced May&amp;nbsp;2018.&lt;/li&gt;
&lt;li&gt;Likely to be 16nm or&amp;nbsp;12nm.&lt;/li&gt;
&lt;li&gt;200W estimated &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;105 TFLOPs of BFloat16, likely from doubling the MXUs to&amp;nbsp;four.&lt;/li&gt;
&lt;li&gt;Each &lt;span class="caps"&gt;MXU&lt;/span&gt; has dedicated access to 8 &lt;span class="caps"&gt;GB&lt;/span&gt; of&amp;nbsp;memory.&lt;/li&gt;
&lt;li&gt;Integrated in four-chip modules (pictured), 420 TFLOPs peak&amp;nbsp;performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;HBM2&lt;/span&gt; integrated memory with access bandwidth of 1200 GBps&amp;nbsp;(assumed).&lt;/li&gt;
&lt;li&gt;PCIe-3 x8 assumed at 8&amp;nbsp;GBps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nextplatform.com/2018/05/10/tearing-apart-googles-tpu-3-0-ai-coprocessor/"&gt;NextPlatform Tearing apart google’s &lt;span class="caps"&gt;TPU&lt;/span&gt; 3.0 &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;coprocessor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="google-tpu-2" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt;&amp;nbsp;v2&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/google-tpu2_220x220.png" alt="TPU-2 board"&gt;&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;TPU&lt;/span&gt; v2 is designed for training and inference. It improves over the &lt;span class="caps"&gt;TPU&lt;/span&gt; v1
with floating point arithmetic and enhanced memory capacity and bandwidth with
&lt;span class="caps"&gt;HBM&lt;/span&gt; integrated&amp;nbsp;memory.&lt;/p&gt;
&lt;p&gt;General details (per&amp;nbsp;chip):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced May&amp;nbsp;2017.&lt;/li&gt;
&lt;li&gt;Likely to be&amp;nbsp;20nm.&lt;/li&gt;
&lt;li&gt;200-250W estimated &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;45 TFLOPs of&amp;nbsp;BFloat16.&lt;/li&gt;
&lt;li&gt;Two cores with scalar and matrix&amp;nbsp;units.&lt;/li&gt;
&lt;li&gt;Also supports &lt;span class="caps"&gt;FP32&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Integrated in four-chip modules (pictured), 180 TFLOPs peak&amp;nbsp;performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;128x128x32b systolic matrix unit (&lt;span class="caps"&gt;MXU&lt;/span&gt;) with BFloat16 multiplication and &lt;span class="caps"&gt;FP32&lt;/span&gt;&amp;nbsp;accumulation.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt; of dedicated &lt;span class="caps"&gt;HBM&lt;/span&gt; with access bandwidth of 300&amp;nbsp;GBps.&lt;/li&gt;
&lt;li&gt;Peak throughput of 22.5 TFLOPs of&amp;nbsp;BFloat16.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;HBM&lt;/span&gt; integrated memory at 600 GBps bandwidth&amp;nbsp;(assumed).&lt;/li&gt;
&lt;li&gt;PCIe-3 x8 (8&amp;nbsp;GBps).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nextplatform.com/2017/05/22/hood-googles-tpu2-machine-learning-clusters/"&gt;NextPlatform Under The Hood Of Google’s &lt;span class="caps"&gt;TPU2&lt;/span&gt; Machine Learning Clusters, May&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomshardware.com/news/tpu-v2-google-machine-learning,35370.html"&gt;Tom&amp;#8217;s Hardware: Hot Chips 2017: A Closer Look At Google&amp;#8217;s &lt;span class="caps"&gt;TPU&lt;/span&gt; v2, September&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="google-tpu-1" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Google &lt;span class="caps"&gt;TPU&lt;/span&gt;&amp;nbsp;v1&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/google-tpu1_220x220.png" alt="TPU-1 board"&gt;&lt;/p&gt;
&lt;p&gt;Google&amp;#8217;s first generation &lt;span class="caps"&gt;TPU&lt;/span&gt; was designed for inference only and supports only
integer arithmetic. It provides acceleration to a host &lt;span class="caps"&gt;CPU&lt;/span&gt; by being sent
instructions across PCIe-3, to perform matrix multiplications and apply
activation functions. This is a significant simplification which would have
saved much time in design and&amp;nbsp;verification.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced in&amp;nbsp;2016.&lt;/li&gt;
&lt;li&gt;331 mm&lt;sup&gt;2&lt;/sup&gt; die on 28nm&amp;nbsp;process.&lt;/li&gt;
&lt;li&gt;Clocked at 700 MHz and 28-40W &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;28 &lt;span class="caps"&gt;MB&lt;/span&gt; on-chip &lt;span class="caps"&gt;SRAM&lt;/span&gt; memory: 24 &lt;span class="caps"&gt;MB&lt;/span&gt; for activations and 4 &lt;span class="caps"&gt;MB&lt;/span&gt; for&amp;nbsp;accumulators.&lt;/li&gt;
&lt;li&gt;Proportions of the die area: 35% memory, 24% matrix multiply unit, 41%
  remaining area for&amp;nbsp;logic.&lt;/li&gt;
&lt;li&gt;256x256x8b systolic matrix multiply unit (64K&amp;nbsp;MACs/cycle).&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;INT8&lt;/span&gt; and &lt;span class="caps"&gt;INT16&lt;/span&gt; arithmetic (peak 92 and 23 TOPs/s&amp;nbsp;respectively).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;-2133 &lt;span class="caps"&gt;DRAM&lt;/span&gt; accessible via two ports at 34 &lt;span class="caps"&gt;GB&lt;/span&gt;/s.&lt;/li&gt;
&lt;li&gt;PCIe-3 x 16 (14&amp;nbsp;GBps).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Tensor_processing_unit"&gt;Wikipedia: Tensor Processing&amp;nbsp;Unit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/1704.04760"&gt;&lt;span class="caps"&gt;TPU&lt;/span&gt; v1 paper (In-Datacenter Performance Analysis of a Tensor Processing Unit), April&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="graphcore-c2-ipu" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Graphcore &lt;span class="caps"&gt;IPU&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/graphcore-ipu_220x220.png" alt="Graphcore IPU floorplan"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;DISCLAIMER&lt;/span&gt;&lt;/strong&gt;: I work at Graphcore, and all of the information given here is
lifted directly from the linked references&amp;nbsp;below.&lt;/p&gt;
&lt;p&gt;The Graphcore &lt;span class="caps"&gt;IPU&lt;/span&gt; architecture is highly parallel with a large collection of
simple processors with small memories, connected by a high-bandwidth all-to-all
&amp;#8216;exchange&amp;#8217; interconnect. The architecture operates under a bulk-synchronous
parallel (&lt;span class="caps"&gt;BSP&lt;/span&gt;) model, whereby execution of a program proceeds as a sequence of
compute and exchange phases. Synchronisation is used to ensure all processes
are ready to start exchange. The &lt;span class="caps"&gt;BSP&lt;/span&gt; model is a powerful programming
abstraction because it precludes concurrency hazards, and &lt;span class="caps"&gt;BSP&lt;/span&gt; execution allows
the compute and exchange phases to make full use of the chip&amp;#8217;s power resources.
Larger systems of &lt;span class="caps"&gt;IPU&lt;/span&gt; chips can be built by connecting the 10 inter-&lt;span class="caps"&gt;IPU&lt;/span&gt;&amp;nbsp;links.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;16 nm, 23.6 bn transistors, ~800mm&lt;sup&gt;2&lt;/sup&gt; die&amp;nbsp;size.&lt;/li&gt;
&lt;li&gt;1216 processor&amp;nbsp;tiles.&lt;/li&gt;
&lt;li&gt;125 TFLOPs peak &lt;span class="caps"&gt;FP16&lt;/span&gt; arithmetic with &lt;span class="caps"&gt;FP32&lt;/span&gt;&amp;nbsp;accumulation.&lt;/li&gt;
&lt;li&gt;300 &lt;span class="caps"&gt;MB&lt;/span&gt; total on-chip memory, distributed among processor cores, providing an
  aggregate access bandwidth of 45&amp;nbsp;TBps.&lt;/li&gt;
&lt;li&gt;All model state held on chip, there is no directly-attached &lt;span class="caps"&gt;DRAM&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;150 W &lt;span class="caps"&gt;TDP&lt;/span&gt; (300 W PCIe&amp;nbsp;card).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2x PCIe-4 host &lt;span class="caps"&gt;IO&lt;/span&gt;&amp;nbsp;links.&lt;/li&gt;
&lt;li&gt;10x inter-card &amp;#8216;&lt;span class="caps"&gt;IPU&lt;/span&gt;&amp;nbsp;links&amp;#8217;.&lt;/li&gt;
&lt;li&gt;Total of 384 GBps &lt;span class="caps"&gt;IO&lt;/span&gt;&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mixed-precision floating-point stochastic&amp;nbsp;arithmetic.&lt;/li&gt;
&lt;li&gt;Runs up to six program&amp;nbsp;threads.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.appg-ai.org/library/raais-2017-simon-knowles-co-founder-cto-graphcore/"&gt;&lt;span class="caps"&gt;RAAIS&lt;/span&gt; presentation, July&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cdn2.hubspot.net/hubfs/729091/NIPS2017/NIPS%2017%20-%20IPU.pdf?t=1526305355186"&gt;&lt;span class="caps"&gt;NIPS&lt;/span&gt; presentation, November&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cdn2.hubspot.net/hubfs/729091/assets/ScaledML%20Stanford%2024mar18%20SK.pdf"&gt;ScaledML presentation, March&amp;nbsp;2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eetimes.com/document.asp?doc_id=1334578#"&gt;EETimes: Graphcore &lt;span class="caps"&gt;CEO&lt;/span&gt; Touts &amp;#8216;Most Complex Processor&amp;#8217; Ever, April&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.servethehome.com/hands-on-with-a-graphcore-c2-ipu-pcie-card-at-dell-tech-world/"&gt;Serve the Home overview of the C2 card, June&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikichip.org/wiki/graphcore/microarchitectures/colossus"&gt;WikiChip: Colossus&amp;nbsp;microarchitecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="habana-gaudi" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Habana Labs&amp;nbsp;Gaudi&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/habana-gaudi_220x220.png" alt="Habana Gaudi board"&gt;&lt;/p&gt;
&lt;p&gt;Habana&amp;#8217;s Gaudi &lt;span class="caps"&gt;AI&lt;/span&gt; training processor shares similarities with contemporary
GPUs, particularly wide &lt;span class="caps"&gt;SIMD&lt;/span&gt; parallelism and &lt;span class="caps"&gt;HBM2&lt;/span&gt; memory. The chip integrates
ten 100G Ethernet links which support remote direct memory access (&lt;span class="caps"&gt;RDMA&lt;/span&gt;). This
&lt;span class="caps"&gt;IO&lt;/span&gt; capability allows large systems to be built with commodity networking
equipment, compared with Nvidia&amp;#8217;s NVLink or&amp;nbsp;OpenCAPI.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced June&amp;nbsp;2019.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 16 nm with CoWoS, assumed die size ~500mm&lt;sup&gt;2&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Heterogeneous architecture with:&lt;ul&gt;
&lt;li&gt;a &lt;span class="caps"&gt;GEMM&lt;/span&gt; operations&amp;nbsp;engine;&lt;/li&gt;
&lt;li&gt;8 Tensor Processing Cores&amp;nbsp;(TPCs);&lt;/li&gt;
&lt;li&gt;a shared &lt;span class="caps"&gt;SRAM&lt;/span&gt; memory (software managed and accessible via &lt;span class="caps"&gt;RDMA&lt;/span&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;200W &lt;span class="caps"&gt;TDP&lt;/span&gt; for PCIe card and 300W &lt;span class="caps"&gt;TDP&lt;/span&gt; for the mezzanine&amp;nbsp;card.&lt;/li&gt;
&lt;li&gt;Unknown total on-chip&amp;nbsp;memory.&lt;/li&gt;
&lt;li&gt;Explicit memory management between chips (no&amp;nbsp;coherency).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;TPC&lt;/span&gt;&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;VLIW&lt;/span&gt; &lt;span class="caps"&gt;SIMD&lt;/span&gt; parallelism and a local &lt;span class="caps"&gt;SRAM&lt;/span&gt;&amp;nbsp;memory.&lt;/li&gt;
&lt;li&gt;Mixed precision: &lt;span class="caps"&gt;FP32&lt;/span&gt;, &lt;span class="caps"&gt;BF16&lt;/span&gt;, plus integer formats (&lt;span class="caps"&gt;INT32&lt;/span&gt;, &lt;span class="caps"&gt;INT16&lt;/span&gt;, &lt;span class="caps"&gt;INT8&lt;/span&gt;, &lt;span class="caps"&gt;UINT32&lt;/span&gt;, &lt;span class="caps"&gt;UINT8&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Random number&amp;nbsp;generation.&lt;/li&gt;
&lt;li&gt;Transcendental functions: Sigmoid, Tanh, Gaussian error linear unit&amp;nbsp;(GeLU).&lt;/li&gt;
&lt;li&gt;Tensor addressing and strided&amp;nbsp;access.&lt;/li&gt;
&lt;li&gt;Unknown local memory per &lt;span class="caps"&gt;TPC&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4x &lt;span class="caps"&gt;HBM2&lt;/span&gt;-2000 &lt;span class="caps"&gt;DRAM&lt;/span&gt; stacks providing 32 &lt;span class="caps"&gt;GB&lt;/span&gt; at 1&amp;nbsp;TBps.&lt;/li&gt;
&lt;li&gt;10x 100GbE interfaces are integrated on-chip, supporting &lt;span class="caps"&gt;RDMA&lt;/span&gt; over Converged Ethernet (RoCE&amp;nbsp;v2).&lt;/li&gt;
&lt;li&gt;IOs are implemented with 20x 56 Gbps &lt;span class="caps"&gt;PAM4&lt;/span&gt; Tx/Rx SerDes and can also be configured as 20x 50 GbE. This allows up to 64 chips to be connected with non-blocking&amp;nbsp;throughput.&lt;/li&gt;
&lt;li&gt;PCIe-4 x16 host&amp;nbsp;interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nextplatform.com/2019/06/17/ai-chip-startup-releases-training-accelerator-to-challenge-gpus"&gt;The Next Platform: &lt;span class="caps"&gt;AI&lt;/span&gt; Chip Startup Releases Training Accelerator to Challenge GPUs, June&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/14760/hot-chips-31-live-blogs-habanas-approach-to-ai-scaling"&gt;AnandTech report from &lt;span class="caps"&gt;HC31&lt;/span&gt;, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://habana.ai/wp-content/uploads/2019/06/Habana-Gaudi-Training-Platform-whitepaper.pdf"&gt;Habana Labs Gaudi whitepaper, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="huawei-ascend" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Huawei Ascend&amp;nbsp;910&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/huawei-ascend_220x220.png" alt="Huawei Ascend floorplan"&gt;&lt;/p&gt;
&lt;p&gt;Huawei&amp;#8217;s Ascend also bears similarities to the latest GPUs with wide &lt;span class="caps"&gt;SIMD&lt;/span&gt;
arithmetic and a 3D matrix unit, comparable to Nvidia&amp;#8217;s Tensor Cores, a
(assumed) coherent 32 &lt;span class="caps"&gt;MB&lt;/span&gt; shared L2 on-chip cache. The chip includes
additional logic for 128 channel video decoding engines for H.264/265. In their
Hot Chips presentation, Huawei described overlapping the cube and vector
operations to obtain high efficiency and the challenge of the memory hierarchy
with ratio of bandwidth to throughput dropping by 10x for L1 cache (in the
core), 100x for L2 cache (shared between cores), and 2000x for external &lt;span class="caps"&gt;DRAM&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced August&amp;nbsp;2019.&lt;/li&gt;
&lt;li&gt;456 mm&lt;sup&gt;2&lt;/sup&gt; logic die on a 7+ nm &lt;span class="caps"&gt;EUV&lt;/span&gt;&amp;nbsp;process.&lt;/li&gt;
&lt;li&gt;Copackaged with four 96 mm&lt;sup&gt;2&lt;/sup&gt; &lt;span class="caps"&gt;HBM2&lt;/span&gt; stacks and &amp;#8216;Nimbus&amp;#8217; &lt;span class="caps"&gt;IO&lt;/span&gt; processor&amp;nbsp;chip.&lt;/li&gt;
&lt;li&gt;32 DaVinci&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;Peak 256 TFLOPs (32 x 4096 x 2) &lt;span class="caps"&gt;FP16&lt;/span&gt; performance, double that for &lt;span class="caps"&gt;INT8&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;32 &lt;span class="caps"&gt;MB&lt;/span&gt; shared on-chip &lt;span class="caps"&gt;SRAM&lt;/span&gt; (L2&amp;nbsp;cache).&lt;/li&gt;
&lt;li&gt;350W &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interconnect and &lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cores interconnected in a 6 x 4 2D mesh packet-switched network, providing
  128 GBps bidirectional bandwidth per&amp;nbsp;core.&lt;/li&gt;
&lt;li&gt;4 TBps access to L2&amp;nbsp;cache.&lt;/li&gt;
&lt;li&gt;1.2 TBps &lt;span class="caps"&gt;HBM2&lt;/span&gt; access&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;li&gt;3x 30 GBps inter-chip&amp;nbsp;IOs.&lt;/li&gt;
&lt;li&gt;2x 25 GBps RoCE networking&amp;nbsp;interfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each DaVinci&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3D 16x16x16 matrix multiply unit providing 4,096 &lt;span class="caps"&gt;FP16&lt;/span&gt; MACs and 8,192 &lt;span class="caps"&gt;INT8&lt;/span&gt;&amp;nbsp;MACs.&lt;/li&gt;
&lt;li&gt;2,048 bit &lt;span class="caps"&gt;SIMD&lt;/span&gt; vector operations for &lt;span class="caps"&gt;FP32&lt;/span&gt; (x64), &lt;span class="caps"&gt;FP16&lt;/span&gt; (x128) and &lt;span class="caps"&gt;INT8&lt;/span&gt;&amp;nbsp;(x256).&lt;/li&gt;
&lt;li&gt;Support for scalar&amp;nbsp;operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.servethehome.com/huawei-ascend-910-provides-a-nvidia-ai-training-alternative/"&gt;Serve the Home report from &lt;span class="caps"&gt;HC31&lt;/span&gt;, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/14756/hot-chips-live-blogs-huawei-da-vinci-architecture"&gt;AnandTech report from &lt;span class="caps"&gt;HC31&lt;/span&gt;, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="intel-nnp-t" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Intel &lt;span class="caps"&gt;NNP&lt;/span&gt;-T&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/intel-nnpt_220x220.png" alt="Intel NNP-T floorplan"&gt;&lt;/p&gt;
&lt;p&gt;This chip is Intel&amp;#8217;s second attempt at an accelerator for machine learning,
following the Xeon Phi. Like the &lt;a href="#habana-gaudi"&gt;Habana Gaudi chip&lt;/a&gt;, it
integrates a small number of wide vector cores, with &lt;span class="caps"&gt;HBM2&lt;/span&gt; integrated memory and
similar 100 Gbit &lt;span class="caps"&gt;IO&lt;/span&gt;&amp;nbsp;links.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;27 bn&amp;nbsp;transistors.&lt;/li&gt;
&lt;li&gt;688 mm&lt;sup&gt;2&lt;/sup&gt; die on &lt;span class="caps"&gt;TSMC&lt;/span&gt; &lt;span class="caps"&gt;16FF&lt;/span&gt;+ &lt;span class="caps"&gt;TSMC&lt;/span&gt; with&amp;nbsp;CoWoS.&lt;/li&gt;
&lt;li&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;HBM2&lt;/span&gt;-2400 in four 8 &lt;span class="caps"&gt;GB&lt;/span&gt; stacks integrated on a 1200 mm&lt;sup&gt;2&lt;/sup&gt; passive silicon&amp;nbsp;interposer.&lt;/li&gt;
&lt;li&gt;60 &lt;span class="caps"&gt;MB&lt;/span&gt; on-chip &lt;span class="caps"&gt;SRAM&lt;/span&gt; memory distributed among cores and &lt;span class="caps"&gt;ECC&lt;/span&gt;&amp;nbsp;protected.&lt;/li&gt;
&lt;li&gt;Up to 1.1 GHz core&amp;nbsp;clock.&lt;/li&gt;
&lt;li&gt;150-250W &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;24 Tensor Processing Cluster (&lt;span class="caps"&gt;TCP&lt;/span&gt;)&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;TPCs connected in a 2D mesh network topology.&lt;ul&gt;
&lt;li&gt;Separate networks for different types of data: control, memory and inter-chip&amp;nbsp;communication.&lt;/li&gt;
&lt;li&gt;Support for&amp;nbsp;multicast.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;119 TOPs peak&amp;nbsp;performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1.22 TBps &lt;span class="caps"&gt;HBM2&lt;/span&gt;&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;li&gt;64 lanes of SerDes with peak 3.58 Tbps aggregate bandwidth (28 Gbps each direction in each lane) for inter-chip&amp;nbsp;IOs.&lt;/li&gt;
&lt;li&gt;x16 PCIe-4 host interface (also supports &lt;span class="caps"&gt;OAM&lt;/span&gt;, Open&amp;nbsp;Compute).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;TPC&lt;/span&gt;&amp;nbsp;core:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2x 32x32 BFloat16 multiplier arrays supporting &lt;span class="caps"&gt;FMAC&lt;/span&gt; operation with &lt;span class="caps"&gt;FP32&lt;/span&gt;&amp;nbsp;accumulation.&lt;/li&gt;
&lt;li&gt;Vector &lt;span class="caps"&gt;FP32&lt;/span&gt; and BFloat16 operations.&lt;ul&gt;
&lt;li&gt;Support for transcendental functions, random number generation, reductions and&amp;nbsp;accumulations.&lt;/li&gt;
&lt;li&gt;Programmable &lt;span class="caps"&gt;FP32&lt;/span&gt; lookup&amp;nbsp;tables.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A separate convolution engine for non-&lt;span class="caps"&gt;MAC&lt;/span&gt;&amp;nbsp;compute.&lt;/li&gt;
&lt;li&gt;2.5 &lt;span class="caps"&gt;MB&lt;/span&gt; two-port private memory with 1.4 TBps read/write&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;li&gt;Memory supports tensor transpose&amp;nbsp;operation.&lt;/li&gt;
&lt;li&gt;Communication interface supporting dynamic packet routing on the mesh
  (virtual channel, reliable&amp;nbsp;transmission).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Scaling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Up to 1024 chips with direct interconnections, providing the same
  distributed-memory programming model (explicit memory management,
  synchronisation primitives, message&amp;nbsp;passing).&lt;/li&gt;
&lt;li&gt;Scaling demonstrated up to 32 chips connected in a ring&amp;nbsp;topology.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fuse.wikichip.org/news/2219/intels-spring-crest-nnp-l-initial-details/"&gt;WikiChip: Intel’s Spring Crest &lt;span class="caps"&gt;NNP&lt;/span&gt;-L Initial Details, April&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tomshardware.com/news/intel-nervana-nueral-net-processor-nnt-p,40185.html"&gt;Tom&amp;#8217;s Hardware, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://newsroom.intel.com/wp-content/uploads/sites/11/2019/08/Intel-Nervana-NNP-T-HotChips-presentation.pdf"&gt;Intel&amp;#8217;s &lt;span class="caps"&gt;HC31&lt;/span&gt; presentation (&lt;span class="caps"&gt;PDF&lt;/span&gt;), August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/14757/hot-chips-live-blogs-intel-spring-crest-nnpt-on-16nm-tsmc"&gt;AnandTech report from &lt;span class="caps"&gt;HC31&lt;/span&gt;, August&amp;nbsp;2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="nvidia-volta" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Nvidia&amp;nbsp;Volta&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/nvidia-volta_220x220.png" alt="Nvidia Volta board"&gt;&lt;/p&gt;
&lt;p&gt;Volta introduces Tensor Cores, &lt;span class="caps"&gt;HBM2&lt;/span&gt; and NVLink 2.0, from the &lt;a href="https://en.wikipedia.org/wiki/Pascal_(microarchitecture)"&gt;Pascal
architecture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced May&amp;nbsp;2017.&lt;/li&gt;
&lt;li&gt;815 mm&lt;sup&gt;2&lt;/sup&gt; on &lt;span class="caps"&gt;TSMC&lt;/span&gt; 12nm &lt;span class="caps"&gt;FFN&lt;/span&gt;, 21.1 bn&amp;nbsp;transistors.&lt;/li&gt;
&lt;li&gt;300 W &lt;span class="caps"&gt;TDP&lt;/span&gt; (&lt;span class="caps"&gt;SXM2&lt;/span&gt; form&amp;nbsp;factor).&lt;/li&gt;
&lt;li&gt;6 &lt;span class="caps"&gt;MB&lt;/span&gt; L2&amp;nbsp;cache.&lt;/li&gt;
&lt;li&gt;84 SMs, each containing: 64 &lt;span class="caps"&gt;FP32&lt;/span&gt; &lt;span class="caps"&gt;CUDA&lt;/span&gt; cores, 32 &lt;span class="caps"&gt;FP64&lt;/span&gt; &lt;span class="caps"&gt;CUDA&lt;/span&gt; cores and 8 Tensor
  Cores (5376 &lt;span class="caps"&gt;FP32&lt;/span&gt; cores, 2688 &lt;span class="caps"&gt;FP64&lt;/span&gt; cores, 672&amp;nbsp;TCs).&lt;/li&gt;
&lt;li&gt;Tensor Cores perform 4x4 &lt;span class="caps"&gt;FMA&lt;/span&gt;, achieving 64 &lt;span class="caps"&gt;FMA&lt;/span&gt; ops/cycle, and 128&amp;nbsp;FLOPs.&lt;/li&gt;
&lt;li&gt;128 &lt;span class="caps"&gt;KB&lt;/span&gt; L1 data cache/shared memory and four 16K 32-bit registers per &lt;span class="caps"&gt;SM&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;HBM2&lt;/span&gt; &lt;span class="caps"&gt;DRAM&lt;/span&gt;, at 900 GBps&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;li&gt;NVLink 2.0 at 300&amp;nbsp;GBps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Volta_(microarchitecture)"&gt;Wikipedia: Volta&amp;nbsp;(microarchitecture)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdf"&gt;Volta architecture&amp;nbsp;whitepaper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://images.nvidia.com/content/technologies/volta/pdf/tesla-volta-v100-datasheet-letter-fnl-web.pdf"&gt;Nvidia Tesla V100&amp;nbsp;datasheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/11367/nvidia-volta-unveiled-gv100-gpu-and-tesla-v100-accelerator-announced"&gt;AnandTech - &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Volta Unveiled: &lt;span class="caps"&gt;GV100&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt; and Tesla V100 Accelerator Announced, May&amp;nbsp;2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="nvidia-turing" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Nvidia&amp;nbsp;Turing&lt;/h2&gt;
&lt;p&gt;&lt;img class="float-right" src="thumbs/nvidia-turing_220x220.png" alt="Nvidia Turing die shot"&gt;&lt;/p&gt;
&lt;p&gt;Turing is an architectural revision of Volta, manufactured on the same 16 nm
process, but with fewer &lt;span class="caps"&gt;CUDA&lt;/span&gt; and Tensor cores. It consequently has a smaller
die size and lower power envelope. Apart from &lt;span class="caps"&gt;ML&lt;/span&gt; tasks, it is designed to
perform real-time ray tracing, for which it also used the Tensor&amp;nbsp;Cores.&lt;/p&gt;
&lt;p&gt;General&amp;nbsp;details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announced September&amp;nbsp;2018.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;TSMC&lt;/span&gt; 12nm &lt;span class="caps"&gt;FFN&lt;/span&gt;, 754 mm&lt;sup&gt;2&lt;/sup&gt; die, 18.6 bn&amp;nbsp;transistors.&lt;/li&gt;
&lt;li&gt;260 W &lt;span class="caps"&gt;TDP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;72 SMs, each containing: 64 &lt;span class="caps"&gt;FP32&lt;/span&gt; cores, and 64 &lt;span class="caps"&gt;INT32&lt;/span&gt; cores, 8 Tensor cores
  (4608 &lt;span class="caps"&gt;FP32&lt;/span&gt; cores, 4608 &lt;span class="caps"&gt;INT32&lt;/span&gt; cores and 576&amp;nbsp;TCs).&lt;/li&gt;
&lt;li&gt;Peak performance with boost clock: 16.3 TFLOPs &lt;span class="caps"&gt;FP32&lt;/span&gt;, 130.5 TFLOPs &lt;span class="caps"&gt;FP16&lt;/span&gt;, 261 TFLOPs &lt;span class="caps"&gt;INT8&lt;/span&gt;, 522 TFLOPs &lt;span class="caps"&gt;INT4&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;24.5 &lt;span class="caps"&gt;MB&lt;/span&gt; on-chip memory between 6 &lt;span class="caps"&gt;MB&lt;/span&gt; L2 cache and 256 &lt;span class="caps"&gt;KB&lt;/span&gt; &lt;span class="caps"&gt;SM&lt;/span&gt; register&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;1455 MHz base&amp;nbsp;clock.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;12x 32-bit &lt;span class="caps"&gt;GDDR6&lt;/span&gt; memory providing 672 GBps aggregate&amp;nbsp;bandwidth.&lt;/li&gt;
&lt;li&gt;2x NVLink x8 links, each providing up to 26 GBps&amp;nbsp;bidirectional.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Turing_(microarchitecture)"&gt;Wikipedia: Turing&amp;nbsp;(mircoarchitecture)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anandtech.com/show/13214/nvidia-reveals-next-gen-turing-gpu-architecture"&gt;AnandTech: &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Reveals Next-Gen Turing &lt;span class="caps"&gt;GPU&lt;/span&gt; Architecture, August&amp;nbsp;2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nvidia.com/content/dam/en-zz/Solutions/design-visualization/technologies/turing-architecture/NVIDIA-Turing-Architecture-Whitepaper.pdf"&gt;Nvidia Turing &lt;span class="caps"&gt;GPU&lt;/span&gt; architecture whitepaper (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/basicmi/AI-Chip"&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; Chip - A list of ICs and IPs for &lt;span class="caps"&gt;AI&lt;/span&gt;, Machine Learning and Deep Learning&amp;nbsp;(GitHub)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mlperf.org/training-results-0-6/"&gt;MLPerf Training v0.6 results (&lt;span class="caps"&gt;TPU&lt;/span&gt; v3 and Volta&amp;nbsp;only)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See
&lt;a href="https://news.ycombinator.com/item?id=21178609"&gt;this thread on Hacker News&lt;/a&gt;
for discussion of this&amp;nbsp;note.&lt;/p&gt;
&lt;!--
More:
- SambaNova (no sign of silicon)
- Wave Computing
- Cambricon (Huwawei NPU, Alibaba)
- Baidu XPU
- Cornami
- Fijitsu DPU
- IBM TrueNorth
- ThinCI
- Vathys
- Groq (no details yet)
Inference only:
- Qualcomm Cloud AI 100 chip
- Tesla Neural Processor
- FlexLogic
- Alibaba Hanguang 800 (12nm 17bn transistors)
- T-Head XuanTie 910
Brain inspired:
- Mythic (analoge computing in NAND memory, works on 8 bit values only)
- Applied Brain Research (ABR) - Nengo "brain" chip
- Rain Neuromophic
- GrAI (pronounced "gray") Matter Labs has a fully digital neuromorphic processor
--&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="machine-intelligence"/><category term="computer-architecture"/></entry><entry><title>Testing silicon logic with scan structures</title><link href="https://jameswhanlon.com/testing-silicon-logic-with-scan-structures.html" rel="alternate"/><published>2019-04-18T00:00:00+02:00</published><updated>2019-04-18T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2019-04-18:/testing-silicon-logic-with-scan-structures.html</id><summary type="html">&lt;p&gt;A description of how digital circuits are modified to allow scan
testing to be&amp;nbsp;performed.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Design for test (&lt;span class="caps"&gt;DFT&lt;/span&gt;) is a methodology for silicon integrated-circuit chips to
enable devices to be tested during and after manufacture. Such testability
permits the detection of faults due to problems in the manufacturing processes
that would adversely affect the functional behaviour of the device. This note
explains the concepts of a particular &lt;span class="caps"&gt;DFT&lt;/span&gt; methodology called &lt;em&gt;scan test&lt;/em&gt;, which
modifies the logic of a design in such a way that the functional behaviour is
preserved but classes of faults become&amp;nbsp;detectable.&lt;/p&gt;
&lt;h2&gt;Scan&amp;nbsp;chains&lt;/h2&gt;
&lt;p&gt;A chip can be viewed as a set of input ports that feed into a series of
combinatorial and sequential cells, and arrive at a set of output ports. To
test that the function of the chip is correct, it would suffice to check that a
particular output is generated for a particular input, or sequence of inputs
and outputs. However, if the intervening logic contains sequential elements, is
computationally difficult to setup inputs each clock cycle to observe desired
values on all outputs. Doing so requires sequencing of state transitions
through the logic, but the size of the state space grows exponentially with the
number of&amp;nbsp;states.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/chip.png"&gt;
  &lt;figcaption&gt;
    Conceptually, a silicon chip is a set of input ports driving logic with
sequential elements, in turn driving output ports.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;To avoid an intractable state space, the design is changed so that inputs and
observable outputs are separated only by combinatorial logic. This is done by
adding new controllable &lt;strong&gt;primary inputs&lt;/strong&gt; and &lt;strong&gt;observable outputs&lt;/strong&gt;, called
&lt;strong&gt;scan chains&lt;/strong&gt;. A scan chain adds three ports to the chip: a scan chain&amp;nbsp;input,
&lt;code&gt;scan_in&lt;/code&gt;, a scan chain&amp;nbsp;output &lt;code&gt;scan_out&lt;/code&gt; and an&amp;nbsp;enable &lt;code&gt;scan_enable&lt;/code&gt;.
All registers are converted by adding a multiplexer on the D pin, with one
input connected to the data signal. The first scan-chain register has it’s
other multiplexer input connected&amp;nbsp;to &lt;code&gt;scan_in&lt;/code&gt;. Subsequent scan registers
take their other multiplexer inputs from the output of the previous register in
the chain. The final register in the chain&amp;nbsp;drives &lt;code&gt;scan_out&lt;/code&gt; from it’s D pin.
All multiplexers are controlled&amp;nbsp;by &lt;code&gt;scan_enable&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/scan-flop.png"&gt;
  &lt;figcaption&gt;
    A standard flip flop (left) and a scanned flip flop with scan-in and
scan-enable inputs (right).
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/scan-chains.png"&gt;
  &lt;figcaption&gt;
    Scan chain topology providing a set of controllable primary inputs and a set of observable outputs.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;When &lt;code&gt;scan_enable&lt;/code&gt; is pulled high, and the clock pulsed, data is shifted into
each register in the chain. Each bit of a chain of N registers can be set in N
clock cycles. When pulled low, the chip is in normal functional mode. These
inputs allow a simple test procedure to be&amp;nbsp;implemented:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;scan_enable&lt;/code&gt; high (scan&amp;nbsp;mode).&lt;/li&gt;
&lt;li&gt;Shift in N bits of input&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;scan_enable&lt;/code&gt; low (functional&amp;nbsp;mode).&lt;/li&gt;
&lt;li&gt;Tick the clock once to propagate input vector though combinatorial logic into&amp;nbsp;outputs.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;scan_enable&lt;/code&gt; high (scan&amp;nbsp;mode).&lt;/li&gt;
&lt;li&gt;Shift out N bits of output&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;Check that the output data equals the input data transformed by the same logic&amp;nbsp;function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since typical tests will contain large numbers of patterns, the time to test
one pattern is critical. It is determined by the length of the chain, to shift
in and out data. To reduce test time, additional scan chains can be introduced
to allow shifting to be performed in parallel. Each chain&amp;nbsp;adds &lt;code&gt;scan_in&lt;/code&gt; and
&lt;code&gt;scan_out&lt;/code&gt; ports to the chip. The number of scan chains is chosen to trade
off the physical requirements of the additional ports and routing with test
time and coverage. To avoid many additional ports at the top level, a set of
parallel scan chains can be driven by &lt;span class="caps"&gt;DFT&lt;/span&gt; logic that supplies compressed
patterns to the inputs and compresses results from the&amp;nbsp;outputs.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/parallel-scan-chains.png"&gt;
  &lt;figcaption&gt;
    Parallel scan chains to reduce test time.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2&gt;Wrapper&amp;nbsp;chains&lt;/h2&gt;
&lt;p&gt;Typically, a chip is too complex to test with a single set of scan chains. Even
with only combinatorial logic between primary inputs and observable outputs, it
becomes computationally difficult to analyse to generate patterns that can
effectively exercise it to achieve good coverage and fault isolation. Instead,
a chip is divided into sub components, each of which is amenable to testing (an
approach known as hierarchical &lt;span class="caps"&gt;DFT&lt;/span&gt;). The components are referred to as &lt;strong&gt;test
cores&lt;/strong&gt; and typically naturally correspond to functional blocks of the chip&amp;nbsp;design.&lt;/p&gt;
&lt;p&gt;It is necessary for a test core to be isolated from the rest of the design. At
a chip-level primary inputs are controllable in that their values are always
known. However, the values of an input to a test core are unknown and likely to
be Xs. If X values propagate into a test core, coverage can be reduced, or
worse, the testing methodology may be invalidated altogether. Isolation is
achieved with &lt;strong&gt;wrapper chains&lt;/strong&gt; that are inserted between the &lt;span class="caps"&gt;IO&lt;/span&gt; ports and the
core logic of the design. A bypass multiplexer is inserted on the output of the
wrapper scan register to control whether the input or output is used or driven
respectively. If the input or output is directly connected to a register, then
a bypass is not&amp;nbsp;necessary.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/wrapper-flop.png"&gt;
  &lt;figcaption&gt;
    Wrapper flops inserted on input and output ports.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/test-core.png"&gt;
  &lt;figcaption&gt;
    A test core isolated with input and output wrapper chains. One or more
additional scan chains may be connected to sequential elements of the core logic.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;An &lt;strong&gt;input wrapper chain&lt;/strong&gt; is the chain of registers that capture the primary
inputs to the core, with their D inputs corresponding to each input of the test
core. Some inputs may be omitted from the wrapper chain, such as clock, reset
and test-related signals. Input wrapper chains are different to regular scan
chains only in the way that&amp;nbsp;their &lt;code&gt;scan_enable&lt;/code&gt; is controlled. During test mode,
the scan enable of the input wrapper is held high when the&amp;nbsp;regular &lt;code&gt;scan_enable&lt;/code&gt;
is low and all other registers are in functional mode. The effect of this is
that the input wrapper chain continues to shift in known values, rather than Xs
from outside of the test core. When the input wrapper registers are not shared
with any other test core, the captured values can be shifted out with the other
test pattern results to ensure all of the registers are functioning&amp;nbsp;correctly.&lt;/p&gt;
&lt;p&gt;An &lt;strong&gt;output wrapper chain&lt;/strong&gt; behaves exactly as an internal scan chain during test
mode. However, when they are shared with an adjacent test core,&amp;nbsp;their
&lt;code&gt;scan_enable&lt;/code&gt; is controlled differently since they will function as an input
wrapper chain for that core, with the behaviour described&amp;nbsp;above.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/adjacent-test-cores.png"&gt;
  &lt;figcaption&gt;
    Test core B shares core B&amp;#8217;s output wrapper chain, using it as an input wrapper chain in test mode.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2&gt;X&amp;nbsp;bounding&lt;/h2&gt;
&lt;p&gt;It may not be possible to add all registers into the scan chains for a design.
In this case, to prevent Xs from propagating into the logic during test, all
sources of Xs must be masked with known values. This is done by inserting a
multiplexer to take the Q pin as input, with the other input as an alternative
known value, typically from a register on a scan chain. The multiplexer is
controlled by&amp;nbsp;an &lt;code&gt;xbnd_enable&lt;/code&gt; signal, which when set high will prevent X
propagation during test mode, and otherwise maintains the functional behaviour
of the&amp;nbsp;circuit.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="https://jwh.ams3.digitaloceanspaces.com/homepage/DFT/xbnd-flop.png"&gt;
  &lt;figcaption&gt;
    A X-source flop with bypass multiplexing of a known value.
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2&gt;References / further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Design_for_testing"&gt;Design for testing&amp;nbsp;(Wikipedia)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vlsitutorials.com/dft-scan-and-atpg/"&gt;&lt;span class="caps"&gt;DFT&lt;/span&gt;, Scan and &lt;span class="caps"&gt;ATPG&lt;/span&gt; (&lt;span class="caps"&gt;VLSI&lt;/span&gt;&amp;nbsp;Tutorials)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Automatic_test_pattern_generation"&gt;Automatic test pattern generation&amp;nbsp;(Wikipedia)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://web.stanford.edu/class/archive/ee/ee371/ee371.1066/lectures.html"&gt;Stanford &lt;span class="caps"&gt;EE371&lt;/span&gt;, lecture 14: Design for&amp;nbsp;testability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;Thanks to Evan Griffiths for his detailed explanations of &lt;span class="caps"&gt;DFT&lt;/span&gt; insertion, upon
which this note is&amp;nbsp;based.&lt;/p&gt;</content><category term="Computing and Silicon"/><category term="microelectronics"/></entry><entry><title>RGB lightbox stacks</title><link href="https://jameswhanlon.com/rgb-lightbox-stacks.html" rel="alternate"/><published>2018-12-31T00:00:00+01:00</published><updated>2018-12-31T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-12-31:/rgb-lightbox-stacks.html</id><summary type="html">&lt;p&gt;Experimental lighting using high-power LEDs in generous volumes and
behind translucent acrylic plastic to create big blocks of&amp;nbsp;colour.&lt;/p&gt;</summary><content type="html">&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/completed-boxes-3.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/completed-boxes-3_800x800.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The &amp;#8216;&lt;span class="caps"&gt;RGB&lt;/span&gt; stacks&amp;#8217; lightboxes are an experiment with using high-power LEDs,
generous volumes and translucent acrylic plastic to create big blocks of
colour. They are constructed from 12 mm birch ply and each pixel measures 300 x
300 (outer dimensions). They are built as three columns of three pixels to
allow them to be arranged in a square, a line, or in different locations. This
note records some of the details of their construction. Although they are now
functional, refinement of their controls and modulation continues to be a work
in progress. This note records some of the details of how they were built (I
will it updated with any new&amp;nbsp;developments).&lt;/p&gt;
&lt;p&gt;The project was inspired by a similar light box project (that unfortunately I
can no longer find on the internet), but which was a single 3 x 3 cabinet
achieving a similar block-colour effect. My motivation was to build something
similar but that could also be used as subtle/ambient lighting, making use of
the amazing colours and ability to accurately modulate LEDs to create smooth
transitions between rich colours and interesting&amp;nbsp;combinations.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/colour-experiment-blue.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/colour-experiment-blue_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/colour-experiment-red.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/colour-experiment-red_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;An early experiment to see how the &lt;span class="caps"&gt;LED&lt;/span&gt; light diffuses through the acrylic in a plywood volume.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Construction of the stacks was straightforward: all panel dimensions are
multiples of 300 and all joints biscuited and glued to avoid any visible
fixings. (I unfortunately don&amp;#8217;t have any pictures of the construction of the&amp;nbsp;stacks.)&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/bead-detail-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bead-detail-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/bead-detail-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/bead-detail-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/tape.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/tape_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Detail of the lip added to seat the acrylic panels and the narrow double-sided tape to fix them in place.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The acrylic panels were cut to fit the inner box dimensions exactly, but with
small variations in the dimensions of the boxes. Getting them all to fit was a
long process of sanding down each one to fit a particular opening. A secure fit
of the panels was achieved with tight tolerances and narrow double-sided sticky
tape (pictured above&amp;nbsp;right).&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/completed-boxes-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/completed-boxes-1_600x600.jpg" alt="The boxes with all acrylic panels in place."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The boxes with all acrylic panels in place.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Pairs of white and &lt;span class="caps"&gt;RGB&lt;/span&gt; LEDs were mounted on aluminium bar in each pixel. The
&lt;span class="caps"&gt;LED&lt;/span&gt; were fixed in place with small bolts. I made small plastic washers to avoid
shorting any of the contacts with the bolt heads. Although the aluminium bar
probably provides a sufficient heat sink, I added additional heatsink blocks on
the rear side, fixed with thermal glue (these were cut up from larger &lt;span class="caps"&gt;IC&lt;/span&gt;
heatsinks). All of the &lt;span class="caps"&gt;LED&lt;/span&gt; wiring was conveniently done with &lt;span class="caps"&gt;CAT6&lt;/span&gt; cable, using
all of the eight cores to wire the four channels. Each channel draws about
1 W at 5 V (200 mA), which is within the specification of the &lt;span class="caps"&gt;CAT6&lt;/span&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/led-bar-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/led-bar-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/led-heatsinks.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/led-heatsinks_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The system used to mount the LEDs in the middle of each box.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/skeleton-boxes-with-leds.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/skeleton-boxes-with-leds_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/boxes-in-workshop.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/boxes-in-workshop_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The boxes with all of the LEDs and their cabling installed.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Each box has a rear plug panel. The central box acts as a master and has
connections for power, Ethernet, and provides serial data and power to the
other outer&amp;nbsp;boxes.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/power-supply.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/power-supply_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/plug-panel.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/plug-panel_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/slave-box-control-boards.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/slave-box-control-boards_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The master and slave plug panels for each stack.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The inter-box wiring uses 5-pin &lt;span class="caps"&gt;XLR&lt;/span&gt; sockets, to carry power, ground and the
differential pair for the serial signal. The wires were made with a dual-core
power wire (sufficient to carry the required power at 5V) with a another
dual-core wire for the serial, wrapped in a heatshrink&amp;nbsp;coat.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/cables.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/cables_600x600.jpg" alt="Custom cabling to connect the left and right hand boxes, containing a dual-core wire for power and two CAT-6 cores for serial data."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Custom cabling to connect the left and right hand boxes, containing a dual-core wire for power and two &lt;span class="caps"&gt;CAT&lt;/span&gt;-6 cores for serial data.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The electronics for the &lt;span class="caps"&gt;LED&lt;/span&gt; drivers is described in a &lt;a href="https://jameswhanlon.com/three-channel-high-power-led-driver.html"&gt;separate
note&lt;/a&gt;. Each of the &lt;span class="caps"&gt;LED&lt;/span&gt; driver boards has three
outputs, so four boards are required to drive a single stack. The Raspberry Pi
microcontroller is used to control all the pixels, and does so with a dual-wire
&lt;span class="caps"&gt;RS&lt;/span&gt;-485 serial bus. This bus connects each of the driver boards in series, and
the outer boxes are wired in parallel. Despite some concerns about this
topology from notes on the &lt;span class="caps"&gt;MAX&lt;/span&gt;-485 driver &lt;span class="caps"&gt;IC&lt;/span&gt; datasheet and that I didn&amp;#8217;t use
terminating resistors, the arrangement performs&amp;nbsp;fine.&lt;/p&gt;
&lt;p&gt;So that I could easily access the electronics, I integrated the drivers and
their wiring on a plywood board that sits in the base of a stack. The master
stack has the power supply, taking mains voltage and providing 5V up to 60W
(12A) for the three stacks. See the table below for calculated power of the
LEDs only. Note that the power supply does not output enough power do drive
the boxes comfortably (80W would be more&amp;nbsp;comfortable).&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Channel&lt;/th&gt;
      &lt;th scope="col"&gt;Voltage (V)&lt;/th&gt;
      &lt;th scope="col"&gt;Current (A)&lt;/th&gt;
      &lt;th scope="col"&gt;&lt;span class="caps"&gt;LED&lt;/span&gt; power (W)&lt;/th&gt;
      &lt;th scope="col"&gt;Driver efficiency&lt;/th&gt;
      &lt;th scope="col"&gt;Driver power (W)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Red&lt;/td&gt;
      &lt;td&gt;2.4&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;0.72&lt;/td&gt;
      &lt;td&gt;0.48&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Green&lt;/td&gt;
      &lt;td&gt;3.4&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;1.02&lt;/td&gt;
      &lt;td&gt;0.68&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Blue&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;1.05&lt;/td&gt;
      &lt;td&gt;0.7&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;White&lt;/td&gt;
      &lt;td&gt;3.2&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;0.96&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total (per pixel)&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;3.75&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total (per stack)&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;11.25&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;18&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;33.75&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;54&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;To check the above power numbers I performed some measurments with a clamp
meter of the central&amp;nbsp;stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With all LEDs off, the quiesence current is 360 mA at 5 V, dissipating 1.8&amp;nbsp;W.&lt;/li&gt;
&lt;li&gt;With all LEDs on at full intensity, the current is 4.75 A at 5 V, dissipating
  23.75&amp;nbsp;W.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These numbers are slightly higher than expected, due to the &lt;span class="caps"&gt;LED&lt;/span&gt; driver current
ranging between 0.357 mA (blue) and 0.370 mA&amp;nbsp;(green).&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/control-board-and-psu.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/control-board-and-psu_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/control-board-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/control-board-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/one-stack-test-with-board.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/one-stack-test-with-board_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Integration of the electronics into the master stack (similar for the outer stacks).&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The back panels fasten with M8 bolts into&amp;nbsp;T-nuts.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/back-panels.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-panels_600x600.jpg" alt="Details of the back plates, fastened by M8 Allen key bolts."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Details of the back plates, fastened by M8 Allen key bolts.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/completed-boxes-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/completed-boxes-2_600x600.jpg" alt="The boxes in a complete state"&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The boxes in a complete state&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;#8217;s hard to capture the quality of the effect of the light boxes on camera.
The images below are two early tests: left just using a lamp in one of the
pixels, right with no blending of the &lt;span class="caps"&gt;RGB&lt;/span&gt;&amp;nbsp;channels.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/one-cell-illuminated.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/one-cell-illuminated_600x600.jpg" alt="Seeing the effect of the acrylic diffusion with just a lamp in one of the cells."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Seeing the effect of the acrylic diffusion with just a lamp in one of the cells.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/RGB-stacks/rgb-test.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/rgb-test_600x600.jpg" alt="The first RGB test of a stack."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The first &lt;span class="caps"&gt;RGB&lt;/span&gt; test of a stack.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The behaviour of the boxes is determined by the &lt;span class="caps"&gt;PIC&lt;/span&gt; programs and the Raspberry
Pi. Since changes to the &lt;span class="caps"&gt;PIC&lt;/span&gt; program requires each of the boards to be
programmed individually and for each program to be compiled with a unique
identifier, this is not an easy way to experiment with modulating schemes.
Instead, each &lt;span class="caps"&gt;PIC&lt;/span&gt; is programmed only to change the output intensity, and
experimentation can be done using Python on the Raspberry Pi over &lt;span class="caps"&gt;SSH&lt;/span&gt;. In these
scheme, updates are sent to the &lt;span class="caps"&gt;LED&lt;/span&gt; drivers synchronously, as a frame. At
115,200 bps baud rate over &lt;span class="caps"&gt;RS485&lt;/span&gt;, this is sufficient to deliver up to 389
updates per second. In practice there are overheads that will reduce this. If,
for smooth graduations between colours the frame rate was not adequate, an
optimisation could be to expand the capability of the &lt;span class="caps"&gt;PIC&lt;/span&gt; driver code to
perform more complex actions like sweeps over intensity ranges, thereby
reducing the number of updates&amp;nbsp;required.&lt;/p&gt;
&lt;p&gt;As I mentioned, these boxes are not yet complete. To finish them, I want to add
a button panel to switch them on off and control the lighting&amp;nbsp;patterns.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/PIC12F1572-pwm"&gt;&lt;span class="caps"&gt;PIC12F1572&lt;/span&gt; &lt;span class="caps"&gt;PWM&lt;/span&gt;&amp;nbsp;example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/PIC12F1572-uart"&gt;&lt;span class="caps"&gt;PIC12F1572&lt;/span&gt; &lt;span class="caps"&gt;UART&lt;/span&gt;&amp;nbsp;example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Physical Projects"/><category term="lighting"/><category term="electronics"/></entry><entry><title>Three-channel high-power LED driver</title><link href="https://jameswhanlon.com/three-channel-high-power-led-driver.html" rel="alternate"/><published>2018-12-30T00:00:00+01:00</published><updated>2018-12-30T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-12-30:/three-channel-high-power-led-driver.html</id><summary type="html">&lt;p&gt;An &lt;span class="caps"&gt;LED&lt;/span&gt; driver module controlled by a &lt;span class="caps"&gt;PIC12F1572&lt;/span&gt; and with &lt;span class="caps"&gt;CAT4101&lt;/span&gt;
drivers, deployable in an array via a &lt;span class="caps"&gt;RS485&lt;/span&gt;&amp;nbsp;interface.&lt;/p&gt;</summary><content type="html">&lt;div class="float-right"&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/board-layers.png" class="glightbox" data-gallery="led-driver"&gt;
  &lt;img class="thumbnail rounded" src="thumbs/board-layers_400x400.png" alt="Board silk screen"&gt;
&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;This note describes an &lt;span class="caps"&gt;LED&lt;/span&gt; driver I designed for a lighting project. I decided
on a custom solution because I couldn&amp;#8217;t find any suitable boards available to
buy at a reasonable price. The intended application (which I will describe in
another note) requires 12 high-power (~1W) LEDs to be driven individually a 3 by 3
grid measuring approximately 1 metre square, with each of the nine cell
containing a red, green, blue and white &lt;span class="caps"&gt;LED&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I embarked on this project without any experience of designing PCBs, and with
relatively little knowledge of electronics, so it was a steep but fantastic
learning experience. I wanted to record some of the details of this project for
others who may find them useful, as I did with some of the resources I&amp;#8217;ve
linked to at the end. All of the &lt;span class="caps"&gt;PCB&lt;/span&gt; design files and processor firmware are
&lt;a href="https://github.com/jameshanlon/3C-HP-LED-driver"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Design&lt;/h1&gt;
&lt;p&gt;The board is designed around the following main &lt;span class="caps"&gt;IC&lt;/span&gt;&amp;nbsp;components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Microchip &lt;span class="caps"&gt;PIC12F1572&lt;/span&gt; for &lt;span class="caps"&gt;PWM&lt;/span&gt; &lt;span class="caps"&gt;LED&lt;/span&gt; control and serial communication. This was
  the simplest &lt;span class="caps"&gt;PIC&lt;/span&gt; I could find that had multiple &lt;span class="caps"&gt;PWM&lt;/span&gt; outputs and &lt;span class="caps"&gt;UART&lt;/span&gt; serial
communication capability. It&amp;#8217;s an 8-bit device with 16-bit PWMs and 3.5 KBs of
program&amp;nbsp;memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Maxim &lt;span class="caps"&gt;MAX485&lt;/span&gt; for communication to multiple of these boards. This &lt;span class="caps"&gt;IC&lt;/span&gt; provides
  half-duplex communication over a 2-wire differential pair using the &lt;span class="caps"&gt;RS485&lt;/span&gt;
protocol, allowing communication over long distances. Importantly it supports
multiple drops, so a number of boards can be wired together with a bus. I chose
this as it is very simple to integrate, with no additional components required,
compared to the capacitors necessary for the &lt;span class="caps"&gt;MAX232&lt;/span&gt;. Talking to the &lt;span class="caps"&gt;PIC&lt;/span&gt;, this
can support a baud rate of 115,200&amp;nbsp;bps.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;ON&lt;/span&gt; Semiconductor &lt;span class="caps"&gt;CAT4101&lt;/span&gt; for driving LEDs with a constant-current up to 1A
with &lt;span class="caps"&gt;PWM&lt;/span&gt; control. Because the temperature fluctuations of high-power LEDs
affects their forward voltage, driving them with a constant current is
important to avoid damage due to over voltage. These chips neatly integrate
this with the &lt;span class="caps"&gt;PWM&lt;/span&gt; control ability. Their only downsides were their cost (~£2
each - with 36 of them needed for my lighting project, they were the greatest
single expense) and package which isn&amp;#8217;t designed to be hand&amp;nbsp;soldered.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other&amp;nbsp;features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Header for in-circuit &lt;span class="caps"&gt;PIC&lt;/span&gt; programming. To disconnect the &lt;span class="caps"&gt;UART&lt;/span&gt; pins (required
  for programming) and to attach a 10K pull up resistor, I included three
  jumper headers. However, I found connecting the pull up wasn&amp;#8217;t necessary for&amp;nbsp;programming.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Screw terminals for all installation&amp;nbsp;connections.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Indicator LEDs for &lt;span class="caps"&gt;UART&lt;/span&gt; &lt;span class="caps"&gt;TX&lt;/span&gt; and &lt;span class="caps"&gt;RX&lt;/span&gt; directions, and&amp;nbsp;power.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I designed the &lt;span class="caps"&gt;PCB&lt;/span&gt; using the excellent &lt;a href="http://kicad-pcb.org/"&gt;KiCAD&lt;/a&gt; and had
it manufactured very cheaply by &lt;a href="https://www.seeedstudio.com/fusion_pcb.html"&gt;Seeed Studio&lt;/a&gt;
in Shenzhen,&amp;nbsp;China.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the&amp;nbsp;schematic:&lt;/p&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/schematic.png" class="glightbox" data-gallery="led-driver"&gt;
    &lt;img class="rounded" src="thumbs/schematic_800x800.png" alt="Board circuit schematic"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;h1&gt;Parts&amp;nbsp;list&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th cope="col"&gt;Quantity&lt;/th&gt;
      &lt;th scope="col"&gt;Package&lt;/th&gt;
      &lt;th scope="col"&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;TO&lt;/span&gt;-263&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;CAT4101&lt;/span&gt; &lt;span class="caps"&gt;LED&lt;/span&gt; drivers 5.5V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;DIP&lt;/span&gt;-8&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;PIC12F1572&lt;/span&gt; microcontroller&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;DIP&lt;/span&gt;-8&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;MAX485&lt;/span&gt; serial interface&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0805&lt;/td&gt;
      &lt;td&gt;Green LEDs&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0805&lt;/td&gt;
      &lt;td&gt;Resistor 10K&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0805&lt;/td&gt;
      &lt;td&gt;Resistor 1.4K&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0805&lt;/td&gt;
      &lt;td&gt;Resistor 510&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;0805&lt;/td&gt;
      &lt;td&gt;Capacitor 0.1 uF&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;&lt;span class="caps"&gt;SOT&lt;/span&gt;-23&lt;/td&gt;
      &lt;td&gt;2N7002 N-channel &lt;span class="caps"&gt;MOSFET&lt;/span&gt; 300 mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;2 way 5mm pitch terminal blocks&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;3 way 5mm pitch terminal blocks&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;12&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;2.54mm pitch pin headers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;2.54mm pin header jumper caps&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;span class="caps"&gt;CAT4101&lt;/span&gt; sense resistors are chosen to give a constant current close to 300
mA, at 1.4 KOhms. See the &lt;span class="caps"&gt;CAT4101&lt;/span&gt; &lt;a href="https://www.onsemi.com/pub/Collateral/CAT4101-D.PDF"&gt;datasheet&lt;/a&gt; for more&amp;nbsp;details.&lt;/p&gt;
&lt;p&gt;For reference, I have assumed the following parameters of the LEDs I
used (you should however check the datasheet for a particular &lt;span class="caps"&gt;LED&lt;/span&gt;):&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Colour&lt;/th&gt;
      &lt;th scope="col"&gt;Typical forward voltage&lt;br&gt;(@ 350 mA)&lt;/th&gt;
      &lt;th scope="col"&gt;Part&lt;/th&gt;
      &lt;th scope="col"&gt;Reference&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Red&lt;/td&gt;
      &lt;td&gt;2.4&lt;/td&gt;
      &lt;td&gt;3W &lt;span class="caps"&gt;RGB&lt;/span&gt; module&lt;/td&gt;
      &lt;td&gt;&lt;a href="https://www.sparkfun.com/datasheets/Components/LED/COM-08718-datasheet.pdf"&gt;Datasheet (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Green&lt;/td&gt;
      &lt;td&gt;3.4&lt;/td&gt;
      &lt;td&gt;3W &lt;span class="caps"&gt;RGB&lt;/span&gt; module&lt;/td&gt;
      &lt;td&gt;&lt;a href="https://www.sparkfun.com/datasheets/Components/LED/COM-08718-datasheet.pdf"&gt;Datasheet (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Blue&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3W &lt;span class="caps"&gt;RGB&lt;/span&gt; module&lt;/td&gt;
      &lt;td&gt;&lt;a href="https://www.sparkfun.com/datasheets/Components/LED/COM-08718-datasheet.pdf"&gt;Datasheet (&lt;span class="caps"&gt;PDF&lt;/span&gt;)&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;White&lt;/td&gt;
      &lt;td&gt;2.8-3.4&lt;/td&gt;
      &lt;td&gt;1W Ice White &lt;span class="caps"&gt;LED&lt;/span&gt; (Bridgelux 9000-15000k)&lt;/td&gt;
      &lt;td&gt;&lt;a href="https://futureeden.co.uk/collections/ice-white-bridgelux-power-led-9000-15000k/products/1w-ice-white-led-bridgelux-12000k-with-pcb"&gt;Future Eden&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;span class="caps"&gt;CAT4101&lt;/span&gt; is a &lt;a href="https://electronics.stackexchange.com/questions/344547/how-do-i-calculate-the-efficiency-of-a-linear-constant-current-led-driver"&gt;linear driver&lt;/a&gt;, so it effectively acts as a
variable resistor to deliver constant current, with an efficiency of
$V_{led}/V_{supply}$. A disadvantage of driving each &lt;span class="caps"&gt;LED&lt;/span&gt; individually is that
its efficiency can be low, down to 50%. The power delivered to the &lt;span class="caps"&gt;LED&lt;/span&gt; is
$I_{led} \times V_{led}$ and the power dissipated by the driver is $I_{led}
\times V_{supply}$ (not including quiescent&amp;nbsp;power).&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope="col"&gt;Channel&lt;/th&gt;
      &lt;th scope="col"&gt;Voltage (V)&lt;/th&gt;
      &lt;th scope="col"&gt;Current (A)&lt;/th&gt;
      &lt;th scope="col"&gt;&lt;span class="caps"&gt;LED&lt;/span&gt; power (W)&lt;/th&gt;
      &lt;th scope="col"&gt;&lt;span class="caps"&gt;CAT4101&lt;/span&gt; efficiency&lt;/th&gt;
      &lt;th scope="col"&gt;Driver power (W)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Red&lt;/td&gt;
      &lt;td&gt;2.4&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;0.72&lt;/td&gt;
      &lt;td&gt;0.48&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Green&lt;/td&gt;
      &lt;td&gt;3.4&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;1.02&lt;/td&gt;
      &lt;td&gt;0.68&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Blue&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;1.05&lt;/td&gt;
      &lt;td&gt;0.7&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;White&lt;/td&gt;
      &lt;td&gt;3.2&lt;/td&gt;
      &lt;td&gt;0.3&lt;/td&gt;
      &lt;td&gt;0.96&lt;/td&gt;
      &lt;td&gt;0.64&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Measurements of each of the &lt;span class="caps"&gt;LED&lt;/span&gt; channels using a current clamp meter showed
that the current drawn ranges from 357 mA to 370&amp;nbsp;mA.&lt;/p&gt;
&lt;h1&gt;Programming&lt;/h1&gt;
&lt;p&gt;The intention of the &lt;span class="caps"&gt;PIC&lt;/span&gt; microcontrollers is to react to a simple set of
commands sent via the serial interface. In deployment, an array of these driver
boards would be controlled by another processor broadcasting on the &lt;span class="caps"&gt;RS485&lt;/span&gt; bus.
I used a Raspberry Pi with an &lt;span class="caps"&gt;RS485&lt;/span&gt; shield to do&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;At a minimum, the PICs need to set the intensity of each &lt;span class="caps"&gt;LED&lt;/span&gt; they control,
which is the current operation of the firmware. They could however be triggered
to perform more complex modulations. This would reduce the data transmission
requirements on the &lt;span class="caps"&gt;RS485&lt;/span&gt; bus, potentially improving the quality of animations
produced by an&amp;nbsp;array.&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;PIC&lt;/span&gt; microcontrollers are programmed in C, which I did using Microchip&amp;#8217;s &lt;span class="caps"&gt;XC&lt;/span&gt;
compiler and MPLab &lt;span class="caps"&gt;IDE&lt;/span&gt; software. In order that each board can uniquely identify
it&amp;#8217;s control data, they are compiled with a unique &lt;span class="caps"&gt;ID&lt;/span&gt;. With a deployment of 12
boards, firmware updates are a little arduous, particularly since the two
jumpers need to be removed as&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;I found that an efficient communication protocol between an array of boards
and the main controller (Raspberry Pi) is a sequence of bytes with the first
uniquely determining the header and the following 36 determining the intensity
of each of the individual LEDs. Each board uses its &lt;span class="caps"&gt;ID&lt;/span&gt; to choose three values
in the payload. At 115,200 bps, this in theory allows up to 389 commands to
be sent per second. Note that the boards do not send an acknowledgement, since
this significantly reduces the throughput. In Python a packet can be sent with
(&lt;a href="https://github.com/jameshanlon/rgb-stacks/blob/master/rgbstacks.py"&gt;snippet from here&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;set_colour&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;assert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;usart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;usart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The PICs receive &lt;span class="caps"&gt;UART&lt;/span&gt; data and set the output PWMs thus
(&lt;a href="https://github.com/jameshanlon/rgb-stacks/blob/master/PIC/main.c"&gt;snippet from here&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RCREGbits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RCREG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;START_PACKET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;uart_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Packet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;uart_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uart_count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RCREGbits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RCREG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;When&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;we&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ve received the payload, update PWMs and setup for next packet.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uart_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PAYLOAD_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cycles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM1DC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uart_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DRIVER_OFFSET&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM2DC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uart_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DRIVER_OFFSET&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM3DC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uart_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DRIVER_OFFSET&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Reload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PWMs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM1LD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM2LD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PWM3LD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;uart_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;Pictures&lt;/h1&gt;
&lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/unpopulated-boards.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/unpopulated-boards_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/assembled-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/assembled-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/assembled-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/assembled-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/assembled-top.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/assembled-top_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/assembled-programmer.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/assembled-programmer_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/8up.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/8up_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/array-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/array-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/array-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/array-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/LED-driver/4up-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/4up-1_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;Improvements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Adjust the &lt;span class="caps"&gt;CAT4101&lt;/span&gt; sense resistor to deliver closer to 300 mA (1.5-1.6&amp;nbsp;KOhm).&lt;/li&gt;
&lt;li&gt;Remove the 10K pull up resistor for programming the &lt;span class="caps"&gt;PIC&lt;/span&gt; since it is&amp;nbsp;unnecessary.&lt;/li&gt;
&lt;li&gt;Update the defunct silk screen &lt;span class="caps"&gt;URL&lt;/span&gt; to my new jameswhanlon.com&amp;nbsp;domain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;References&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/3C-HP-LED-driver"&gt;Board design and microcontroller source code on&amp;nbsp;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thecustomgeek.com/2013/12/28/rgbw31/"&gt;&lt;span class="caps"&gt;RGBW&lt;/span&gt; &lt;span class="caps"&gt;LED&lt;/span&gt; Controller v3.1 (The Custom Geek)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bigclive.com/newrgb.htm"&gt;Make an &lt;span class="caps"&gt;RGB&lt;/span&gt; lighting controller&amp;nbsp;(Bigclivedotcom)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/id/Easy-CAT4101-LED-Driver/"&gt;Easy &lt;span class="caps"&gt;CAT4101&lt;/span&gt; &lt;span class="caps"&gt;LED&lt;/span&gt; Driver&amp;nbsp;(Instructables)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/id/Circuits-for-using-High-Power-LED-s/"&gt;High power &lt;span class="caps"&gt;LED&lt;/span&gt; driver circuits&amp;nbsp;(Instructables)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/id/Power-LED-s---simplest-light-with-constant-current/"&gt;Power &lt;span class="caps"&gt;LED&lt;/span&gt;&amp;#8217;s - Simplest Light With Constant-current Circuit&amp;nbsp;(Instructables)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://electronics.stackexchange.com/questions/344547/how-do-i-calculate-the-efficiency-of-a-linear-constant-current-led-driver"&gt;Re: Help understanding electrical efficiency of LEDs with &lt;span class="caps"&gt;PWM&lt;/span&gt; dimming (Candle Power&amp;nbsp;Forums)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Physical Projects"/><category term="lighting"/><category term="electronics"/></entry><entry><title>Querying logical paths in a Verilog design</title><link href="https://jameswhanlon.com/querying-logical-paths-in-a-verilog-design.html" rel="alternate"/><published>2018-11-20T00:00:00+01:00</published><updated>2018-11-20T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-11-20:/querying-logical-paths-in-a-verilog-design.html</id><summary type="html">&lt;p&gt;A description of a command-line tool I created for tracing timing
paths from a flattened netlist back through the &lt;span class="caps"&gt;RTL&lt;/span&gt;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I wrote a simple command-line tool for querying logical paths in a Verilog
design. My motivation for doing this is that it&amp;#8217;s easy to create complex logic
in Verilog, particularly between modules, but more difficult to understand
exactly what is driving a particular net, just from inspecting the code. It is
the complex cones of logic that lead to timing problems in a synthesised
design, but having to push a design through a synthesis flow takes time, making
speculative timing fixes a lengthy process. A command-line tool is useful as it
can be integrated into more complex workflows, in contrast with using more
complex and usually graphical &lt;span class="caps"&gt;EDA&lt;/span&gt;&amp;nbsp;tooling.&lt;/p&gt;
&lt;p&gt;The tool addresses high-level structural problems in a design, such as
incorrect dependencies when a signal including logic that is not necessary to
its function. It does not deal with other timing issues that are a product of
the synthesis and physical build of the design. As such, all the structural
information required is contained within the Verilog source&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;This note briefly explains how the tool works and records some ideas on how it
could be&amp;nbsp;extended.&lt;/p&gt;
&lt;h2&gt;Use&lt;/h2&gt;
&lt;p&gt;Instructions to build the tool are in the &lt;span class="caps"&gt;README&lt;/span&gt; in the &lt;a href="https://github.com/jameshanlon/netlist-paths/blob/master/README.md"&gt;GitHub
repository&lt;/a&gt;.
Assuming&amp;nbsp;the &lt;code&gt;netlist-paths&lt;/code&gt; install &lt;code&gt;bin&lt;/code&gt; directory is available in&amp;nbsp;your
&lt;code&gt;PATH&lt;/code&gt;, then using the &lt;a href="https://github.com/cliffordwolf/picorv32"&gt;PicoRV32 processor
implementation&lt;/a&gt; as an example, its
netlist can be generated as&amp;nbsp;follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/cliffordwolf/picorv32.git
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;picorv32
$&lt;span class="w"&gt; &lt;/span&gt;verilator&lt;span class="w"&gt; &lt;/span&gt;--dump-netlist-graph&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;picorv32.v&lt;span class="w"&gt; &lt;/span&gt;--top-module&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi
...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# lots of warnings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here a modified version of &lt;a href="https://www.veripool.org/wiki/verilator"&gt;Verilator&lt;/a&gt;
is used to generate the netlist. (Note&amp;nbsp;that &lt;code&gt;netlist-paths&lt;/code&gt; can invoke
Verilator but with&amp;nbsp;the &lt;code&gt;--compile&lt;/code&gt; option, but PicoRV32 requires&amp;nbsp;Verilator&amp;#8217;s
&lt;code&gt;--top-module&lt;/code&gt; option. It may be useful to extend the command line arguments to
allow arbitrary arguments to be passed to Verilator.) Verilator performs the
generation by traversing the abstract syntax tree of the design and constructs
a graph of dependencies between variables and combinatorial logical constructs,
and identifies variables corresponding to sequential elements (flip&amp;nbsp;flops).&lt;/p&gt;
&lt;p&gt;The graph structure/netlist is written to file in &lt;a href="https://graphviz.gitlab.io/_pages/doc/info/lang.html"&gt;Graphviz dot
format&lt;/a&gt;, and specifies
the vertices, with their type and source code location information, and the
edges between them. The analysis tool reads this file and reports on the
connectivity between&amp;nbsp;points.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;digraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;netlist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ASSIGNW&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32.v:2539&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PORT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32_axi.trace_data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32.v:2539&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PORT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;trace_data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32.v:2539&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n3&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ASSIGNW&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32.v:2538&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n4&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PORT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32_axi.trace_valid&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;picorv32.v:2538&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;n6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A vertex in this netlist corresponds to the occurrence of a variable (ie a
symbolic name). A given symbolic name can appear in different vertices,
corresponding to its different uses. To see this, the&amp;nbsp;option &lt;code&gt;--dumpnames&lt;/code&gt;
prints the names, types and directions of all the vertices in the graph. This
output can be piped&amp;nbsp;through &lt;code&gt;grep&lt;/code&gt; to locate particular signals. For example,
to see all the output&amp;nbsp;variables:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;netlist-paths&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;--dumpnames&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;OUTPUT
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;eoi
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_araddr
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_arprot
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_arvalid
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_awaddr
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_awprot
PORT&lt;span class="w"&gt; &lt;/span&gt;OUTPUT&lt;span class="w"&gt; &lt;/span&gt;mem_axi_awvalid
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or all the&amp;nbsp;registers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;netlist-paths&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;--dumpnames&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;REG_DST
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.ack_arvalid
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.ack_awvalid
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.ack_wvalid
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.xfer_done
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.alu_out_0_q
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.alu_out_q
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.alu_wait
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.alu_wait_2
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.cached_ascii_instr
REG_DST&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.cached_insn_imm
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here,&amp;nbsp;the &lt;code&gt;REG_DST&lt;/code&gt; type corresponds to a variable that is the left-hand side
of a non-blocking&amp;nbsp;assignment &lt;code&gt;&amp;lt;=&lt;/code&gt;. Conversely,&amp;nbsp;the &lt;code&gt;REG_SRC&lt;/code&gt; type is where the
same variable appears in an expression on the right-hand side. In general,
there can only be a&amp;nbsp;single &lt;code&gt;REG_DST&lt;/code&gt; node with a specific name, whereas there
can be&amp;nbsp;multiple &lt;code&gt;REG_SRC&lt;/code&gt; nodes with a specific names. The same is true&amp;nbsp;with
&lt;code&gt;VAR&lt;/code&gt;, &lt;code&gt;WIRE&lt;/code&gt; and &lt;code&gt;PORT&lt;/code&gt; types. When using this tool, I&amp;#8217;ve found it
straight forward to locate the variables I need&amp;nbsp;using &lt;code&gt;grep&lt;/code&gt; with
&lt;code&gt;--dumpnames&lt;/code&gt;, but there may be more sophisticated approaches that could be&amp;nbsp;implemented.&lt;/p&gt;
&lt;p&gt;A start or end point can be specified as any named vertex, which is anything
except logic statements. You can query if a path exists between two&amp;nbsp;points:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;netlist-paths&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;--start&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.cpu_state&lt;span class="w"&gt; &lt;/span&gt;--end&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.cpu_state&lt;span class="w"&gt;        &lt;/span&gt;REG_SRC&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:1160
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGNW&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:1373
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.launch_next_insn&lt;span class="w"&gt; &lt;/span&gt;WIRE&lt;span class="w"&gt;            &lt;/span&gt;picorv32.v:750
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                      &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:760
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn&lt;span class="w"&gt;   &lt;/span&gt;REG_DST&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:751
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this path report, it lists the sequential dependencies from the start point
to the end point, through a sequence of zero or more combinatorial logic
statements/blocks, with each dependency corresponding to a variable.
Importantly, the filenames and line numbers given reference the original source&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;Since there may be multiple vertices with a name matching the specified start
and end points, the register version is preferentially located&amp;nbsp;(&lt;code&gt;SRC&lt;/code&gt; for a
start point&amp;nbsp;and &lt;code&gt;DST&lt;/code&gt; for an end point), followed&amp;nbsp;by &lt;code&gt;VAR&lt;/code&gt;, &lt;code&gt;WIRE&lt;/code&gt; and
&lt;code&gt;PORT&lt;/code&gt; types.&lt;/p&gt;
&lt;p&gt;You can also query all the paths that fan out from a particular start&amp;nbsp;point:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;netlist-paths netlist.graph --start picorv32_axi.picorv32_core.cpu_state
Path 1
  picorv32_axi.picorv32_core.cpu_state        REG_SRC         picorv32.v:1160
  ASSIGNW                                     LOGIC           picorv32.v:1373
  picorv32_axi.picorv32_core.launch_next_insn WIRE            picorv32.v:750
  ALWAYS                                      LOGIC           picorv32.v:760
  picorv32_axi.picorv32_core.q_ascii_instr    REG_DST         picorv32.v:742

Path 2
  picorv32_axi.picorv32_core.cpu_state        REG_SRC         picorv32.v:1160
  ASSIGNW                                     LOGIC           picorv32.v:1373
  picorv32_axi.picorv32_core.launch_next_insn WIRE            picorv32.v:750
  ALWAYS                                      LOGIC           picorv32.v:760
  picorv32_axi.picorv32_core.q_insn_imm       REG_DST         picorv32.v:743

Path 3
  picorv32_axi.picorv32_core.cpu_state        REG_SRC         picorv32.v:1160
  ASSIGNW                                     LOGIC           picorv32.v:1373
  picorv32_axi.picorv32_core.launch_next_insn WIRE            picorv32.v:750
  ALWAYS                                      LOGIC           picorv32.v:760
  picorv32_axi.picorv32_core.q_insn_opcode    REG_DST         picorv32.v:744
...
Found 223 path(s)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or query all the paths that fan in to a particular end&amp;nbsp;point:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;netlist-paths&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;--end&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn
Path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.trap&lt;span class="w"&gt;           &lt;/span&gt;REG_SRC&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:86
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                    &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:760
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn&lt;span class="w"&gt; &lt;/span&gt;REG_DST&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:751

Path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.instr_lui&lt;span class="w"&gt;       &lt;/span&gt;REG_SRC&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:630
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:684
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGN&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:685
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.new_ascii_instr&lt;span class="w"&gt; &lt;/span&gt;VAR&lt;span class="w"&gt;             &lt;/span&gt;picorv32.v:673
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:760
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn&lt;span class="w"&gt;  &lt;/span&gt;REG_DST&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:751

Path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.instr_auipc&lt;span class="w"&gt;     &lt;/span&gt;REG_SRC&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:630
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:684
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGN&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:685
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.new_ascii_instr&lt;span class="w"&gt; &lt;/span&gt;VAR&lt;span class="w"&gt;             &lt;/span&gt;picorv32.v:673
&lt;span class="w"&gt;  &lt;/span&gt;ALWAYS&lt;span class="w"&gt;                                     &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:760
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.picorv32_core.dbg_valid_insn&lt;span class="w"&gt;  &lt;/span&gt;REG_DST&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:751
...
Found&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;74&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;paths
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since the number of paths between any two points in an arbitrary graph grows
exponentially with the size of the graph, it infeasible to report all paths
between two points, so this tool simply looks for any path that satisfies those
constraints. (An option is provided to enumerate all paths, but it can only be
used on small&amp;nbsp;netlists.)&lt;/p&gt;
&lt;p&gt;When trying to match a particular path in a physical build it it useful to
further constrain the search to force it to match the same path. This can be
done by specifying through points with&amp;nbsp;the &lt;code&gt;--through&lt;/code&gt; option. Each through
argument is taken in order as an intermediate point in the path. The same
search algorithm is used on each pair of points to build up a composite report.
For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;netlist-paths&lt;span class="w"&gt; &lt;/span&gt;netlist.graph&lt;span class="w"&gt; &lt;/span&gt;--start&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.ack_wvalid&lt;span class="w"&gt; &lt;/span&gt;--through&lt;span class="w"&gt; &lt;/span&gt;picorv32_axi.axi_adapter.mem_axi_wvalid&lt;span class="w"&gt; &lt;/span&gt;--end&lt;span class="w"&gt; &lt;/span&gt;mem_axi_wvalid
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.axi_adapter.ack_wvalid&lt;span class="w"&gt;     &lt;/span&gt;REG_SRC&lt;span class="w"&gt;         &lt;/span&gt;picorv32.v:2700
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGNW&lt;span class="w"&gt;                                 &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:2711
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.axi_adapter.mem_axi_wvalid&lt;span class="w"&gt; &lt;/span&gt;PORT&lt;span class="w"&gt;            &lt;/span&gt;picorv32.v:2671
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGNW&lt;span class="w"&gt;                                 &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:2556
&lt;span class="w"&gt;  &lt;/span&gt;picorv32_axi.mem_axi_wvalid&lt;span class="w"&gt;             &lt;/span&gt;PORT&lt;span class="w"&gt;            &lt;/span&gt;picorv32.v:2484
&lt;span class="w"&gt;  &lt;/span&gt;ASSIGNW&lt;span class="w"&gt;                                 &lt;/span&gt;LOGIC&lt;span class="w"&gt;           &lt;/span&gt;picorv32.v:2484
&lt;span class="w"&gt;  &lt;/span&gt;mem_axi_wvalid&lt;span class="w"&gt;                          &lt;/span&gt;PORT&lt;span class="w"&gt;            &lt;/span&gt;picorv32.v:2484
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;To avoid writing a preprocessor and parser for Verilog, I modified
&lt;a href="https://www.veripool.org/wiki/verilator"&gt;Verilator&lt;/a&gt; to obtain the netlist of a
Verilog design. (I would have liked to use
&lt;a href="http://www.clifford.at/yosys/"&gt;Yosys&lt;/a&gt; to do this because it provides a neat
interface to adding custom &lt;span class="caps"&gt;AST&lt;/span&gt; passes, but unfortunately it does not currently
support enough of the SystemVerilog standard.) The Verilator modifications add
a new &lt;span class="caps"&gt;AST&lt;/span&gt; visitor, which walks the tree after it has been processed, for
example to propagate constants and inline tasks and&amp;nbsp;modules.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;netlist-paths&lt;/code&gt; tool is implemented in C++ and makes use of the Boost Graph
Library. Paths are identified using&amp;nbsp;the &lt;code&gt;boost::depth_first_search&lt;/code&gt; algorithm.
The all-fan-out report enumerates paths to all the end points in a depth-first
traversal of the graph, the fan-in variant uses&amp;nbsp;the &lt;code&gt;boost::reverse_graph&lt;/code&gt;
adaptor and performs the same algorithm. Properties are associated with
vertices in the graph using&amp;nbsp;a &lt;code&gt;boost::dynamic_property_map&lt;/code&gt;. I put together a
&lt;a href="https://github.com/jameshanlon/boost_graph_example"&gt;simple example program&lt;/a&gt; to
illustrate how to use these maps (plus some other library features) since I
found there were some subtleties in getting this to&amp;nbsp;work.&lt;/p&gt;
&lt;h2&gt;Improvements&lt;/h2&gt;
&lt;p&gt;There are many ways this tool could be extended and improved. Here are a few&amp;nbsp;ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide additional flexibility to allow a choice between multiple matching start, through or end&amp;nbsp;points.&lt;/li&gt;
&lt;li&gt;Provide a mechanism to search for high fan-out&amp;nbsp;variables.&lt;/li&gt;
&lt;li&gt;Provide a mechanism to seach for the longest paths in the&amp;nbsp;graph.&lt;/li&gt;
&lt;li&gt;Provide a mechanism to assert there is no logical path between two sub&amp;nbsp;modules.&lt;/li&gt;
&lt;li&gt;Detect and report timing&amp;nbsp;loops.&lt;/li&gt;
&lt;li&gt;Add options&amp;nbsp;to &lt;code&gt;dumpnames&lt;/code&gt; to filter by type or&amp;nbsp;direction.&lt;/li&gt;
&lt;li&gt;Add options to the querys to select only internal paths or only input/output&amp;nbsp;paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/netlist-paths"&gt;Netlist paths tool on&amp;nbsp;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/verilator"&gt;Modified Verilator on&amp;nbsp;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jameshanlon/boost_graph_example"&gt;Boost Graph Library&amp;nbsp;example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="microelectronics"/><category term="verilog"/></entry><entry><title>Retrofit shed insulation</title><link href="https://jameswhanlon.com/retrofit-shed-insulation.html" rel="alternate"/><published>2018-09-30T00:00:00+02:00</published><updated>2018-09-30T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-09-30:/retrofit-shed-insulation.html</id><summary type="html">&lt;p&gt;Retrofitting an existing shed/workshop with insulation to improve its
energy efficiency and make it a usable space throughout the&amp;nbsp;year.&lt;/p&gt;</summary><content type="html">&lt;p&gt;To make the shed in my garden (built by the previous owner) a usable space in
cold weather, I decided to insulate it. The construction of it is a stud timber
frame of 2x4&amp;#8221; with a corrugated metal exterior and lined inside with &lt;span class="caps"&gt;OSB&lt;/span&gt; board.
The construction has created voids in the floor, walls and roof, providing a
convenient space to add&amp;nbsp;insulation.&lt;/p&gt;
&lt;p&gt;I considered using natural wool insulation, as opposed to rigid insulation
board, but felt that it would difficult to secure it in place in a consistent
way, as well as ensuring an air gap remains between the external cladding. I
decided on using Celotex rigid insulation board and used 12 sheets of 75mm
thick standard 2400 mm x 1200 mm size, and two boards of the same size at 50 mm
for the back wall. In total, the insulation cost £512.74 (including &lt;span class="caps"&gt;VAT&lt;/span&gt;). To
prevent draughts as much as possible, I decided to tape the gaps between the
boards and shed timbers. I bought about 8 rolls of foil tape to do&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;The insulation board turned out to be easy to work with, easy to cut with a
panel saw and fitting snugly in the gaps and leaving plenty of space for
ventilation. I found the dust created by sawing the board irritating to my eyes
and breathing so as much as possible wore eye protection and a mask (although
hard to do getting hot in the small space). Working overhead on the roof was
the worst part as it was difficult to avoid falling dust on my face. The whole
job took three days to complete and has made a substantial difference to the
stability of the temperature in the&amp;nbsp;space.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/before-left-wall.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/before-left-wall_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/before-consumer-unit.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/before-consumer-unit_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/insulation-board.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/insulation-board_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;The &lt;span class="caps"&gt;OSB&lt;/span&gt; lining before starting (left) and the 75 mm board (right).&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/stripped-panorama.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/stripped-panorama_w=1200.jpg" alt="OSB lining removed from the walls and roof."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;span class="caps"&gt;OSB&lt;/span&gt; lining removed from the walls and roof.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/stripped-floor.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/stripped-floor_h=450.jpg" alt="The remaining OSB removed from the floor."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The remaining &lt;span class="caps"&gt;OSB&lt;/span&gt; removed from the floor.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/floor-1.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/floor-1_600x600.jpg" alt="Complete and taped floor insulation, and half the floor restored."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Complete and taped floor insulation, and half the floor restored.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/exposed-roof.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/exposed-roof_600x600.jpg" alt="Installation of insulation into the roof apex. The dust falling from the board as they are positioned in place made this an unpleasant job."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Installation of insulation into the roof apex. The dust falling from the board as they are positioned in place made this an unpleasant job.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/left-wall-done.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/left-wall-done_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/right-wall-done-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/right-wall-done-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/fiddly-bit.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/fiddly-bit_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Completed walls and roof, prior to taping.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/back-wall-preparation.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-wall-preparation_600x600.jpg" alt="Timer added to provide a space to install the insulation."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Timer added to provide a space to install the insulation.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/back-wall-done.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-wall-done_600x600.jpg" alt="...and the insulation in place."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&amp;#8230;and the insulation in place.&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;/div&gt;
&lt;/div&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/back-right-2.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/back-right-2_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/door-left-done.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/door-left-done_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Details of more completed areas, before and after taping.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/complete-tools-panorama.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/complete-tools-panorama_w=1200.jpg" alt="The scene before tidying up."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;The scene before tidying up.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/complete-panorama.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/complete-panorama_w=1200.jpg" alt="...and after tidying."&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&amp;#8230;and after tidying.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
&lt;div class="row align-items-center"&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/work-bench.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/work-bench_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="col"&gt;
  &lt;div class="text-center"&gt;
  &lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/shed-insulation/shelving.jpg" class="glightbox" data-gallery="all"&gt;
    &lt;img class="thumbnail" src="/thumbs/shelving_600x600.jpg" alt="No alt text"&gt;
  &lt;/a&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;Almost done: enough &lt;span class="caps"&gt;OSB&lt;/span&gt; lining back in to install the workbench and shelves.&lt;/figcaption&gt;
&lt;/figure&gt;</content><category term="Home and Sustainability"/><category term="energy-efficiency"/><category term="retrofit"/><category term="sheds"/><category term="sustainability"/></entry><entry><title>Vim command composition</title><link href="https://jameswhanlon.com/vim-command-composition.html" rel="alternate"/><published>2018-08-23T00:00:00+02:00</published><updated>2018-08-23T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-08-23:/vim-command-composition.html</id><summary type="html">&lt;p&gt;The rules for composing Vim&amp;#8217;s motions and&amp;nbsp;operators.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve been using Vim for a long time and I&amp;#8217;m familiar with many of its commands
but I&amp;#8217;ve never had a good understanding of the underlying components of
commands and their composition. Although there are many good Vim
&lt;a href="#references"&gt;references&lt;/a&gt;, I felt that I was still not seeing the full picture.
So, to try and dig a little deeper and educate myself, I&amp;#8217;ve put together this
reference, which details a subset of the command language. The approach I&amp;#8217;ve
taken was inspired by the grammar rules outlined in &lt;a href="https://takac.github.io/2013/01/30/vim-grammar/"&gt;this blog
post&lt;/a&gt;, and should be useful
for anyone who is familiar with&amp;nbsp;Vim.&lt;/p&gt;
&lt;p&gt;A Vim command can be constructed from different rules, and below each rule is
specified with a &lt;a href="https://en.wikipedia.org/wiki/Extended_Backus-Naur_form"&gt;&lt;span class="caps"&gt;EBNF&lt;/span&gt;-style
syntax&lt;/a&gt;,&amp;nbsp;where &lt;code&gt;&amp;lt;...&amp;gt;&lt;/code&gt; is
another&amp;nbsp;rule. &lt;code&gt;{...}&lt;/code&gt; represents some key&amp;nbsp;presses, &lt;code&gt;|&lt;/code&gt; is an alternative&amp;nbsp;and
&lt;code&gt;[...]&lt;/code&gt; is an optional component. Be warned that
since there are many special cases to Vim commands and I&amp;#8217;ve not checked all the
combinations, some of the rules below may yield invalid compositions! As such,
these rules are better viewed as a way of remembering commands. For an
exhaustive treatment of the command language, please check the &lt;a href="https://www.vim.org/docs.php"&gt;Vim
documentation&lt;/a&gt;, or use&amp;nbsp;the &lt;code&gt;:help&lt;/code&gt; tags that I&amp;#8217;ve&amp;nbsp;given.&lt;/p&gt;
&lt;h2&gt;Motions&lt;/h2&gt;
&lt;p&gt;Motions change the position of the cursor and can be combined with a count to
repeat the&amp;nbsp;motion.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;2fx&lt;/code&gt; - move to the second right-hand occurrence&amp;nbsp;of &lt;code&gt;x&lt;/code&gt; in the line&amp;nbsp;(inclusive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2Tx&lt;/code&gt; - move to the second left-hand occurrence&amp;nbsp;of &lt;code&gt;x&lt;/code&gt; in the line&amp;nbsp;(exclusive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;w&lt;/code&gt; - move to the next&amp;nbsp;word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10j&lt;/code&gt; or &lt;code&gt;10_&lt;/code&gt; - move down 10&amp;nbsp;lines&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10k&lt;/code&gt; - move up 10&amp;nbsp;lines&lt;/li&gt;
&lt;li&gt;&lt;code&gt;6w&lt;/code&gt; - move to start of the sixth word&amp;nbsp;forwards&lt;/li&gt;
&lt;li&gt;&lt;code&gt;6E&lt;/code&gt; - move to end of sixth word&amp;nbsp;forwards&lt;/li&gt;
&lt;li&gt;&lt;code&gt;4b&lt;/code&gt; - move to start of the fourth word&amp;nbsp;backwards&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2{&lt;/code&gt; - move two paragraphs&amp;nbsp;down&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3/foo&lt;/code&gt; - move to the third occurrence&amp;nbsp;of &lt;code&gt;foo&lt;/code&gt; later in the&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3?foo&lt;/code&gt; - move to the third occurrence&amp;nbsp;of &lt;code&gt;foo&lt;/code&gt; earlier in the&amp;nbsp;buffer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Text&amp;nbsp;objects&lt;/h2&gt;
&lt;p&gt;Text objects are a collection of characters relative to the position of the
cursor. Compared to motions, text objects on a whole object, regardless of the
specific cursor position.&amp;nbsp;The &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;i&lt;/code&gt; modifiers augment text objects,
specifying whether the surrounding context should be included. The context may
be whitespace or delimiting&amp;nbsp;characters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;modifier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aw&lt;/code&gt; - around word (includes surrounding&amp;nbsp;whitespace)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iw&lt;/code&gt; - inner word (excludes surrounding&amp;nbsp;whitespace)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aW&lt;/code&gt; - around &lt;span class="caps"&gt;WORD&lt;/span&gt; (where word is delimited by&amp;nbsp;whitespace)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;as&lt;/code&gt; - around&amp;nbsp;sentence&lt;/li&gt;
&lt;li&gt;&lt;code&gt;is&lt;/code&gt; - inner&amp;nbsp;sentence&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ap&lt;/code&gt; - around&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ip&lt;/code&gt; - inner&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a'&lt;/code&gt; - a single-quoted&amp;nbsp;string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i'&lt;/code&gt; - inside a single-quoted&amp;nbsp;string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a(&lt;/code&gt; = &lt;code&gt;a)&lt;/code&gt;= &lt;code&gt;ab&lt;/code&gt; - a parenthesised block,&amp;nbsp;from &lt;code&gt;(&lt;/code&gt; to &lt;code&gt;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i(&lt;/code&gt; = &lt;code&gt;i)&lt;/code&gt;= &lt;code&gt;ib&lt;/code&gt; - inside a parenthesised block, contents&amp;nbsp;of &lt;code&gt;(...)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a&amp;lt;&lt;/code&gt; = &lt;code&gt;a&amp;gt;&lt;/code&gt; - a tag,&amp;nbsp;from &lt;code&gt;&amp;lt;&lt;/code&gt; to &lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;at&lt;/code&gt; - around tag block, including matching start and end&amp;nbsp;tags &lt;code&gt;&amp;lt;tag&amp;gt;...&amp;lt;/tag&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;it&lt;/code&gt; - inside tag block, excluding&amp;nbsp;tags&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aB&lt;/code&gt; = &lt;code&gt;a{&lt;/code&gt; = &lt;code&gt;a}&lt;/code&gt; - around&amp;nbsp;a &lt;code&gt;{...}&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iB&lt;/code&gt; = &lt;code&gt;i{&lt;/code&gt; = &lt;code&gt;i}&lt;/code&gt; - inside&amp;nbsp;a &lt;code&gt;{...}&lt;/code&gt; block&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Operators on text&amp;nbsp;objects&lt;/h2&gt;
&lt;p&gt;Operators can be applied to text objects. In some circumstances, a count can be
applied to the text object to repeat its&amp;nbsp;effect.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;modifier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cw&lt;/code&gt;  - change word from&amp;nbsp;cursor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ciw&lt;/code&gt; - change word under&amp;nbsp;cursor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dw&lt;/code&gt; - delete until end of&amp;nbsp;word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5dw&lt;/code&gt; = &lt;code&gt;d5w&lt;/code&gt; - delete until end of right-hand sixth&amp;nbsp;word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;caw&lt;/code&gt; - change around word under&amp;nbsp;cursor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2d3w&lt;/code&gt; - delete six&amp;nbsp;words&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5gUw&lt;/code&gt; - make the next five words&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dgg&lt;/code&gt; - delete lines from cursor to beginning of&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dG&lt;/code&gt; - delete lines from cursor to end of&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3d_&lt;/code&gt; - delete three&amp;nbsp;lines&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c$&lt;/code&gt; - change until end of&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y_&lt;/code&gt; = &lt;code&gt;yy&lt;/code&gt; = &lt;code&gt;Y&lt;/code&gt; - yank the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c_&lt;/code&gt; = &lt;code&gt;cc&lt;/code&gt; = &lt;code&gt;C&lt;/code&gt; - change the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gUap&lt;/code&gt; - make paragraph&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gqap&lt;/code&gt; - format paragraph text&amp;nbsp;to &lt;code&gt;textwidth&lt;/code&gt; line&amp;nbsp;length&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dit&lt;/code&gt; - delete text between&amp;nbsp;tags &lt;code&gt;&amp;lt;tag&amp;gt;&amp;lt;/tag&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dat&lt;/code&gt; - delete tag&amp;nbsp;block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yi"&lt;/code&gt; - yank text&amp;nbsp;in &lt;code&gt;"..."&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yi&amp;lt;&lt;/code&gt; - yank text&amp;nbsp;in &lt;code&gt;&amp;lt;...&amp;gt;&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yiB&lt;/code&gt; - yank text&amp;nbsp;in &lt;code&gt;{...}&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yaB&lt;/code&gt; - yank&amp;nbsp;whole &lt;code&gt;{...}&lt;/code&gt; block&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Operators on&amp;nbsp;motions&lt;/h2&gt;
&lt;p&gt;A motion can be applied after an operator to apply the operator on the text
that was moved&amp;nbsp;over.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dl&lt;/code&gt; = &lt;code&gt;x&lt;/code&gt; - delete next&amp;nbsp;character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db&lt;/code&gt; - delete backwards to the start of a&amp;nbsp;word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dtx&lt;/code&gt; - delete&amp;nbsp;until &lt;code&gt;x&lt;/code&gt; character in line&amp;nbsp;(exclusive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dfx&lt;/code&gt; - delete&amp;nbsp;until &lt;code&gt;x&lt;/code&gt; character in line&amp;nbsp;(inclusive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d/foo&lt;/code&gt; - delete from cursor to next occurrence&amp;nbsp;of &lt;code&gt;foo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d3/foo&lt;/code&gt; - delete from cursor until the third occurrence&amp;nbsp;of &lt;code&gt;foo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c$&lt;/code&gt; = &lt;code&gt;C&lt;/code&gt; - change until end of&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d$&lt;/code&gt; = &lt;code&gt;D&lt;/code&gt; - delete until end of&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d0&lt;/code&gt; - delete until beginning of&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d^&lt;/code&gt; - delete until first non-blank character in&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c{&lt;/code&gt; - change from current line to beginning of&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gU}&lt;/code&gt; - make paragraph&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c{&lt;/code&gt; - change paragraph (same&amp;nbsp;as &lt;code&gt;cap&lt;/code&gt; operator-text&amp;nbsp;object)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;}&lt;/code&gt; - indent&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y%&lt;/code&gt; - yank the&amp;nbsp;entire &lt;code&gt;{...}&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cgg&lt;/code&gt; - change lines from cursor to top of&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ggdG&lt;/code&gt; - delete contents of&amp;nbsp;buffer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Duplicate&amp;nbsp;operators&lt;/h2&gt;
&lt;p&gt;Operators applied twice affect the entire line, a synonym&amp;nbsp;for &lt;code&gt;&amp;lt;operator&amp;gt;_&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dd&lt;/code&gt; = &lt;code&gt;d_&lt;/code&gt; - delete&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cc&lt;/code&gt; = &lt;code&gt;c_&lt;/code&gt; - change&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yy&lt;/code&gt; = &lt;code&gt;y_&lt;/code&gt; - yank&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; = &lt;code&gt;&amp;gt;_&lt;/code&gt; = &lt;code&gt;&amp;gt;l&lt;/code&gt; - indent&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; = &lt;code&gt;&amp;lt;_&lt;/code&gt; = &lt;code&gt;&amp;gt;l&lt;/code&gt; - unindent&amp;nbsp;line&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: duplication does not apply&amp;nbsp;to &lt;code&gt;~&lt;/code&gt; or two-character&amp;nbsp;operators.&lt;/p&gt;
&lt;h2&gt;Aliases&lt;/h2&gt;
&lt;p&gt;Some commonly-used commands have&amp;nbsp;aliases.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt; = &lt;code&gt;dl&lt;/code&gt; - delete next&amp;nbsp;character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C&lt;/code&gt; = &lt;code&gt;c$&lt;/code&gt; - change until the end of the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D&lt;/code&gt; = &lt;code&gt;d$&lt;/code&gt; - delete until the end of the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Y&lt;/code&gt; = &lt;code&gt;yy&lt;/code&gt; - yank the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;S&lt;/code&gt; = &lt;code&gt;cc&lt;/code&gt; - change the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A&lt;/code&gt; = &lt;code&gt;$a&lt;/code&gt; - append text to end of the&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt; = &lt;code&gt;cl&lt;/code&gt; - substitute character (delete and&amp;nbsp;insert)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;S&lt;/code&gt; = &lt;code&gt;cc&lt;/code&gt; - substitute&amp;nbsp;line&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Filtering&lt;/h2&gt;
&lt;p&gt;Text lines can be filtered through an external program&amp;nbsp;(see &lt;code&gt;:help filter&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples, using some basic utilities found on Unix&amp;nbsp;platforms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;!8jsort&lt;/code&gt; - sort the next 8&amp;nbsp;lines&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!apsort&lt;/code&gt; - sort lines in&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!apwc -l&lt;/code&gt; - replace paragraph with word&amp;nbsp;count&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!apfmt -s&lt;/code&gt; - collapse whitespace in paragraph into single&amp;nbsp;spaces&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!apfmt -c&lt;/code&gt; - centre lines in&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!i(grep foo&lt;/code&gt; - remove all lines&amp;nbsp;in &lt;code&gt;(...)&lt;/code&gt; block that don&amp;#8217;t&amp;nbsp;contain &lt;code&gt;foo&lt;/code&gt;
  (similar to the Ex&amp;nbsp;command &lt;code&gt;:%v/foo/d&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gg!Gsort&lt;/code&gt; - sort all lines in&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gg!Guniq -c&lt;/code&gt; - remove all duplicate lines in buffer and prefix remaining with duplicate&amp;nbsp;counts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Visual&amp;nbsp;selection&lt;/h2&gt;
&lt;p&gt;Visual selection,&amp;nbsp;character-wise &lt;code&gt;v&lt;/code&gt;,&amp;nbsp;line-wise &lt;code&gt;V&lt;/code&gt; or&amp;nbsp;block-wise &lt;code&gt;Ctrl+v&lt;/code&gt; (all
referred to below&amp;nbsp;by &lt;code&gt;{visual}&lt;/code&gt;,&amp;nbsp;see &lt;code&gt;:help visual-start&lt;/code&gt;), followed by a
motion or text object can be used to specify a character range. An operator can
then be used to transform the text. Note the&amp;nbsp;operators &lt;code&gt;gu&lt;/code&gt;, &lt;code&gt;gU&lt;/code&gt; and &lt;code&gt;g@&lt;/code&gt;
can&amp;#8217;t be used in visual mode and text objects in visual mode, however, there
are additional ones that can&amp;nbsp;(see &lt;code&gt;:help visual-operators&lt;/code&gt;). A visual block is
created by entering a visual mode, then providing a motion or text object to
set the selection, or alternatively by any sequence of movement commands
(referred to&amp;nbsp;by &lt;code&gt;{move-around}&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;move&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;around&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vtxd&lt;/code&gt; = &lt;code&gt;dtx&lt;/code&gt; - delete&amp;nbsp;until &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vt.rx&lt;/code&gt; - replace all characters&amp;nbsp;with &lt;code&gt;x&lt;/code&gt; until &lt;code&gt;.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v3as~&lt;/code&gt; - make next three sentences&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vapU&lt;/code&gt; - make paragraph&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vapd&lt;/code&gt; - delete&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{Ctrl+v}{move-around}sfoo{Esc}&lt;/code&gt; - replace each line of blockwise selection&amp;nbsp;with &lt;code&gt;foo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{Ctrl+v}{move-around}Ifoo{Esc}&lt;/code&gt; -&amp;nbsp;prepend &lt;code&gt;foo&lt;/code&gt; to each line of blockwise&amp;nbsp;selection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{Ctrl+v}{move-around}Afoo{Esc}&lt;/code&gt; -&amp;nbsp;append &lt;code&gt;foo&lt;/code&gt; to each line of blockwise&amp;nbsp;selection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vap!sort&lt;/code&gt; - sort the lines of the current&amp;nbsp;paragraph&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vap!fmt&lt;/code&gt; - use&amp;nbsp;the &lt;code&gt;fmt&lt;/code&gt; command-line tool to format selection into
  lines of 75 characters (similar to&amp;nbsp;the &lt;code&gt;gqap&lt;/code&gt; command)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ggvG!indent&lt;/code&gt; - use&amp;nbsp;the &lt;code&gt;indent&lt;/code&gt; command-line tool to apply automatic
  indentation all lines of a C-code&amp;nbsp;buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{visual}J&lt;/code&gt; - join the highlighted lines on the current&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{visual}gJ&lt;/code&gt; - join the highlighted lines on the current line (removing&amp;nbsp;whitespace)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other command&amp;nbsp;combinations&lt;/h2&gt;
&lt;p&gt;Beyond the above rules, there are further command keys and more restricted
combination with motions, operators and text&amp;nbsp;objects.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; command repeats the last change that was&amp;nbsp;made.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;db.&lt;/code&gt; - delete the previous two&amp;nbsp;words&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db4.&lt;/code&gt; - delete the previous five&amp;nbsp;words&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{insert text...}&lt;/code&gt; then &lt;code&gt;/{pattern}.&lt;/code&gt; - insert text again before next text&amp;nbsp;matching &lt;code&gt;{pattern}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;gn&lt;/code&gt; and &lt;code&gt;gN&lt;/code&gt; motions can be used with operators to move between matching
search&amp;nbsp;patterns.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;gn&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;gN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cgn&lt;/code&gt; - change the next search&amp;nbsp;match&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3cgn&lt;/code&gt; - change the third search&amp;nbsp;match&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cgN&lt;/code&gt; - change the previous search&amp;nbsp;match&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are some other interesting and potentially useful commands that I&amp;#8217;ve found
in the Vim&amp;nbsp;help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gf&lt;/code&gt; - goto file (when cursor is on a valid filesystem&amp;nbsp;path)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gF&lt;/code&gt; - goto file and line number (line number following&amp;nbsp;path)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;J&lt;/code&gt; - Join the current line with the next one (with space in&amp;nbsp;between)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gJ&lt;/code&gt; - Join the current line with the next one (without space in&amp;nbsp;between)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3J&lt;/code&gt; - join the next three lines on the current line (removing&amp;nbsp;indent)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3gJ&lt;/code&gt; - join the next three lines on the current&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gv&lt;/code&gt; - reselect previous visual&amp;nbsp;area&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g~~&lt;/code&gt; = &lt;code&gt;g~g~&lt;/code&gt; - switch case of&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gUU&lt;/code&gt; = &lt;code&gt;gUgU&lt;/code&gt; - make line&amp;nbsp;uppercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;guu&lt;/code&gt; = &lt;code&gt;gugu&lt;/code&gt; - make line&amp;nbsp;lowercase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;r{char}&lt;/code&gt; - replace character under cursor&amp;nbsp;with &lt;code&gt;{char}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10r{char}&lt;/code&gt; - replace the next 10 characters&amp;nbsp;with &lt;code&gt;{char}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Summary of&amp;nbsp;rules&lt;/h2&gt;
&lt;div class="row"&gt;
&lt;div class="col-sm"&gt;
  &lt;h2&gt;Motions&lt;/h2&gt;
  &lt;p&gt;&lt;code&gt;&amp;lt;motion-keys&amp;gt;&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;References: &lt;code&gt;:help motion&lt;/code&gt;
    &lt;code&gt;:help various-motions&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l&lt;/code&gt;,&lt;code&gt;h&lt;/code&gt;,&lt;code&gt;j&lt;/code&gt;,&lt;code&gt;k&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;right, left, down, up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;w&lt;/code&gt; / &lt;code&gt;W&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;start of next word / start of next &lt;span class="caps"&gt;WORD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt; / &lt;code&gt;B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;start of pevious word / start of previous &lt;span class="caps"&gt;WORD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;e&lt;/code&gt; / &lt;code&gt;E&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;end of next word / end of next &lt;span class="caps"&gt;WORD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt; / &lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;start / end of line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt; / &lt;code&gt;g_&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;first / last non-blank character in line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{&lt;/code&gt; / &lt;code&gt;}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;start / end of paragraph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;t{char}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;till - move to next character (inclusive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f{char}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;find - move to next character (exclusive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;T{char}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;till - move to previous character (inclusive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;F{char}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;find - move to previous character (exclusive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;move to matching character (default&amp;nbsp;pairs: &lt;code&gt;()&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[(&lt;/code&gt;, &lt;code&gt;[)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;move to matching parenthesis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[{&lt;/code&gt;, &lt;code&gt;[}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;move to matching curly brace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/{pattern}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;search forward (must be followed&amp;nbsp;by &lt;code&gt;{CR}&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?{pattern}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;search backwards (must be followed&amp;nbsp;by &lt;code&gt;{CR}&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gg&lt;/code&gt; / &lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;move to first / last line in buffer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="col-sm"&gt;
  &lt;h2&gt;Operators&lt;/h2&gt;
  &lt;p&gt;&lt;code&gt;&amp;lt;operators&amp;gt;&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;Reference: &lt;code&gt;:help operator&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;delete&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;yank&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;swap case&amp;nbsp;(or &lt;code&gt;g~&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;shift right (always linewise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;shift left (always linewise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gu&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;make lowercase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gU&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;make uppercase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;format text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;g@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;apply function (set&amp;nbsp;by &lt;code&gt;operatorfunc&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;  &lt;h2&gt;Visual&amp;nbsp;operators&lt;/h2&gt;
  &lt;p&gt;&lt;code&gt;&amp;lt;visual-operators&amp;gt;&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;References: &lt;code&gt;:help visual-operators&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;r{char}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;replace every character in selection with {char}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;substitute (inserted text replicated on each line for blockwise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;J&lt;/code&gt; / &lt;code&gt;gJ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;join / join (remove whitespace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;put (replace selection with contents of register)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;U&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;make uppercase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;make lowercase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;I&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;insert (prepend, only on blockwise selection)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;insert (append, only on blockwise selection)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="row"&gt;
&lt;div class="col-sm"&gt;
  &lt;h2&gt;Text&amp;nbsp;objects&lt;/h2&gt;
  &lt;p&gt;&lt;code&gt;&amp;lt;text-object-keys&amp;gt;&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;References: &lt;code&gt;:help text-objects&lt;/code&gt;, &lt;code&gt;:help objects&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Text object&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;word (delimited by non-keyword characters,&amp;nbsp;see &lt;code&gt;:help iskeyword&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;W&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WORD&lt;/span&gt; (delimited by whitespace, includes empy line)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sentence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;paragraph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between square brackets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{&lt;/code&gt;, &lt;code&gt;}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between curly braces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between parethesises&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'&lt;/code&gt;, &lt;code&gt;'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between single quotes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"&lt;/code&gt;, &lt;code&gt;"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between double quotes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between angle braces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;`&lt;/code&gt;, &lt;code&gt;`&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block between back ticks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block&amp;nbsp;between &lt;code&gt;(&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text block&amp;nbsp;between &lt;code&gt;{&lt;/code&gt; and &lt;code&gt;}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="col-sm"&gt;
  &lt;h2&gt;Modifiers&lt;/h2&gt;
  &lt;p&gt;&lt;code&gt;&amp;lt;modifiers&amp;gt;&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;References: &lt;code&gt;:help text-objects&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Movement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a or around&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;inner&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;modifier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;modifier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;move&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;around&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;motion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;visual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;block&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;gn&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;gN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Some random&amp;nbsp;commands&lt;/h2&gt;
&lt;p&gt;Just for fun, here are some random commands using the above rules to show the
variety of actions you can perform. Some might not make sense or not work, but
they might give you some&amp;nbsp;ideas.&lt;/p&gt;
&lt;div class="container"&gt;
  &lt;div class="row"&gt;
    &lt;div class="col-sm-3"&gt;&lt;h3&gt;Motions&lt;/h3&gt;&lt;/div&gt;
    &lt;div class="col-sm-3"&gt;&lt;h3&gt;Text&amp;nbsp;objects&lt;/h3&gt;&lt;/div&gt;
    &lt;div class="col-sm-3"&gt;&lt;h3&gt;Operators on text&amp;nbsp;objects&lt;/h3&gt;&lt;/div&gt;
    &lt;div class="col-sm-3"&gt;&lt;h3&gt;Operators on&amp;nbsp;motions&lt;/h3&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="row"&gt;
    &lt;div class="col-sm-3"&gt;
      &lt;div class="row"&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;F{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;t{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;9B&lt;/code&gt;&lt;br&gt;&lt;code&gt;3/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;b&lt;/code&gt;&lt;br&gt;&lt;code&gt;T{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;{&lt;/code&gt;&lt;br&gt;&lt;code&gt;j&lt;/code&gt;&lt;br&gt;&lt;code&gt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;l&lt;/code&gt;&lt;br&gt;&lt;code&gt;g_&lt;/code&gt;&lt;br&gt;&lt;code&gt;5[(&lt;/code&gt;&lt;br&gt;&lt;code&gt;%&lt;/code&gt;&lt;br&gt;&lt;code&gt;{&lt;/code&gt;&lt;br&gt;&lt;code&gt;0F{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;T{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;10&lt;/code&gt;&lt;br&gt;&lt;code&gt;k&lt;/code&gt;&lt;br&gt;&lt;code&gt;[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;%&lt;/code&gt;&lt;br&gt;&lt;code&gt;1G&lt;/code&gt;&lt;br&gt;&lt;code&gt;[{&lt;/code&gt;&lt;br&gt;&lt;code&gt;5k&lt;/code&gt;&lt;br&gt;&lt;code&gt;0&lt;/code&gt;&lt;br&gt;&lt;code&gt;/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;1/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;2l&lt;/code&gt;&lt;/div&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;?{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;g_&lt;/code&gt;&lt;br&gt;&lt;code&gt;1h&lt;/code&gt;&lt;br&gt;&lt;code&gt;h&lt;/code&gt;&lt;br&gt;&lt;code&gt;t{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4F{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;0$&lt;/code&gt;&lt;br&gt;&lt;code&gt;t{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;$&lt;/code&gt;&lt;br&gt;&lt;code&gt;B&lt;/code&gt;&lt;br&gt;&lt;code&gt;l&lt;/code&gt;&lt;br&gt;&lt;code&gt;g_&lt;/code&gt;&lt;br&gt;&lt;code&gt;^&lt;/code&gt;&lt;br&gt;&lt;code&gt;1{&lt;/code&gt;&lt;br&gt;&lt;code&gt;2?{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;G&lt;/code&gt;&lt;br&gt;&lt;code&gt;^&lt;/code&gt;&lt;br&gt;&lt;code&gt;k&lt;/code&gt;&lt;br&gt;&lt;code&gt;1[(&lt;/code&gt;&lt;br&gt;&lt;code&gt;$&lt;/code&gt;&lt;br&gt;&lt;code&gt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;h&lt;/code&gt;&lt;br&gt;&lt;code&gt;^&lt;/code&gt;&lt;br&gt;&lt;code&gt;/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;gg&lt;/code&gt;&lt;br&gt;&lt;code&gt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;g_&lt;/code&gt;&lt;br&gt;&lt;code&gt;1e&lt;/code&gt;&lt;br&gt;&lt;code&gt;[)&lt;/code&gt;&lt;br&gt;&lt;code&gt;t{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;6/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;t{ch}&lt;/code&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="col-sm-3"&gt;
      &lt;div class="row"&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;iw&lt;/code&gt;&lt;br&gt;&lt;code&gt;ab&lt;/code&gt;&lt;br&gt;&lt;code&gt;a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;aw&lt;/code&gt;&lt;br&gt;&lt;code&gt;it&lt;/code&gt;&lt;br&gt;&lt;code&gt;i&amp;lt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;i[&lt;/code&gt;&lt;br&gt;&lt;code&gt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;aw&lt;/code&gt;&lt;br&gt;&lt;code&gt;i"&lt;/code&gt;&lt;br&gt;&lt;code&gt;a"&lt;/code&gt;&lt;br&gt;&lt;code&gt;ip&lt;/code&gt;&lt;br&gt;&lt;code&gt;iB&lt;/code&gt;&lt;br&gt;&lt;code&gt;i[&lt;/code&gt;&lt;br&gt;&lt;code&gt;a]&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;a{&lt;/code&gt;&lt;br&gt;&lt;code&gt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;a[&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;a"&lt;/code&gt;&lt;br&gt;&lt;code&gt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;i{&lt;/code&gt;&lt;br&gt;&lt;code&gt;i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;it&lt;/code&gt;&lt;br&gt;&lt;code&gt;ab&lt;/code&gt;&lt;br&gt;&lt;code&gt;i&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;a'&lt;/code&gt;&lt;/div&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;at&lt;/code&gt;&lt;br&gt;&lt;code&gt;i{&lt;/code&gt;&lt;br&gt;&lt;code&gt;is&lt;/code&gt;&lt;br&gt;&lt;code&gt;iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;aW&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;i[&lt;/code&gt;&lt;br&gt;&lt;code&gt;a{&lt;/code&gt;&lt;br&gt;&lt;code&gt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;aB&lt;/code&gt;&lt;br&gt;&lt;code&gt;ip&lt;/code&gt;&lt;br&gt;&lt;code&gt;a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;a]&lt;/code&gt;&lt;br&gt;&lt;code&gt;i"&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;lt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;ib&lt;/code&gt;&lt;br&gt;&lt;code&gt;a(&lt;/code&gt;&lt;br&gt;&lt;code&gt;iw&lt;/code&gt;&lt;br&gt;&lt;code&gt;i"&lt;/code&gt;&lt;br&gt;&lt;code&gt;a{&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;lt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;at&lt;/code&gt;&lt;br&gt;&lt;code&gt;a{&lt;/code&gt;&lt;br&gt;&lt;code&gt;ip&lt;/code&gt;&lt;br&gt;&lt;code&gt;a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;a"&lt;/code&gt;&lt;br&gt;&lt;code&gt;as&lt;/code&gt;&lt;br&gt;&lt;code&gt;i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;a{&lt;/code&gt;&lt;br&gt;&lt;code&gt;ap&lt;/code&gt;&lt;br&gt;&lt;code&gt;a&amp;lt;&lt;/code&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="col-sm-3"&gt;
      &lt;div class="row"&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;&amp;lt;aW&lt;/code&gt;&lt;br&gt;&lt;code&gt;5gua{&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;gt;4aW&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;at&lt;/code&gt;&lt;br&gt;&lt;code&gt;8&amp;gt;iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;gUis&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;gt;aW&lt;/code&gt;&lt;br&gt;&lt;code&gt;3g@aw&lt;/code&gt;&lt;br&gt;&lt;code&gt;g@i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;0ap&lt;/code&gt;&lt;br&gt;&lt;code&gt;~a(&lt;/code&gt;&lt;br&gt;&lt;code&gt;y5a]&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;0i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;gt;3ip&lt;/code&gt;&lt;br&gt;&lt;code&gt;g@a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;da"&lt;/code&gt;&lt;br&gt;&lt;code&gt;gUi[&lt;/code&gt;&lt;br&gt;&lt;code&gt;gq1i{&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;i]&lt;/code&gt;&lt;br&gt;&lt;code&gt;2g~ib&lt;/code&gt;&lt;br&gt;&lt;code&gt;g@i]&lt;/code&gt;&lt;br&gt;&lt;code&gt;gua`&lt;/code&gt;&lt;br&gt;&lt;code&gt;gUi(&lt;/code&gt;&lt;br&gt;&lt;code&gt;~8a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;is&lt;/code&gt;&lt;br&gt;&lt;code&gt;d7a[&lt;/code&gt;&lt;br&gt;&lt;code&gt;g~i(&lt;/code&gt;&lt;br&gt;&lt;code&gt;d5aw&lt;/code&gt;&lt;br&gt;&lt;code&gt;g~a}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4diW&lt;/code&gt;&lt;br&gt;&lt;code&gt;gqiw&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;4i{&lt;/code&gt;&lt;/div&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;&amp;lt;is&lt;/code&gt;&lt;br&gt;&lt;code&gt;g~iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;daW&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;aB&lt;/code&gt;&lt;br&gt;&lt;code&gt;~a)&lt;/code&gt;&lt;br&gt;&lt;code&gt;c5a&amp;lt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;gUaB&lt;/code&gt;&lt;br&gt;&lt;code&gt;ca}&lt;/code&gt;&lt;br&gt;&lt;code&gt;9g@as&lt;/code&gt;&lt;br&gt;&lt;code&gt;gu0a(&lt;/code&gt;&lt;br&gt;&lt;code&gt;~2a"&lt;/code&gt;&lt;br&gt;&lt;code&gt;ya&amp;lt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;gUa'&lt;/code&gt;&lt;br&gt;&lt;code&gt;~9a`&lt;/code&gt;&lt;br&gt;&lt;code&gt;y2is&lt;/code&gt;&lt;br&gt;&lt;code&gt;gU2i)&lt;/code&gt;&lt;br&gt;&lt;code&gt;c4i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;7ya"&lt;/code&gt;&lt;br&gt;&lt;code&gt;guaB&lt;/code&gt;&lt;br&gt;&lt;code&gt;0&amp;lt;i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;c9i'&lt;/code&gt;&lt;br&gt;&lt;code&gt;guib&lt;/code&gt;&lt;br&gt;&lt;code&gt;g@a`&lt;/code&gt;&lt;br&gt;&lt;code&gt;9g@a&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;6c9ip&lt;/code&gt;&lt;br&gt;&lt;code&gt;2g@2ab&lt;/code&gt;&lt;br&gt;&lt;code&gt;yi[&lt;/code&gt;&lt;br&gt;&lt;code&gt;1c3iW&lt;/code&gt;&lt;br&gt;&lt;code&gt;c3ap&lt;/code&gt;&lt;br&gt;&lt;code&gt;8gUi`&lt;/code&gt;&lt;br&gt;&lt;code&gt;gqit&lt;/code&gt;&lt;br&gt;&lt;code&gt;g@i[&lt;/code&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="col-sm-3"&gt;
      &lt;div class="row"&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;0d{&lt;/code&gt;&lt;br&gt;&lt;code&gt;9gu[)&lt;/code&gt;&lt;br&gt;&lt;code&gt;2yT{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;8g~?{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;2ce&lt;/code&gt;&lt;br&gt;&lt;code&gt;0gUb&lt;/code&gt;&lt;br&gt;&lt;code&gt;8g~j&lt;/code&gt;&lt;br&gt;&lt;code&gt;2c[(&lt;/code&gt;&lt;br&gt;&lt;code&gt;3&amp;gt;}&lt;/code&gt;&lt;br&gt;&lt;code&gt;3&amp;gt;gg&lt;/code&gt;&lt;br&gt;&lt;code&gt;6&amp;gt;G&lt;/code&gt;&lt;br&gt;&lt;code&gt;6~j&lt;/code&gt;&lt;br&gt;&lt;code&gt;0d[{&lt;/code&gt;&lt;br&gt;&lt;code&gt;8gU{&lt;/code&gt;&lt;br&gt;&lt;code&gt;4c[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4~h&lt;/code&gt;&lt;br&gt;&lt;code&gt;7&amp;lt;l&lt;/code&gt;&lt;br&gt;&lt;code&gt;7g@^&lt;/code&gt;&lt;br&gt;&lt;code&gt;6~/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;7yh&lt;/code&gt;&lt;br&gt;&lt;code&gt;3&amp;lt;}&lt;/code&gt;&lt;br&gt;&lt;code&gt;1&amp;lt;F{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4cw&lt;/code&gt;&lt;br&gt;&lt;code&gt;1gu[)&lt;/code&gt;&lt;br&gt;&lt;code&gt;0cB&lt;/code&gt;&lt;br&gt;&lt;code&gt;7g~[{&lt;/code&gt;&lt;br&gt;&lt;code&gt;3g~[{&lt;/code&gt;&lt;br&gt;&lt;code&gt;7yk&lt;/code&gt;&lt;br&gt;&lt;code&gt;3~k&lt;/code&gt;&lt;br&gt;&lt;code&gt;5g~[)&lt;/code&gt;&lt;br&gt;&lt;code&gt;5g@G&lt;/code&gt;&lt;br&gt;&lt;code&gt;8yt{ch}&lt;/code&gt;&lt;/div&gt;
    &lt;div class="col-4"&gt;&lt;code&gt;0g@e&lt;/code&gt;&lt;br&gt;&lt;code&gt;8&amp;gt;0&lt;/code&gt;&lt;br&gt;&lt;code&gt;6g~[(&lt;/code&gt;&lt;br&gt;&lt;code&gt;5dB&lt;/code&gt;&lt;br&gt;&lt;code&gt;9&amp;gt;T{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;0gU{&lt;/code&gt;&lt;br&gt;&lt;code&gt;3&amp;lt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;1y?{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4g@[{&lt;/code&gt;&lt;br&gt;&lt;code&gt;5~b&lt;/code&gt;&lt;br&gt;&lt;code&gt;2&amp;lt;^&lt;/code&gt;&lt;br&gt;&lt;code&gt;4&amp;gt;w&lt;/code&gt;&lt;br&gt;&lt;code&gt;4y{&lt;/code&gt;&lt;br&gt;&lt;code&gt;1&amp;lt;e&lt;/code&gt;&lt;br&gt;&lt;code&gt;8c[}&lt;/code&gt;&lt;br&gt;&lt;code&gt;6c{&lt;/code&gt;&lt;br&gt;&lt;code&gt;2g~/{pat}&lt;/code&gt;&lt;br&gt;&lt;code&gt;3cj&lt;/code&gt;&lt;br&gt;&lt;code&gt;8cT{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;3&amp;gt;%&lt;/code&gt;&lt;br&gt;&lt;code&gt;0&amp;lt;F{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;4gqB&lt;/code&gt;&lt;br&gt;&lt;code&gt;3gqT{ch}&lt;/code&gt;&lt;br&gt;&lt;code&gt;3dk&lt;/code&gt;&lt;br&gt;&lt;code&gt;5&amp;gt;[)&lt;/code&gt;&lt;br&gt;&lt;code&gt;2gqh&lt;/code&gt;&lt;br&gt;&lt;code&gt;8ce&lt;/code&gt;&lt;br&gt;&lt;code&gt;7~gg&lt;/code&gt;&lt;br&gt;&lt;code&gt;3cl&lt;/code&gt;&lt;br&gt;&lt;code&gt;4c^&lt;/code&gt;&lt;br&gt;&lt;code&gt;4c%&lt;/code&gt;&lt;br&gt;&lt;code&gt;1gq$&lt;/code&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a name="references" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;References/further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://danielmiessler.com/study/vim/"&gt;A vim Tutorial and&amp;nbsp;Primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zzapper.co.uk/vimtips.html"&gt;Best of Vim&amp;nbsp;Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://yanpritzker.com/learn-to-speak-vim-verbs-nouns-and-modifiers-d7bfed1f6b2d"&gt;Learn to speak vim — verbs, nouns, and&amp;nbsp;modifiers!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ismail.badawi.io/blog/2014/04/23/the-compositional-nature-of-vim/"&gt;The compositional nature of&amp;nbsp;Vim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rc3.org/2012/05/12/the-grammar-of-vim/"&gt;The grammar of&amp;nbsp;Vim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://michael.peopleofhonoronly.com/vim/"&gt;Vim Cheat Sheet for&amp;nbsp;Programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vim.rtorr.com/"&gt;Vim Cheat&amp;nbsp;Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fprintf.net/vimCheatSheet.html"&gt;Vim Commands Cheat&amp;nbsp;Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://takac.github.io/2013/01/30/vim-grammar/"&gt;Vim&amp;nbsp;Grammar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guidehttps://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide//https://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/"&gt;Vim Text Objects: The Definitive&amp;nbsp;Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vim.org/docs.php"&gt;Vim&amp;nbsp;documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zmievski.org/files/talks/codeworks-2009/vim-for-php-programmers.pdf"&gt;Vim for &lt;span class="caps"&gt;PHP&lt;/span&gt;&amp;nbsp;programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118"&gt;Your problem with Vim is that you don&amp;#8217;t grok&amp;nbsp;vi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Perspectives"/><category term="computing"/><category term="vim"/></entry><entry><title>Writing synthesizable Verilog</title><link href="https://jameswhanlon.com/writing-synthesizable-verilog.html" rel="alternate"/><published>2018-05-04T00:00:00+02:00</published><updated>2018-05-04T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2018-05-04:/writing-synthesizable-verilog.html</id><summary type="html">&lt;p&gt;Coding style for &lt;span class="caps"&gt;RTL&lt;/span&gt; design using Verilog / SystemVerilog. Updated&amp;nbsp;2024.&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;:&lt;/em&gt;&lt;/strong&gt;  Updated February 2024 with improvements and new&amp;nbsp;guidance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the last year, I&amp;#8217;ve started from scratch writing SystemVerilog for hardware
design. Coming from a software background where I was mainly using C/C++ and
Python, it has been interesting to experience the contrasting philosophy and
mindset associated with using a language to describe hardware circuits. Much of
this is because SystemVerilog provides little abstraction of hardware
structures, and only through disciplined/idiomatic use, can efficient designs
be implemented. A compounding issue is that complex hardware designs rely on a
complex ecosystem of proprietary&amp;nbsp;tooling.&lt;/p&gt;
&lt;p&gt;As I see it, there are three aspects to writing synthesizable SystemVerilog
code: the particular features of the language to use, the style and idioms
employed in using those features, and the tooling support for a design. Good
coding style can help achieve better results in synthesis and simulation, as
well as producing code that contains less errors and is understandable,
reusable, and easily modifiable. Many of the observations in this note relate
to coding style. The next sections give some context around the use of
SystemVerilog in digital design, or you can &lt;a href="#guidance"&gt;skip ahead&lt;/a&gt; to the&amp;nbsp;guidance.&lt;/p&gt;
&lt;h3&gt;The SystemVerilog&amp;nbsp;language&lt;/h3&gt;
&lt;p&gt;SystemVerilog (which subsumed Verilog as of the 2009 standardisation) is a
unified language, serving distinct purposes of modern hardware design. These
can be enumerated&amp;nbsp;as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Circuit design/specification at different levels of abstraction:&lt;ul&gt;
&lt;li&gt;Behavioural.&lt;/li&gt;
&lt;li&gt;Structural/register-transfer level (&lt;span class="caps"&gt;RTL&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Gate.&lt;/li&gt;
&lt;li&gt;Switch/transistor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Testbench-based&amp;nbsp;verification.&lt;/li&gt;
&lt;li&gt;Specification of formal&amp;nbsp;properties.&lt;/li&gt;
&lt;li&gt;Specification of functional&amp;nbsp;coverage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SystemVerilog provides specific features to serve each of these
purposes. For circuit specification, each level of abstraction uses a different
language subset, generally with fewer features at lower levels. Behavioural
design uses the procedural features of SystemVerilog (with little regard for the
structural realisation of the circuit). &lt;span class="caps"&gt;RTL&lt;/span&gt; design specifies a circuit in terms
of data flow through registers and logical operations. Gate- and switch-level
design use only primitive operations. Typical modern hardware design uses a mix
of register-transfer- and gate-level&amp;nbsp;design.&lt;/p&gt;
&lt;p&gt;It is interesting to note that the SystemVerilog specification does not specify
which features are synthesizable; that depends on the tooling&amp;nbsp;used.&lt;/p&gt;
&lt;h3&gt;Tooling&lt;/h3&gt;
&lt;p&gt;There is a variety of standard tooling that is used with SystemVerilog, and
indeed other hardware description languages (HDLs). This includes simulation,
formal analysis/model checking, formal equivalence checking, coverage analysis,
synthesis and physical layout, known collectively as electronic design
automation tools (&lt;span class="caps"&gt;EDA&lt;/span&gt;). Since standard &lt;span class="caps"&gt;EDA&lt;/span&gt; tooling is developed and maintained
as proprietary and closed-source software by companies like Cadence, Synopsys
and Mentor, the tooling options are&amp;nbsp;multiplied.&lt;/p&gt;
&lt;p&gt;In contrast with the open-source software ecosystems of programming languages
(for example), closed-source &lt;span class="caps"&gt;EDA&lt;/span&gt; tools do not benefit from the scale and
momentum of open projects, in the way that conventional software languages do,
with a one (or perhaps two) compilers and associated tooling such as debuggers
and program analysers. Such a fragmented ecosystem inevitably has a larger
variability in precisely how features of SystemVerilog language are implemented
and which features are not supported, particularly since there is no standard
synthesizable subset. Consequently, engineers using SystemVerilog/HDLs with
proprietary &lt;span class="caps"&gt;EDA&lt;/span&gt; tools do so conservatively, sticking to a lowest common
denominator of the language features (within their chosen synthesizable
subset), to ensure compatibility and good&amp;nbsp;results.&lt;/p&gt;
&lt;hr&gt;

&lt;p&gt;&lt;a name="guidance" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This note records rules, conventions and guidance for writing SystemVerilog
approaches that I have been observed to interact well with the supporting
tooling and to encourage good coding style and produce good synthesis results.
I owe many of these insights to the guidance of my&amp;nbsp;colleagues.&lt;/p&gt;
&lt;p&gt;This note assumes familiarity with SystemVerilog. As such it is not a
comprehensive guide to programming practices. Some of the references at the end
will serve those purposes better. The remainder is organised in the following&amp;nbsp;sections:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#types"&gt;Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#always-blocks"&gt;Always blocks&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#always_comb"&gt;always_comb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#always_comb"&gt;always_ff&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#control-flow"&gt;Control flow&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#if-statements"&gt;If&amp;nbsp;statements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#case-statements"&gt;Case&amp;nbsp;statements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#expressions"&gt;Expressions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#constants"&gt;Constants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#x-values"&gt;X&amp;nbsp;values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#naming"&gt;Naming&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#naming-prefixes-suffixes"&gt;Prefixes and&amp;nbsp;suffixes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#signal-naming"&gt;Signal&amp;nbsp;naming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generate-naming"&gt;Generate block&amp;nbsp;naming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#code-structure"&gt;Code structure&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#modules"&gt;Modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#packages"&gt;Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#assertions"&gt;Assertions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#preprocessor"&gt;Preprocessor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#formatting"&gt;Formatting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name="types" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Types&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;logic&lt;/code&gt; should be used to declare point-to-point nets, variables and ports.&lt;/strong&gt;
This is because logic is checked at compile time for multiple drivers. Note
that variables are entities driven by procedural assignments (in always
blocks), whereas nets occur in any other forms of assignment (continuous,
primitive outputs and module ports). An exception to this is when integrating
external &lt;span class="caps"&gt;IP&lt;/span&gt; that uses wire types where some sparing use of&amp;nbsp;the &lt;code&gt;wire&lt;/code&gt; type may
be required for consistency.&lt;sup id="fnref:logic-wire-reg"&gt;&lt;a class="footnote-ref" href="#fn:logic-wire-reg"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multiply-driven nets should be declared using wire.&lt;/strong&gt; This is&amp;nbsp;because &lt;code&gt;wire&lt;/code&gt;
data types permit multiple&amp;nbsp;drivers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Combined logic declarations and assignment statements are not allowed.&lt;/strong&gt; The behaviour of these is to assign
a value at time 0, which is not synthesizable. Continuous assignment after time 0, which is the typical intention,
requires a separate assignment. Note that a combined assignment with a wire declaration behaves differently
and is equivalent to a separate continuous&amp;nbsp;assignment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assignment of a logic net at time 0, not allowed.&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;32&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Correct way to continuously drive a logic net.&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;32&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Wire declarations can use an initial value to specify a continuous&lt;/span&gt;
&lt;span class="c1"&gt;// assignment.&lt;/span&gt;
&lt;span class="kt"&gt;wire&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Same behaviour as above declaration.&lt;/span&gt;
&lt;span class="kt"&gt;wire&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Structures and unions must always be fully packed.&lt;/strong&gt; This applies
to their members recursively. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;packed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Packed structure.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;valid_t&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Packed array.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;parity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bus_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="always-blocks" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Always&amp;nbsp;blocks&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;always_ff&lt;/code&gt;, &lt;code&gt;always_latch&lt;/code&gt; and &lt;code&gt;always_comb&lt;/code&gt; constructs should be used instead of the old-style always statement
since they provide extra compile-time checking.&lt;sup id="fnref:always-blocks"&gt;&lt;a class="footnote-ref" href="#fn:always-blocks"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name="always_comb" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;always_comb&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;always_comb&lt;/code&gt; instead&amp;nbsp;of &lt;code&gt;always&lt;/code&gt; for combinatorial logic.&lt;/strong&gt;&amp;nbsp;The
&lt;code&gt;always_comb&lt;/code&gt; statement allows tools to check that it does not contain any
latched state and that no other processes assign to variables appearing on the
left-hand side. (It&amp;#8217;s worth checking the &lt;span class="caps"&gt;LRM&lt;/span&gt; for details of of the other
differences.) The use of&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; block is also a much clearer
indication of a combinatorial block that the use&amp;nbsp;of &lt;code&gt;=&lt;/code&gt; as opposed&amp;nbsp;to &lt;code&gt;&amp;lt;=&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Always provide an initial value.&lt;/strong&gt; A latch will be inferred if there exists a
control-flow path in which a value of a signal is not set.&amp;nbsp;Since &lt;code&gt;always_comb&lt;/code&gt;
specifically precludes the creation of latches, doing so will cause a warning
or error in simulation or synthesis. For example, the following code implies a
latch since there is no assignment&amp;nbsp;to &lt;code&gt;foo&lt;/code&gt; when the condition is not&amp;nbsp;true.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To prevent this, always provide an initial value as the first line of a&amp;nbsp;block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Avoid reading and writing a signal in&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; block.&lt;/strong&gt;
Avoid reading and writing a signal in&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; block. The sensitivity
list only includes variables that are read in expressions or functions and it
excludes variables that are also written to. According to these restrictions, a
variable that is read and written in a block is excluded from the sensitivity
list, and activation of the block will be dependent on other variables.
However, this style can cause some tools to warn of a simulation-synthesis
mismatch (presumably because they apply conservative rules from older versions
of the language&amp;nbsp;standard).&lt;/p&gt;
&lt;p&gt;In the following code, the block is triggered only when the the&amp;nbsp;right-hand-side
&lt;code&gt;foo&lt;/code&gt; changes, rather than entering a feedback loop where it shifts&amp;nbsp;continuously:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To avoid reading and&amp;nbsp;writing &lt;code&gt;foo&lt;/code&gt; in the same block and possible warnings
from tools, a new signal can be&amp;nbsp;introduced:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;next_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Where possible extract logic&amp;nbsp;into &lt;code&gt;assign&lt;/code&gt; statements.&lt;/strong&gt; Extract single
assignments to a variable into a&amp;nbsp;separate &lt;code&gt;assign&lt;/code&gt; statement, where it is
possible to do so. This approach uses the features of SystemVerilog
consistently, rather than using two mechanisms to achieve the same effect. This
makes it clear that&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; is used to introduce sequentiality.
Another opportunity to move logic into&amp;nbsp;separate &lt;code&gt;assign&lt;/code&gt; statements is with
complex expressions, such as the Boolean value for a conditional statement.
Doing this makes the control flow structure clearer, potentially provide
opportunities for reuse, and provides a separate signal when inspecting the
signals in a waveform&amp;nbsp;viewer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid unnecessary sequentiality.&lt;/strong&gt; It is easy to add statements to&amp;nbsp;an
&lt;code&gt;always_comb&lt;/code&gt; to expand its behaviour, but this should only be done when there
are true sequential dependencies between statements in the block. In general,
parallelism should be exposed where ever possible. In the the following
example, the sequentiality is not necessary since the&amp;nbsp;output &lt;code&gt;set_foo&lt;/code&gt; depends
independently on the various&amp;nbsp;conditions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;signal_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal_c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;signal_d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Clearly the sequencing of the conditions is not necessary, so the block could
be transformed to separate the logic for each condition into separate parallel
processes (extracting&amp;nbsp;into &lt;code&gt;assign&lt;/code&gt; statements as per the rule above) and
explicitly combine them with the implied logical disjunction of the original&amp;nbsp;block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;condition_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signal_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signal_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signal_c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signal_d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;signal_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;set_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is &lt;a href="https://www.veripool.org/papers/verilator_philips_internals.pdf"&gt;recommended&lt;/a&gt; by the author of Verilator to split&amp;nbsp;up
&lt;code&gt;always&lt;/code&gt; blocks (combinatorial or sequential) so they contain as few
statements as possible. This allows Verilator the most freedom to order the
code to improve execution performance. Presumably, this provides similar
freedoms to other&amp;nbsp;simulators.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Drive one signal per block.&lt;/strong&gt; With complex control flow statements, it is
tempting to use a&amp;nbsp;single &lt;code&gt;always_comb&lt;/code&gt; block to drive multiple signals. In some
circumstances, there may be good reasons to do this, such as when many output
signals are used in a similar way, but in the general case, splitting each
signal into a separate block makes it clear what logic involved in driving that
signal, and as such, facilitates further&amp;nbsp;simplification.&lt;/p&gt;
&lt;p&gt;An additional reason to avoid driving multiple signals&amp;nbsp;per &lt;code&gt;always_comb&lt;/code&gt; block
is that &lt;a href="https://www.veripool.org/wiki/verilator"&gt;Verilator&lt;/a&gt; can infer a dependence between two signals,
leading to false circular combinatorial loops. In these cases, it issues an
&lt;a href="https://www.embecosm.com/appnotes/ean6/html/ch07s02s07.html"&gt;&lt;code&gt;UPOPTFLAT&lt;/code&gt; warning&lt;/a&gt; and cannot optimise the path, leading to
reduced emulation performance. Generally, fixing warnings pertaining to
unoptimisable constructs can improve Verilator&amp;#8217;s simulation performance by &lt;a href="https://www.veripool.org/papers/verilator_philips_internals.pdf"&gt;up
to a factor of two&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The&amp;nbsp;process:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Can be written as two independent&amp;nbsp;processes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="always_ff" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;always_ff&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;always_ff&lt;/code&gt; instead&amp;nbsp;of &lt;code&gt;always&lt;/code&gt; for sequential logic.&lt;/strong&gt; Similarly&amp;nbsp;to
&lt;code&gt;always_comb&lt;/code&gt;, use&amp;nbsp;of &lt;code&gt;always_ff&lt;/code&gt; permits tools to check that the procedure
only contains sequential logic behaviour (no timing controls and only one event
control) that variables on the left-hand side are not written to by any other
process, and makes clear the intent for sequential logic behaviour with
non-blocking&amp;nbsp;assignments, &lt;code&gt;&amp;lt;=&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid adding logic to non-blocking assignments.&lt;/strong&gt; This is primarily a matter
of taste, but having non-blocking assignments&amp;nbsp;in &lt;code&gt;always_ff&lt;/code&gt; blocks only from a
logic signal name, rather than a logical expression, keeps the block simple and
limits combinatorial logic&amp;nbsp;to &lt;code&gt;always_comb&lt;/code&gt; blocks&amp;nbsp;and &lt;code&gt;assign&lt;/code&gt; statements
elsewhere in the module. Since&amp;nbsp;synthesizable &lt;code&gt;always_ff&lt;/code&gt;s are additionally
restricted in that variables assigned to must have a reset condition of a
constant value, maintaining this clarity aids the designer. Having separate
combinatorial blocks is also useful since it allows the logic signal driving a
flip-flop as well as the registered value to be apparent in a waveform viewer,
particularly when clock gates are&amp;nbsp;used.&lt;/p&gt;
&lt;p&gt;A typical pattern when implementing combinatorial logic and registers is to
define the set and clear conditions in&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; and register the value
in an&amp;nbsp;accompanying &lt;code&gt;always_ff&lt;/code&gt;, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bit_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bit_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clear_condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bit_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bit_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Registers should always be reset to a constant value.&lt;/strong&gt; Without being reset,
a flip flop will drive X on its output, which can lead to
simulation-versus-synthesis mismatches, potentially obscuring bugs. Having
registers initialised with a defined value precludes these kinds of mismatches.
In the above&amp;nbsp;example, &lt;code&gt;bit_q&lt;/code&gt; is correctly initialised to&amp;nbsp;0.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid using synchronous-reset registers.&lt;/strong&gt; These type of flip flops are not
typically used because there are circumstances when a clock is not available
and reset-to-clock paths are not timed in the physical implementation. In cases
where area and power are constrained, non-reset flip flops can instead be
deployed for better&amp;nbsp;savings.&lt;/p&gt;
&lt;p&gt;In certain circumstances when it is appropriate to use synchronous-reset registers, then
&lt;strong&gt;avoid mixing synchronous and asynchronous reset signals&lt;/strong&gt;.
A reset signal&amp;nbsp;(eg &lt;code&gt;i_rst&lt;/code&gt;) should not be used as a
synchronous reset for one set of registers and an asynchronous reset for another set. This is because the resets
must be controlled differently by &lt;span class="caps"&gt;DFT&lt;/span&gt; control logic, and use of a single signal may obscure the designer&amp;nbsp;intent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid using non-reset registers.&lt;/strong&gt; To avoid issues with X values in a design
as far as possible, non-reset registers should only be used when specifically
required to save area and power, such as for the storage elements of a register
file. In certain circumstances when it is appropriate to use non-reset
registers, then &lt;strong&gt;define non-reset registers in a&amp;nbsp;separate &lt;code&gt;always_ff&lt;/code&gt; block&lt;/strong&gt;.
For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// A non-reset register.&lt;/span&gt;
&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bit_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When non-reset registers are used, a separate form of reset must be
provided.&lt;/strong&gt; In the example of a register file, a broadcast write could be used
to initialise the contents to a known&amp;nbsp;state.&lt;/p&gt;
&lt;p&gt;&lt;a name="control-flow" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Control&amp;nbsp;flow&lt;/h2&gt;
&lt;p&gt;&lt;a name="if-statements" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;If&amp;nbsp;statements&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Avoid mixing block control flow with Boolean expressions.&lt;/strong&gt; This is because
it make it harder for structural coverage analysis tools to break down complex
conditions into manageable sub terms, or even that analysis will ignore
important conditional context of&amp;nbsp;expressions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace mixed block control flow and boolean expressions:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;// With a pure control flow approach:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;// Or even better collapsed into a single Boolean expression:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use if-else-if statements to implement priority encoders.&lt;/strong&gt; Although&amp;nbsp;a
&lt;code&gt;priority case&lt;/code&gt; statement can be used to do this, it is easier for designers to
recognise a priority encoder when it is written as an if-else-if statement. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace an unqualified case:&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;hold:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;

&lt;span class="c1"&gt;// With an if-else statement:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Do not use qualifiers&amp;nbsp;with &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt;-&lt;code&gt;if&lt;/code&gt; statements.&lt;/strong&gt; The default
behaviour of if statements is that&amp;nbsp;of &lt;code&gt;priority&lt;/code&gt;, meaning that one condition is
matched, the conditions are evaluated in sequence and only the body of the
first matching condition is evaluated.&amp;nbsp;For &lt;code&gt;unique&lt;/code&gt; and &lt;code&gt;unique0&lt;/code&gt; variants&amp;nbsp;of
&lt;code&gt;if&lt;/code&gt; statements (one or no matching conditions, which can be evaluated in
parallel), use&amp;nbsp;a &lt;code&gt;unique&lt;/code&gt;-qualified case statement instead. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace a unique if:&lt;/span&gt;
&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;// With a unique case:&lt;/span&gt;
&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b01&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b10&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note&amp;nbsp;that &lt;code&gt;if&lt;/code&gt; statements are X-optimistic in that a condition that evaluates
to an X is treated as if it were a zero. This behaviour has drawbacks and
benefits, but should be carefully considered since it can be a cause of
divergence in behaviour between simulation and synthesis. In contrast, case
statements do not select conditions with an input X&amp;nbsp;value.&lt;/p&gt;
&lt;p&gt;&lt;a name="case-statements" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Case&amp;nbsp;statements&lt;/h3&gt;
&lt;p&gt;All case statements should include a qualifier for additional checking and guidance to synthesis. The qualifiers&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;unique&lt;/code&gt; to specify that all valid conditions have been listed, exactly one
  condition will always match and the conditions can be evaluated in parallel.
  A violation is reported in a given cycle if no case conditions match or more
  than one case condition is&amp;nbsp;matched.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;priority&lt;/code&gt; to specify that all valid conditions have been listed, that they
  are evaluated in sequence and only the body of the first matching case is
  evaluated. A violation is only reported if no case conditions match in a given&amp;nbsp;cycle.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The behaviour of an unqualified case statement is that of priority, but without
the requirement for any case item expressions to match and the corresponding
violation check. Because case statements are typically used to represent
parallel choices, an unqualified case does not clearly indicate whether the
designer has intended the case be priority or parallel. Adding a qualifier
makes this explicit (leading to the right synthesis result) and adds&amp;nbsp;checking.&lt;/p&gt;
&lt;p&gt;It is important to have checking of case behaviour: if a violation is reported
during simulation, then this indicates a mismatch between the behaviour of
simulation and synthesis, which means the synthesized design will not
necessarily be the same as the &lt;span class="caps"&gt;RTL&lt;/span&gt; design being simulated, thereby invalidating
the&amp;nbsp;verification.&lt;/p&gt;
&lt;p&gt;Note that if a case condition contains a list of expressions, it is not a
violation of uniqueness if more than one expression matches since they are
selecting the same&amp;nbsp;statement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do not&amp;nbsp;use &lt;code&gt;unique0&lt;/code&gt; as a case qualifier.&lt;/strong&gt; Despite this qualifier being in
the SystemVerilog &lt;span class="caps"&gt;LRM&lt;/span&gt; for more than a decade, tool support&amp;nbsp;for &lt;code&gt;unique0&lt;/code&gt; is
patchy and sometimes absent. This suggests that adoption&amp;nbsp;of &lt;code&gt;unique0&lt;/code&gt; is low, so
the &lt;span class="caps"&gt;EDA&lt;/span&gt; companies have not needed to support it comprehensively. As&amp;nbsp;such,
&lt;code&gt;unique0&lt;/code&gt; should not be used, and instead a unique case with an empty default
should be used, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace a unique0 case:&lt;/span&gt;
&lt;span class="n"&gt;unique0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;

&lt;span class="c1"&gt;// With a unique case and empty default:&lt;/span&gt;
&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Empty default disables the no-matching-condition violation&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// check, making the unique case statement behave like a unique0&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// case.&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;If in doubt, use priority case with a default.&lt;/strong&gt; If a designer is not completely sure whether the case conditions
are always matches and/or are parallel, then they should use a priority case with a default. This way, the
logic simulated results will always match the synthesized&amp;nbsp;logic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Synopsys full_case/parallel_case compiler directives should not be
used.&lt;/strong&gt; Instead, use either&amp;nbsp;the &lt;code&gt;unique&lt;/code&gt; or &lt;code&gt;priority&lt;/code&gt; qualifiers, as
shown in the table&amp;nbsp;below:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col"&gt;SystemVerilog construct&lt;/th&gt;
  &lt;th scope="col"&gt;Approximate Synopsys pragma equivalent&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;unique case&lt;/code&gt; without default&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;full_case&lt;/code&gt; and &lt;code&gt;parallel_case&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;priority case&lt;/code&gt; without default&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;full_case&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;unique case&lt;/code&gt; with default&lt;/td&gt;
  &lt;td&gt;&lt;code&gt;parallel_case&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;priority case&lt;/code&gt; with default&lt;/td&gt;
  &lt;td&gt;No equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;The use of defaults in case statements should be used sparingly since they
can obscure designer intent, prevent violation checks from being performed and
change synthesis&amp;nbsp;results.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note that default conditions are matched only if no case condition matches, so
they can be used to cover all other case conditions that are not explicitly
specified. Their inclusion in a case statement must be considered&amp;nbsp;carefully.&lt;/p&gt;
&lt;p&gt;Defaults can be used to assign a value to a combinatorial signal to avoid
latches from being inferred, however it is clearer to provide a default value
at the beginning of&amp;nbsp;an &lt;code&gt;always_comb&lt;/code&gt; block (see above). This is because it is
conventional to add&amp;nbsp;a &lt;code&gt;default&lt;/code&gt; at the end of&amp;nbsp;a &lt;code&gt;case&lt;/code&gt; statement, which obscures
the effect of a default, possibly leading to bugs. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assign a default at the top of the block.&lt;/span&gt;
&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;STATE_A:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATE_B&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;STATE_B:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATE_C&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;STATE_Z:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATE_A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// No need for a default here.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If a condition were to be added around the above case statement, the default
value assignment&amp;nbsp;of &lt;code&gt;next_state&lt;/code&gt; would remain at the top of the block. On the
other hand, if the default value assignment were done in a default of the case,
and not moved out, a latch would be&amp;nbsp;inferred.&lt;/p&gt;
&lt;p&gt;Defaults can be used to trap unexpected case values. However, by&amp;nbsp;specifying
&lt;code&gt;unique&lt;/code&gt; or &lt;code&gt;priority&lt;/code&gt;, unexpected case values will cause either of the
no-matching-condition or multiple-conditions matching violation checks to fire.
For example, with a one-hot case select, it is not necessary to add&amp;nbsp;a
&lt;code&gt;default: $error(...);&lt;/code&gt; case condition to trap values that are not one&amp;nbsp;hot.&lt;/p&gt;
&lt;p&gt;There is&amp;nbsp;no &lt;code&gt;priority0&lt;/code&gt; case statement qualifier, so it is reasonable to
include an&amp;nbsp;empty &lt;code&gt;default&lt;/code&gt; with&amp;nbsp;a &lt;code&gt;priority case&lt;/code&gt; to disable the
no-matching-condition violation check, similarly&amp;nbsp;to &lt;code&gt;unique case&lt;/code&gt;. However, it
is more conventional to use&amp;nbsp;an &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt;-&lt;code&gt;if&lt;/code&gt; to implement a priority
encoder. Example of a case-based priority&amp;nbsp;encoder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;VALUE_A:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;VALUE_B:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;VALUE_C:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Use an empty default with priority when there are no matching&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// conditions, but could the case equally be written with an&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// if-then-if statement?&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Empty defaults might also be used to plug coverage holes. This can occur when
the coverage tool expects to see all input combinations and does not understand
when these are prevented by design, eg with one-hot encoding. Adding an empty
default may plug this coverage hole, however doing this will typically change
the synthesis results because it implies an additional decode/control signal to
select the default block, which is probably not what the designer intended. In
such a situation, designers should add coverage waivers where a lack of a
default case creates a coverage hole rather than changing the &lt;span class="caps"&gt;RTL&lt;/span&gt; to add an
empty default&amp;nbsp;case.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Since the case is unique, the empty default is not necessary and will be&lt;/span&gt;
&lt;span class="c1"&gt;// dead code, and may change the synthesis results.&lt;/span&gt;
&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;four_bit_one_hot_select&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0010&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0100&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// This default is not necessary if the case conditions are&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// activated every cycle.&lt;/span&gt;
&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;unique case (1'b1)&lt;/code&gt; for one-hot conditions.&lt;/strong&gt; For example, a one-hot
multiplexer can be&amp;nbsp;written:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_one_hot_mux3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;i_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;i_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;i_c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_sel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;o_out&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i_sel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i_sel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i_sel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As an aside, it is convenient to define a one-hot encoding in&amp;nbsp;a &lt;code&gt;union&lt;/code&gt; type
with&amp;nbsp;another &lt;code&gt;struct&lt;/code&gt; to provide named access to each member. For&amp;nbsp;example,
&lt;code&gt;status_q&lt;/code&gt; above could be redefined&amp;nbsp;as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;STATUS_START&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;STATUS_END&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;STATUS_ERROR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b100&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_enum_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;union&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;packed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;status_enum_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;packed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Bear in mind however that this union introduces potential for the control structure to correspond incorrectly with
the enumeration, which may introduce bugs into the&amp;nbsp;design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Minimise the amount of logic inside a case statement.&lt;/strong&gt; The rationale for
this is similar to extracting logic&amp;nbsp;from &lt;code&gt;always_comb&lt;/code&gt; blocks&amp;nbsp;into &lt;code&gt;assign&lt;/code&gt;
statements where possible: to make the control flow structure clearer to the
designer and tooling, and to provide opportunities for reuse or
further simplification. For example, avoid&amp;nbsp;nesting &lt;code&gt;case&lt;/code&gt; statements:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mode_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nl"&gt;stat_start:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;unique0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b000&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="mh"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATUS_ERROR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATUS_END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nl"&gt;status_end:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nl"&gt;status_error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And instead extract a&amp;nbsp;nested &lt;code&gt;case&lt;/code&gt; into a separate process, providing a
result signal to use in the parent&amp;nbsp;case:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;status_q&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;next_status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;status_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_next_status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode_q&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;start_next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;state_q&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;mode_q&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;inside&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;4&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b000?,&lt;/span&gt;
&lt;span class="s1"&gt;    4&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;b0&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nt"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;STATUS_ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;STATUS_END&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;endcase&lt;/span&gt;
&lt;span class="nt"&gt;end&lt;/span&gt;

&lt;span class="nt"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;case&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;status_start&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;next_status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_next_status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;status_end&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;status_q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;status_error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;endcase&lt;/span&gt;
&lt;span class="nt"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Although this example seems simple,&amp;nbsp;the &lt;code&gt;case&lt;/code&gt;-based logic driving a state
machine can quickly become&amp;nbsp;complicated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;case inside&lt;/code&gt; for matching with don&amp;#8217;t cares.&lt;/strong&gt; For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;localparam&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_done&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;p_init&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;p_end&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;p_error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b00&lt;/span&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b01&lt;/span&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Unless matching&amp;nbsp;upon &lt;code&gt;'bX&lt;/code&gt; or &lt;code&gt;'bZ&lt;/code&gt; is genuinely required,&amp;nbsp;then &lt;code&gt;casex&lt;/code&gt; or
&lt;code&gt;casez&lt;/code&gt; should not be used.&lt;/strong&gt; Instead,&amp;nbsp;the &lt;code&gt;case inside&lt;/code&gt; construct should be
used to indicate don&amp;#8217;t-care bits in the case select as per the previous&amp;nbsp;example.&lt;/p&gt;
&lt;p&gt;&lt;a name="expressions" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Expressions&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Make operator associativity explicit.&lt;/strong&gt; This is to avoid any ambiguity over
the ordering of operators. In particular, always bracket the condition of a
ternary/conditional expression&amp;nbsp;(&lt;code&gt;?:&lt;/code&gt;), especially if you are nesting them,
since they associate left to right, and all other arithmetic and logical
operators associate right to&amp;nbsp;left.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cond_a&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cond_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;cond_c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="n"&gt;e3&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inside&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b01&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Make expression bit lengths explicit.&lt;/strong&gt; Although the SystemVerilog
specification provides rules for the extension of operands as inputs to binary
operations and assignments, these are complicated and not always obvious. In
particular, the extension is determined either by the operands or by the
context of the expression. Since there may be inconsistencies between tools,
particularly between simulation and synthesis, explicitly specifying expression
bit widths avoids these issues and makes the intent obvious. For example, pad
the result of a narrower expression for&amp;nbsp;assignment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;24&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;op1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op2&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Use an explicit type cast to specify the width of an intermediate expression
(note that integer literals are interpreted as 32-bit&amp;nbsp;integers):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;value_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value_t&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="mh"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Special care should be taken with sub expressions, since their result length is
determined automatically by the width of the largest operand. For example,
without an explicit type cast to a 17-bit result&amp;nbsp;around &lt;code&gt;a + b&lt;/code&gt;, the carry out
bit would be&amp;nbsp;lost:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;15&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum_t&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Capture carry out bits (even if they are unused) so the left-hand-side
assignment width matches the full width of the right hand side. Using a prefix&amp;nbsp;like &lt;code&gt;unused_&lt;/code&gt; makes the process of signing off any related warnings with the
downstream synthesis and physical build&amp;nbsp;simpler:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;unused_co&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Exceptions to this rule can be made for the common constants 0, 1 and -1 to be
specified&amp;nbsp;as &lt;code&gt;integer&lt;/code&gt; literals, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;signed&lt;/code&gt; types for signed arithmetic, and avoid implementing signed
arithmetic with manual sign extensions.&lt;/strong&gt; SystemVerilog uses the signedness of
an expression to determine how to extend its width (as well as inferring
signedness of parent expressions). Since the rules for sign determination is
similar to expression size but not the same, making it explicit avoids errors.
It also facilitates the use of optimised arithmetic implementations in
synthesis, particularly with multipliers. The following example (adapted from
&lt;a href="http://www.sutherland-hdl.com/papers/2006-SNUG-Boston_standard_gotchas_presentation.pdf"&gt;this presentation&lt;/a&gt;) shows how these rules can be&amp;nbsp;confusing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;signed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;signed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Unsigned addition due to unsigned ci.&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Signed addition, but ci == 1&amp;#39;b1 will be&lt;/span&gt;
&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="c1"&gt;// sign extended to 4&amp;#39;b1111 or -1.&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;({&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Safe sign extension.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that an operation is only considered signed if all of the operands are
signed, and that literal values can be specified as signed, for&amp;nbsp;example:
&lt;code&gt;2'sb11&lt;/code&gt; is -1 in 2&amp;nbsp;bits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid splitting arithmetic between statements or modules.&lt;/strong&gt; This facilitates
optimisation during synthesis, for example, to choose or generate an optimised
adder implementation for the given set of operands and carry ins/outs. Instead&amp;nbsp;of:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;4&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;int_sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;int_sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;unused_co&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;int_sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All of the arithmetic contributing&amp;nbsp;to &lt;code&gt;sum&lt;/code&gt; can be written in a single&amp;nbsp;expression:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;unused_co&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Do not mix bitwise and logical operator in the same expression.&lt;/strong&gt; There are
different precedence rules for the types, so the behaviour may not be what is
expected. Instead, break up the expression to make it explicit what the
intended behaviour&amp;nbsp;is.&lt;/p&gt;
&lt;p&gt;&lt;a name="constants" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Constants&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Avoid magic numbers.&lt;/strong&gt; All numeric constants, with the exception of zero and
one (for incrementing) should be defined symbolically. All assignment to
constants must be sized correctly to avoid width-mismatch warnings that must be
signed off later in the&amp;nbsp;flow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constants should be declared inside packages.&lt;/strong&gt; Derived constants with a
meaning specific to a module should be defined in the appropriate scope of the&amp;nbsp;module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constants assigned to&amp;nbsp;an &lt;code&gt;enum&lt;/code&gt; port must be of the&amp;nbsp;same &lt;code&gt;enum&lt;/code&gt; type.&lt;/strong&gt; Not
doing so relies on an implicit conversion, which can have inconsistent
behaviour between tools. Assign&amp;nbsp;an &lt;code&gt;enum&lt;/code&gt; value directly, or by using a static
cast. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="n"&gt;m_foo_pkg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enum_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;endpackage&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_foo_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;enum_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;m_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Tie the input to a constant value using the enum type, rather than&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// via a value of any other type.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_foo_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Be explicit when assigning values to nets and variables.&lt;/strong&gt; For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;127&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Explicitly 32 bits wide, decimal 0 assigment.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;128&lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Explicitly 32 bits wide, binary 0 assignment.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;128&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Avoid.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// A user-defined type.&lt;/span&gt;
&lt;span class="n"&gt;foo_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// An implicit cast is acceptable.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;&amp;#39;d5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// But an explicit one is best.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="mh"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the exception&amp;nbsp;of &lt;code&gt;'0&lt;/code&gt;, unsized literal single-bit values (unsigned and
without a radix) in assignments should not be used in combinatorial logic,
since they can be misinterpreted. They appear similar to explicit assignments
with a radix, yet represent very different values. For&amp;nbsp;example, &lt;code&gt;'1&lt;/code&gt; looks
similar&amp;nbsp;to &lt;code&gt;'d1&lt;/code&gt; but encodes the value $2^n - 1$ where $n$ is the width of the
variable being assigned&amp;nbsp;to.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;15&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Sets data to 16&amp;#39;hFFFF, not 16&amp;#39;h0001.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;&amp;#39;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Clearer and harder to misinterpret.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;16&amp;#39;hFFFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The replication operator should be used to set all bits to a value.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Equivalent to above assigment&lt;/span&gt;

&lt;span class="c1"&gt;// Acceptable since repeated zeroes are still zero.&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;&amp;#39;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;16&amp;#39;h0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Equivalent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="x-values" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;X&amp;nbsp;values&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Assignment&amp;nbsp;of &lt;code&gt;X&lt;/code&gt; values as don&amp;#8217;t care values should be avoided.&lt;/strong&gt; This is
for similar reasons for not using non-reset registers, which can lead to
simulation-versus-synthesis mismatches, potentially obscuring bugs. However, if
it can be demonstrated that use of X values can provide better QoR in the
physical build of a block, specific and limited use&amp;nbsp;of &lt;code&gt;X&lt;/code&gt; values can be&amp;nbsp;justified.&lt;/p&gt;
&lt;p&gt;&lt;a name="naming" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Naming&lt;/h2&gt;
&lt;p&gt;Clear and consistent naming is important for a design to be easily understood
and maintainability by a designer, but naming must facilitate easy manipulation
by various tools in the &lt;span class="caps"&gt;RTL&lt;/span&gt; and physical design&amp;nbsp;flows.&lt;/p&gt;
&lt;p&gt;During &lt;span class="caps"&gt;RTL&lt;/span&gt; debug, names should allow simple sorting and searching in a
wave viewer. By using common prefixes for related signals, sorting will place
them together. Similarly, common substrings are useful to filter a subset of
signals over, for example to select a set of registers or similar signals
different in pipeline&amp;nbsp;stages.&lt;/p&gt;
&lt;p&gt;Throughout the physical design flows, names must allow sensible flattening. It
is typical for synthesis to flatten the hierarchical structure and consequently
symbol names are derived from their place in the module hierarchy. A suitable
naming scheme really only requires consistency across a design. As an example,
a flip-flop clock pin might be&amp;nbsp;named
&lt;code&gt;u_toplevel_u_submodule_p0_signal_q_reg_17_/CK&lt;/code&gt; corresponding to the&amp;nbsp;register
&lt;code&gt;u_toplevel/u_submodule/p0_signal_q[17]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Names should be meaningful, whilst avoiding excessive verbosity.&lt;/strong&gt; For&amp;nbsp;example,
&lt;code&gt;n3&lt;/code&gt; should be avoided as it lacks meaning&amp;nbsp;whereas &lt;code&gt;floating_point_opcode_bus&lt;/code&gt; is
excessively&amp;nbsp;long. &lt;code&gt;fp_opcode&lt;/code&gt; is a reasonable&amp;nbsp;compromise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid using C/C++/Verilog/SystemVerilog/&lt;span class="caps"&gt;VHDL&lt;/span&gt; keywords as names.&lt;/strong&gt; Even if
they are not reserved names in the language being used in that file. For&amp;nbsp;example: &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;unsigned&lt;/code&gt;, &lt;code&gt;task&lt;/code&gt;, &lt;code&gt;register&lt;/code&gt; or &lt;code&gt;asm&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All names must be all lower case and underscore separated.&lt;/strong&gt;
For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="n"&gt;m_cpu&lt;/span&gt;;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="n"&gt;m_cpu_pkg&lt;/span&gt;;
&lt;span class="n"&gt;logic&lt;/span&gt; &lt;span class="n"&gt;unused_co&lt;/span&gt;
&lt;span class="n"&gt;logic&lt;/span&gt; &lt;span class="n"&gt;p3_ctrl&lt;/span&gt;
&lt;span class="n"&gt;logic&lt;/span&gt; &lt;span class="n"&gt;p4_prod_q&lt;/span&gt;
&lt;span class="n"&gt;begin&lt;/span&gt; : &lt;span class="n"&gt;ecc_encode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="naming-prefixes-suffixes" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Prefixes and&amp;nbsp;suffixes&lt;/h3&gt;
&lt;p&gt;Name prefixes are generally used to indicate object types (such as module
instances, flip flops, ports etc), and suffixes are generally used to convey
semantic information. A good standard set of prefixes and suffixes are
enumerated&amp;nbsp;below:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col" style="width:20%"&gt;Prefix&lt;/th&gt;
  &lt;th scope="col"&gt;Usage&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;i_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Input port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;o_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Output port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;io_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Bidirecitonal (inout) port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;u_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Module instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;m_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Module definition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;p_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Parameter/localparam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;g_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Generate block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;[a-z][0-9]_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Pipeline stage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;unused_&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Unused signal for lint signoff&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
&lt;thead&gt;
  &lt;th scope="col" style="width:20%"&gt;Suffix&lt;/th&gt;
  &lt;th scope="col"&gt;Usage&lt;/th&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_clk&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Clock signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_gclk&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Gated clock signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_rst&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Reset signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_q&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Signal driven from a flip flop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_n&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Active-low signal&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_t&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Type via a typedef&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_pkg&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;code&gt;_if&lt;/code&gt;&lt;/td&gt;
  &lt;td&gt;Interface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Where signals are both active-low and require a suffix from elsewhere in the
table,&amp;nbsp;the &lt;code&gt;_n&lt;/code&gt; suffix should be appended without an extra underscore. For&amp;nbsp;example, &lt;code&gt;_q&lt;/code&gt; becomes &lt;code&gt;_qn&lt;/code&gt; for an active-low flop output,&amp;nbsp;and &lt;code&gt;_clk&lt;/code&gt; becomes
&lt;code&gt;_clkn&lt;/code&gt; for an inverted&amp;nbsp;clock.&lt;/p&gt;
&lt;p&gt;The following code example shows appropriate usage of the above prefix and
suffix&amp;nbsp;guidelines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_ctrl_fsm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;i_ready&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;i_done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;o_control&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;LOAD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b110&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;DONE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b001&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;state_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;state_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_control&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;always_comb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state_q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;IDLE:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_ready&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOAD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;LOAD:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOAD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;DONE:&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IDLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;endcase&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Another example illustrates the use of the pipeline prefix,&amp;nbsp;using &lt;code&gt;e&lt;/code&gt; to denote
an external signal&amp;nbsp;and &lt;code&gt;p&lt;/code&gt; an internal&amp;nbsp;one:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_mempipe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;i_e1_valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_e1_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_e2_data&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;p2_valid_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;31&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p3_data_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;p3_data_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;32&amp;#39;h00000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e2_valid_q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;p3_data_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_e2_data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p3_data_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="signal-naming" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Signal&amp;nbsp;naming&lt;/h3&gt;
&lt;p&gt;A strict approach to signal naming should be taken to make it easier to
understand and navigate a&amp;nbsp;design:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To make clear their relationship to the structure of a module&lt;/strong&gt;. Prefixes and
suffices can denote, for example, whether a signal is an input or output, the
pipeline stage it corresponds to and whether it is driven by logic or directly
from a flip-flop. The exact naming convention will be tailored to a project,
but here are some&amp;nbsp;examples:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;i_p0_operand&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// Input into pipeline stage 0.&lt;/span&gt;
&lt;span class="n"&gt;p1_state&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;// A current state of a state machine.&lt;/span&gt;
&lt;span class="n"&gt;p1_state_ns&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// The next state.&lt;/span&gt;
&lt;span class="n"&gt;state_clk&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// A clock signal.&lt;/span&gt;
&lt;span class="n"&gt;m1_sum_co_unused&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// An unused carryout bit from an addition.&lt;/span&gt;
&lt;span class="n"&gt;m2_result_ff&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// A registered result, driven by a flip-flop.&lt;/span&gt;
&lt;span class="n"&gt;o_x4_state&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;// An output signal driven from stage x4.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;To allow simple sorting and searching in wave viewer&lt;/strong&gt;. By using common
prefixes for related signals, sorting will place them together. Similarly,
common substrings are useful to filter a subset of signals over, for example to
select a set of registers or similar signals different in pipeline&amp;nbsp;stages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To be flattened sensibly by downstream tools&lt;/strong&gt;. It is typical for synthesis
to flatten the hierarchical structure of a SystemVerilog design. Consequently
symbols names are derived from their place in the module hierarchy. A suitable
naming scheme really only requires consistency across a design. As an example,
a flip-flop clock pin might be&amp;nbsp;named
&lt;code&gt;u_toplevel_u_submodule_p0_signal_q_reg_17_/CK&lt;/code&gt; corresponding to the&amp;nbsp;register
&lt;code&gt;u_toplevel/u_submodule/p0_signal_q[17]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a name="generate-naming" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Generate block&amp;nbsp;naming&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;All scopes of a generate block should be named.&lt;/strong&gt; This avoids
automatically-assigned names being created by the elaboration tool, making it
hard to understand the structure of the code. This applies to branches of
conditional and loop statements. For example, with named&amp;nbsp;conditions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_gen_cond&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;#(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;parameter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_gen_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;generate&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_gen_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_gen_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_gen_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g_eq_1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g_eq_0&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endgenerate&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the resulting hierarchy, the first two conditionals are not easily
distinguishable, nor are the branches that are&amp;nbsp;chosen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;m_gen_cond&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;g_eq_0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With named loops, a similar situation&amp;nbsp;arises:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_gen_loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;#(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;parameter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_gen_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;generate&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;genvar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;genvar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;genvar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g_loop&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gen_op2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endgenerate&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the resulting hierarchy, there is no correspondence to the blocks assigning
to gen_op0 or gen_op1, indeed these could be switched with no visibility in the&amp;nbsp;hierarchy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;m_gen_loop&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;g_loop&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;g_loop&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;g_loop&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;genblk2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using&amp;nbsp;a &lt;code&gt;g_&lt;/code&gt; prefix for named generate blocks, clearly distinguishes with
instantiations of modules, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;m_child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u_child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;generate&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;genvar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g_loop&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;endgenerate&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Has the&amp;nbsp;hierarchy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;m_foo&lt;/span&gt;
&lt;span class="n"&gt;u_child&lt;/span&gt;
&lt;span class="n"&gt;g_loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="code-structure" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Code&amp;nbsp;structure&lt;/h2&gt;
&lt;p&gt;&lt;a name="modules" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Modules&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Place parameters and variables at the top of their containing scope.&lt;/strong&gt;
Nets/variables/parameters should be declared in the minimum scope in which they
will be used to avoid polluting namespaces. For example, nets global to a
module should be declared at the top of the module for use in the code that&amp;nbsp;follows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Separate combinatorial and sequential nets.&lt;/strong&gt; Declarations of combinatorial
and sequential nets should be separated into different sections for clarity.
This allows the flip-flops in the design to be seen clearly providing a feel
for the size and complexity of the block. The following ripple-carry adder with
registered outputs illustrates this kind of&amp;nbsp;structuring:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_rca&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;#(&lt;/span&gt;&lt;span class="k"&gt;parameter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_op1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_op2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;o_co&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Wires.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Registers.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;co_q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Variables.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;genvar&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;o_co&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o_sum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;co_q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum_q&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Named generate block for per-bit continuous assignments.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bit&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_op1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_op2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;always_ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;posedge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;sum_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;co_q&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;sum_q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;co_q&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;endmodule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;.*&lt;/code&gt; and &lt;code&gt;.name()&lt;/code&gt; syntax in some circumstances to simplify port lists in module
instantiations.&lt;/strong&gt; Doing so can reduce the amount of boilerplate code and thus the
scope for typing or copy-paste errors. The&amp;nbsp;wildcard &lt;code&gt;.*&lt;/code&gt; also provides additional checks:&lt;sup id="fnref:wildcards"&gt;&lt;a class="footnote-ref" href="#fn:wildcards"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It requires all nets be&amp;nbsp;connected.&lt;/li&gt;
&lt;li&gt;It requires all nets to be the same&amp;nbsp;size.&lt;/li&gt;
&lt;li&gt;It prevents implicit nets from being&amp;nbsp;inferred.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Named connections&amp;nbsp;with &lt;code&gt;.name()&lt;/code&gt; can be used with wildcards to add specific
exceptions, such as when names do not match or for unconnected or tied-off
ports. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_clk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i_rst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;endmodule&lt;/span&gt;

&lt;span class="n"&gt;u_module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Bear in mind that implicit hookups with wildcards may obscure module
connectivity when navigating source code during debug. It is up to the designer
to make the right tradeoff. Specific examples of where wildcard hookups are
useful are in wrapper modules and&amp;nbsp;testbenches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avoid logic in module instantiations.&lt;/strong&gt; By instantiating a module with a set
of named signals, mapping one-to-one with ports, it is easier to inspect the
port hookups and the widths of the signals for correctness. Not doing so
obscures functionality in the&amp;nbsp;design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In parameter lists, separate parameters that are intended to be set
externally from secondary parameters that are only used internally.&lt;/strong&gt; There is
no way to prevent some parameters being set externally, ie&amp;nbsp;with &lt;code&gt;localparam&lt;/code&gt;,
so a comment can be used to do this, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_rf&lt;/span&gt;
&lt;span class="p"&gt;#(&lt;/span&gt;&lt;span class="k"&gt;parameter&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;p_entry_width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;p_num_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Internal parameter(s) - do not set.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;p_idx_width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$clog2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_num_entries&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_entry_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wr_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p_idx_width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wr_idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wr_en&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Name scopes that contain local variables.&lt;/strong&gt; For similar reasons to the naming
of generate blocks, if a variable is declared in a local scope, that scope must
be named. It may be useful to introduce named local scopes to separate a large
module into sections. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Any unused or dangling signals/ports within a block must be terminated with a
signal prefixed&amp;nbsp;with &lt;code&gt;unused_&lt;/code&gt;.&lt;/strong&gt; These signals can be &lt;span class="caps"&gt;AND&lt;/span&gt;-reduced to make a
single-bit signal. The &lt;span class="caps"&gt;AND&lt;/span&gt;-reduction with constant zeros guarantees the result
is always zero, so it can be safely optimised away. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_unused_ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="mb"&gt;&amp;#39;b0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="n"&gt;sig_not_used_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="n"&gt;sig_not_used_yet_b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// To be fixed&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="packages" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Packages&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Define packages to share definitions (types, constants, tasks, functions etc)
between multiple modules or&amp;nbsp;IPs.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Qualify types, constants, tasks or functions with their package name and
avoid * imports.&lt;/strong&gt; This resolves any potential ambiguity in the providence of
symbols to the designer and avoids polluting the current scope with all names
defined by the package. For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Avoid&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;m_core_pkg::*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Prefer&lt;/span&gt;
&lt;span class="n"&gt;m_core_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FIFO_RAM_WIDTH&lt;/span&gt;
&lt;span class="n"&gt;m_core_pkg&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;grey_code&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="assertions" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Assertions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Assertions should be written in a separate file that is bound in to the
appropriate scope.&lt;/strong&gt; Verification tests must be written to specifically ensure
that the assertions are present in&amp;nbsp;simulation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Assertion files must be named after the block they apply to, with&amp;nbsp;an
&lt;code&gt;_assert.sv&lt;/code&gt; suffix.&lt;/strong&gt; Where assertions have been split into different groups
to allow use in gate-level simulations (or other environments), the file name
may have&amp;nbsp;a &lt;code&gt;_ports_assert.sv&lt;/code&gt;, &lt;code&gt;_regs_assert.sv&lt;/code&gt; or &lt;code&gt;_nets_assert.sv&lt;/code&gt; suffix as&amp;nbsp;appropriate.&lt;/p&gt;
&lt;p&gt;&lt;a name="preprocessor" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Preprocessor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;In general, it should be possible to avoid any preprocessing of code.&lt;/strong&gt; Other
built-in language structures such as parameters and generate statements should
be used instead. Don&amp;#8217;t use&amp;nbsp;local &lt;code&gt;define&lt;/code&gt; statements in modules unless
absolutely necessary,&amp;nbsp;use &lt;code&gt;localparam&lt;/code&gt; instead&amp;nbsp;of &lt;code&gt;define&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Avoid&lt;/span&gt;
&lt;span class="cp"&gt;`define CONSTANT 1&lt;/span&gt;

&lt;span class="c1"&gt;// Prefer&lt;/span&gt;
&lt;span class="k"&gt;localparam&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p_constant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is because SystemVerilog macro definitions are not scoped within a module,
which can easily lead to them &amp;#8216;leaking&amp;#8217; between files in a filelist, making the
elaboration dependent on the ordering of the&amp;nbsp;list.&lt;/p&gt;
&lt;p&gt;For similar reasons, &lt;strong&gt;use generate-if blocks instead&amp;nbsp;of &lt;code&gt;ifdef&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Avoid&lt;/span&gt;
&lt;span class="no"&gt;`ifdef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FLAG&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="no"&gt;`endif&lt;/span&gt;

&lt;span class="c1"&gt;// Prefer&lt;/span&gt;
&lt;span class="k"&gt;generate&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;endgenerate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;If a local define is unavoidable, then a&amp;nbsp;corresponding &lt;code&gt;undef&lt;/code&gt; must be included
before the end of the file.&lt;/strong&gt; This is to avoid macro definitions polluting the
global&amp;nbsp;namespace.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;`define LOCAL_DEFINE&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// End of the file or use of LOCAL_DEFINE&lt;/span&gt;
&lt;span class="no"&gt;`undef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOCAL_DEFINE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a name="formatting" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Formatting&lt;/h2&gt;
&lt;p&gt;Rules for formatting are not mandated so to provide some flexibility to
designer&amp;#8217;s own tastes and the inevitable exceptions to rules. Above all, the
most important issue with formatting is to maintain consistency within a
logical part of the&amp;nbsp;design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use spaces instead of tabs&lt;/strong&gt;, consistent with the accepted approach in other
programming languages for compatibility with version control and editors&amp;nbsp;etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Split long lines or complex expressions with continuations or across
statements.&lt;/strong&gt; Apply indent as appropriate  for clarity. In this context, &amp;#8216;long&amp;#8217;
is a reasonable value chosen by the author, but typically between 80 and 120&amp;nbsp;characters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use begin and end to&amp;nbsp;wrap &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;, &lt;code&gt;always_ff&lt;/code&gt; and &lt;code&gt;always_comb&lt;/code&gt;
blocks.&lt;/strong&gt; This adds consistency to the code and can help to prevent statements
from unintentionally being excluded from a block. Only use begin and end in
case alternatives when they contain multiple&amp;nbsp;statements.&lt;/p&gt;
&lt;p&gt;&lt;a name="summary" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;SystemVerilog is a large language with many features supporting different
purposes. It is used as a standard in hardware design but its specification
does not define a synthesizable subset. Although there is a general consensus
on which features can be used for synthesis, the fine details are determined by
the particular &lt;span class="caps"&gt;EDA&lt;/span&gt; tooling flow used by a design team. SystemVerilog is
consequently used in a conservative way for specifying synthesizable designs.
The rules and rationale given in this note outline some of the important
aspects of a coding style for hardware design. There are many more details of
SystemVerilog&amp;#8217;s features that are relevant; the references below are a good
place to find out&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;&lt;a name="refs" class="anchor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;References/further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;IEEE&lt;/span&gt; Standard for SystemVerilog (&lt;span class="caps"&gt;IEEE&lt;/span&gt; 1800-2012 and&amp;nbsp;1800-2017).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.sutherland-hdl.com/papers.html"&gt;Sutherland &lt;span class="caps"&gt;HDL&lt;/span&gt; papers&lt;/a&gt; on
  Verilog/SystemVerilog, in&amp;nbsp;particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Stuart Sutherland and Don Mills, Standard gotchas subtleties in the
  Verilog and SystemVerilog standards that every engineer should know. &lt;span class="caps"&gt;SNUG&lt;/span&gt; 2006.
  (&lt;a href="http://www.sutherland-hdl.com/papers/2006-SNUG-Boston_standard_gotchas_paper.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stuart Sutherland, A Proposal for a Standard Synthesizable SystemVerilog Subset. DVCon 2006.
  (&lt;a href="http://www.sutherland-hdl.com/papers/2006-DVCon_SystemVerilog_synthesis_subset_paper.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stuart Sutherland and Don Mills, Synthesizing SystemVerilog: Busting the
  myth that SystemVerilog is only for verification, &lt;span class="caps"&gt;SNUG&lt;/span&gt; 2013.
  (&lt;a href="http://www.sutherland-hdl.com/papers/2013-SNUG-SV_Synthesizable-SystemVerilog_paper.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stuart Sutherland and Don Mills, Can my synthesis compiler do that? What &lt;span class="caps"&gt;ASIC&lt;/span&gt;
  and &lt;span class="caps"&gt;FPGA&lt;/span&gt; synthesis compilers support in the SystemVerilog-2012 standard, DVCon 2014
  (&lt;a href="http://www.sutherland-hdl.com/papers/2014-DVCon_ASIC-FPGA_SV_Synthesis_paper.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stuart Sutherland, I&amp;#8217;m Still In Love With My X! (but, do I want my X to
  be an optimist, a pessimist, or eliminated?), DVCon 2013,
  (&lt;a href="https://sutherland-hdl.com/papers/2013-DVCon_In-love-with-my-X_paper.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clifford E. Cummings and Don Mills. Synchronous Resets? Asynchronous Resets?
  I am so confused! How will I ever know which to use?
  (&lt;a href="http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_Resets.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SystemVerilog&amp;#8217;s priority &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; unique - A Solution to Verilog&amp;#8217;s &amp;#8220;full_case&amp;#8221; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &amp;#8220;parallel_case&amp;#8221; Evil Twins!,
  Clifford E. Cummings, &lt;span class="caps"&gt;SNUG&lt;/span&gt; 2005
  (&lt;a href="http://www.sunburst-design.com/papers/CummingsSNUG2005Israel_SystemVerilog_UniquePriority.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md"&gt;lowRISC Verilog style guide&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verilog &lt;span class="caps"&gt;HDL&lt;/span&gt; Coding, Semiconductor Reuse Standard, Freescale Semiconductor
  (&lt;a href="https://people.ece.cornell.edu/land/courses/ece5760/Verilog/FreescaleVerilog.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Complex Digital Systems, Synthesis, &lt;span class="caps"&gt;MIT&lt;/span&gt; &lt;span class="caps"&gt;OCW&lt;/span&gt;, 2005 (presentation slides,
  (&lt;a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-884-complex-digital-systems-spring-2005/lecture-notes/l05_synthesis.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Datapath Synthesis for Standard-Cell Design, Reto Zimmermann, 2009
  (&lt;a href="http://icslwebs.ee.ucla.edu/dejan/ee219awiki/images/d/de/WB7_tutorial_datapath_final_032112.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Getting the Most from Synthesis to Improve your Datapath QoR, Reto
  Zimmermann, Principal R&amp;amp;D Engineer, DesignWare &lt;span class="caps"&gt;IP&lt;/span&gt;
  (&lt;a href="http://icslwebs.ee.ucla.edu/dejan/ee219awiki/images/d/de/WB7_tutorial_datapath_final_032112.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:logic-wire-reg"&gt;
&lt;p&gt;More details on these types is given
  &lt;a href="https://blogs.sw.siemens.com/verificationhorizons/2013/05/03/wire-vs-reg"&gt;here&lt;/a&gt; and
  &lt;a href="https://www.verilogpro.com/verilog-reg-verilog-wire-systemverilog-logic"&gt;here&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:logic-wire-reg" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:always-blocks"&gt;
&lt;p&gt;With one exception of memory structures that require
  initialisation via an external hierarchical reference. If the memory array is
  written by&amp;nbsp;an &lt;code&gt;always_&lt;/code&gt; block, the memory cannot be driven by another process.
  Support&amp;nbsp;for &lt;code&gt;$deposit&lt;/code&gt; is patchy in tooling, so this cannot always be relied
  on.&amp;#160;&lt;a class="footnote-backref" href="#fnref:always-blocks" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:wildcards"&gt;
&lt;p&gt;See Section 7 of &amp;#8216;Synthesizing SystemVerilog: Busting the Myth
  that SystemVerilog is only for Verification (linked in the references).&amp;#160;&lt;a class="footnote-backref" href="#fnref:wildcards" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="microelectronics"/><category term="programming-languages"/><category term="verilog"/></entry><entry><title>Notes on testing random number generators</title><link href="https://jameswhanlon.com/notes-on-testing-random-number-generators.html" rel="alternate"/><published>2017-04-05T00:00:00+02:00</published><updated>2017-04-05T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2017-04-05:/notes-on-testing-random-number-generators.html</id><summary type="html">&lt;p&gt;Using empirical statistical tests to determine the quality of&amp;nbsp;PRNGs.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently I have been doing some work testing the quality of &lt;a href="https://en.wikipedia.org/wiki/Random_number_generator"&gt;random
number generators&lt;/a&gt;
(RNGs), so I thought I would record things that should be useful as a
reference. I won&amp;#8217;t provide too much background here since there are many good
existing references to the theory and practice of RNGs, the ones of which I
have encountered I have linked&amp;nbsp;to.&lt;/p&gt;
&lt;h1&gt;Properties&lt;/h1&gt;
&lt;p&gt;More specifically, a &lt;a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator"&gt;pseudorandom number
generator&lt;/a&gt; (&lt;span class="caps"&gt;PRNG&lt;/span&gt;)
is a &lt;strong&gt;repeatable&lt;/strong&gt; process for producing numbers that have good statistical
random properties. A true &lt;span class="caps"&gt;RNG&lt;/span&gt;, in contrast, produces statistically random
numbers in a non-repeatable way, for example in electronics by using a physical
source of entropy. True RNGs have an obvious importance in cryptographic&amp;nbsp;applications.&lt;/p&gt;
&lt;p&gt;A pseudorandom sequence can be repeated by starting with a particular &lt;strong&gt;seed&lt;/strong&gt;
number.  The &lt;strong&gt;period&lt;/strong&gt; of a &lt;span class="caps"&gt;PRNG&lt;/span&gt; is the longest unique sequence of numbers
generated from any seed. The period is bounded by the size of the internal
state of a generator ($n$ bits of state can encode $2^n$ numbers), however a
generator may produce shorter repeated sequences, called &lt;strong&gt;cycles&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The properties of a &amp;#8216;good&amp;#8217; &lt;span class="caps"&gt;PRNG&lt;/span&gt;&amp;nbsp;are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;That the length of its period exceeds the number of values that taken from
   the generator by a program.  &lt;a href="http://xoroshiro.di.unimi.it/#remarks"&gt;As a rule of
   thumb&lt;/a&gt;, the period should be at least
   the square of the numbers&amp;nbsp;used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For independent uses of a generator concurrently, that the probability is low
   that any two sequences starting at different seeds&amp;nbsp;overlap.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;That successive values are uniformly distributed. In the literature this
   property is also described as
   &lt;a href="https://en.wikipedia.org/wiki/Equidistributed_sequence"&gt;equidistribution&lt;/a&gt;,
   which can be stated as the probability of finding a number in an interval of
   a sequence is proportional to the length of the&amp;nbsp;interval.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;That successive values are&amp;nbsp;uncorrelated.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;That each value can be computed&amp;nbsp;efficiently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first two properties can typically be determined analytically and it is
true that PRNGs are designed in order that they can be.  Uniformity can be
tested by sampling a large number of values and using statistical measures to
analyse the difference from the expected distribution.  The fifth
characteristic is straightforward to determine, whether the generator is
implemented in hardware or software.  Much harder to determine, however, is the
third property. If it were possible to prove whether a generator is free of
correlation, no &lt;span class="caps"&gt;PRNG&lt;/span&gt; would be considered random since by definition there
exists a well-defined relationship between successive&amp;nbsp;numbers.&lt;/p&gt;
&lt;h1&gt;Empirical&amp;nbsp;testing&lt;/h1&gt;
&lt;p&gt;Conventional approaches to testing RNGs subject them to a collection of tests,
exploring different aspects of the generator&amp;#8217;s statistics. They cannot be
exhaustive, but are shown to be effective by their performance in detecting
correlations in existing standard RNGs. This pragmatism is summed up well in
&lt;a href="http://portal.acm.org/citation.cfm?doid=1268776.1268777"&gt;this paper&lt;/a&gt; with the
comment: &amp;#8220;the different between good and bad RNGs, in a nutshell, is that the
bad ones fail very simple tests whereas the good ones fail only very
complicated tests that are hard to figure out or impractical to&amp;nbsp;run.&amp;#8221;&lt;/p&gt;
&lt;p&gt;There are two popular empirical test&amp;nbsp;suites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://simul.iro.umontreal.ca/testu01/tu01.html"&gt;TestU01&lt;/a&gt;, a comprehensive C
  library, containing example PRNGs, utilities and a collection of statistical
  tests drawn from the academic literature of RNGs. The statistical tests can
  be run ggindividually, or as part of test batteries, which have various run
  times and levels of&amp;nbsp;stringency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://pracrand.sourceforge.net/"&gt;PractRand&lt;/a&gt;, which provides similar
  functionality to TestU01 but implemented in C++, with more modern features
  such as multithreading, flexible interfaces and support for long sequence
  lengths (over 100 terabytes). &lt;a href="http://pracrand.sourceforge.net/PractRand.txt"&gt;According to the
  author&lt;/a&gt;, it&amp;#8217;s tests are not
  drawn from the literature (presumably designed by the author instead) and are
  therefore a good complement to testing with TestU01 or similar. It also
  requires more random bits than TestU01 and therefore takes longer to&amp;nbsp;run.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also worth investigating are the
&lt;a href="https://www.phy.duke.edu/~rgb/General/dieharder.php"&gt;Dieharder&lt;/a&gt; test suite (an
updated version of the original
&lt;a href="https://en.wikipedia.org/wiki/Diehard_tests"&gt;Diehard&lt;/a&gt;) and the
&lt;a href="http://cristianopi.altervista.org/RaBiGeTe/"&gt;RaBiGeTe&lt;/a&gt; test suite. There is
also some interesting discussion from 2010 between the authors of PractRand and
RaBiGete &lt;a href="http://mathforum.org/kb/message.jspa?messageID=7152033"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Testing with&amp;nbsp;TestU01&lt;/h1&gt;
&lt;p&gt;TestU01 provides an interface to test external generators written in C. The
interface requires a&amp;nbsp;method, &lt;code&gt;GetU01&lt;/code&gt;, to generate numbers in the unit interval
$[0, 1)$ as&amp;nbsp;a &lt;code&gt;double&lt;/code&gt; and a&amp;nbsp;method, &lt;code&gt;GetBits&lt;/code&gt;, to return 32 random bits as&amp;nbsp;an
&lt;code&gt;unsigned int&lt;/code&gt;. Some tests will use random bits and some will use random floats.
Just one function can be provided, with the other defined by TestU01 with
the relationship&amp;nbsp;$\texttt{GetU01}=\texttt{GetBits}/2^{32}$.&lt;/p&gt;
&lt;p&gt;Converting 32 random bits to a double-precision float is lossless in that it
has be represented exactly in the 52 bits of mantissa. However, the conversion
biases the higher bits since the lowest bits will be most affected by numerical
errors. For this reason, it is considered good practice to also test the
reversed output of generator, to expose the lowest bits. To test generators
with a larger output, say 64 bits, it is important that all the bits are
exposed to the tests. One way to do this is to alternately use the high and low
bits of a 64-bit value each call&amp;nbsp;to &lt;code&gt;GetBits&lt;/code&gt; or &lt;code&gt;GetU01&lt;/code&gt;. A further reason to
run the reverse of a generator is that the Crush test battery are defined to
ignore the bottom-most bit of the generator&amp;#8217;s output, and most tests also
ignore the second bit (see the &lt;a href="http://simul.iro.umontreal.ca/testu01/guideshorttestu01.pdf"&gt;TestU01
documentation&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In his testing of&amp;nbsp;the &lt;code&gt;xorshift&lt;/code&gt; family of generators, &lt;a href="http://vigna.di.unimi.it/"&gt;Sebastiano
Vigna&lt;/a&gt; takes the following approach to measuring
quality with TestU01: for a particular generator, run it with 100 different
seeds, which are spaced at regular intervals in the state space, i.e.  for a
generator with $n$ bits of state, choose seeds at $1 + i\lfloor 2^n/100\rfloor$
for $0 \leq i &amp;lt; 100$. The quality of a generator is then measured by the total
number of failures over all seeds, with fewer failures meaning higher
quality. If a generator has 100 or more failures, the failure is called
&lt;em&gt;systematic&lt;/em&gt; and the generator is disregarded. Quality is measured with the
BigCrush battery, but since it takes many hours to run (using approximately
$2^{38}$ random values in 106 tests), potential generators can be assessed by
running the smaller test batteries SmallCrush (10 tests) and Crush (96 tests),
continuing based on the number of&amp;nbsp;failures.&lt;/p&gt;
&lt;p&gt;Through my own experiments, I found that the reverse of a generator won&amp;#8217;t
always catch weak lower&amp;nbsp;bits.  &lt;code&gt;xoroshiro128+&lt;/code&gt; is currently the &lt;a href="http://xoroshiro.di.unimi.it/#shootout"&gt;highest
quality and fastest known generator&lt;/a&gt;,
as measured by the above process, with 31 failures and 27 failures when
reversed, but it has a known weak bit 0 that follows a &lt;a href="https://en.wikipedia.org/wiki/Linearity#Boolean_functions"&gt;linear
recurrence&lt;/a&gt; that is
not detected by BigCrush, even when reversed.  However, the weak bit is
detectable with the matrix rank test with parameters $N=1$, $n=80$, $r=15$,
$s=15$, $L=k=5000$, or more simply by swapping the high and low 16-bit portions
of each 32-bit word to move the bottom bit into the middle. I didn&amp;#8217;t discover
anything new&amp;nbsp;about &lt;code&gt;xoroshiro128+&lt;/code&gt; here, but what this does highlight is that
comprehensive test sets like TestU01 are by no means exhaustive, and it
therefore worth testing some of their assumptions, particularly in this case if
you are interested in the quality of bit&amp;nbsp;0.&lt;/p&gt;
&lt;p&gt;Incidentally, TestU01 includes a battery of nine tests called Alphabit, which
is allows specific bits or ranges of bits from a generator to be tested. It was
not stringent enough however to detect the correlation&amp;nbsp;of &lt;code&gt;xoroshirt128+&lt;/code&gt;&lt;span class="quo"&gt;&amp;#8216;&lt;/span&gt;s bit&amp;nbsp;0.&lt;/p&gt;
&lt;h1&gt;An&amp;nbsp;example&lt;/h1&gt;
&lt;p&gt;I&amp;#8217;ve put together a simple example, &lt;a href="https://github.com/jameshanlon/prng-testing/tree/2017-blog"&gt;available on
Github&lt;/a&gt;, of using
TestU01 to assess the quality of a &lt;span class="caps"&gt;PRNG&lt;/span&gt;, which replicates Vigna&amp;#8217;s testing&amp;nbsp;of
&lt;code&gt;xoroshiro128+&lt;/code&gt;.  The code includes a C program to&amp;nbsp;test &lt;code&gt;xoroshiro128+&lt;/code&gt; with
the Crush batteries and Python scripts to run the test over different seeds and
to summarise the output of&amp;nbsp;TestU01.&lt;/p&gt;
&lt;h1&gt;Further reading and&amp;nbsp;links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://xoroshiro.di.unimi.it/"&gt;The &lt;span class="caps"&gt;PRNG&lt;/span&gt; shootout&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sebastiano Vigna. An experimental exploration of Marsaglia&amp;#8217;s xorshift
  generators, scrambled. &lt;span class="caps"&gt;ACM&lt;/span&gt; Trans. Math. Software, 42(4),&amp;nbsp;2016.&lt;/li&gt;
&lt;li&gt;For a comprehensive general introduction to PRNGs and testing them, see &amp;#8216;The
  art of computer systems performance analysis&amp;#8217; by Raj Jain (1991) Chapters 26
  and&amp;nbsp;27.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="PRNGs"/></entry><entry><title>A convolutional neural network from scratch</title><link href="https://jameswhanlon.com/a-convolutional-neural-network-from-scratch.html" rel="alternate"/><published>2017-02-10T00:00:00+01:00</published><updated>2017-02-10T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2017-02-10:/a-convolutional-neural-network-from-scratch.html</id><summary type="html">&lt;p&gt;A C++ implementation of a convoluational neural network building on the
explanation in Michael Nielsen&amp;#8217;s book &amp;#8216;Neural Networks and Deep&amp;nbsp;Learning&amp;#8217;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The online book &amp;#8216;&lt;a href="http://neuralnetworksanddeeplearning.com"&gt;Neural Networks and Deep
Learning&lt;/a&gt;&amp;#8216; by Michael Nielsen is an
excellent introduction to neural networks and the world of deep learning.  As
the book works through the theory, it makes it concrete by explaining how the
concepts are implemented using Python. The complete Python programs are
&lt;a href="https://github.com/mnielsen/neural-networks-and-deep-learning"&gt;available on
Github&lt;/a&gt; for
further inspection and&amp;nbsp;experimentation.&lt;/p&gt;
&lt;p&gt;I decided to write my own implementations of the examples however. Partly to
develop a better understanding but also because I felt that the matrix-based
presentation of the mathematics and use of NumPy operations in the examples
obscured some of the intuition around neurons and their connections, and
because the later examples of convolutional layers are implemented using
&lt;a href="deeplearning.net/software/theano/"&gt;Theano&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, in the hope that it might be interesting as a simple and self-contained
example of a convolutional neural network where nothing is hidden, I&amp;#8217;ve put he
source code for my implementation (written in C++) on
&lt;a href="https://github.com/jameshanlon/convolutional-neural-network"&gt;GitHub&lt;/a&gt;. For
reference I&amp;#8217;ve also written up below the various equations for the
fully-connected and convolutional layers in element-wise notation. I should
thank two particularly useful blog posts by &lt;a href="http://andrew.gibiansky.com/blog/machine-learning/convolutional-neural-networks/"&gt;Andrew
Gibiansky&lt;/a&gt;
and &lt;a href="https://grzegorzgwardys.wordpress.com/2016/04/22/8/"&gt;Grzegorz Gwardys&lt;/a&gt;
which helped me to derive the convolutional equations for back&amp;nbsp;propagation.&lt;/p&gt;
&lt;h1&gt;The source&amp;nbsp;code&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://github.com/jameshanlon/convolutional-neural-network"&gt;repository&lt;/a&gt;
contains several example programs with different network
configurations. They are instantiated from a generic&amp;nbsp;header &lt;code&gt;Network.hpp&lt;/code&gt;,
which contains classes for fully-connected, softmax, convolutional and
max-pooling layer types, and a network class that performs the stochastic
gradient descent, minibatching and training over multiple epochs with
randomly-shuffled training data. The header also contains definitions for
quadratic and cross-entropy cost functions, and sigmoid and rectified-linear
activation functions, which are specified as template parameters to the
network. The code is written primarily primarily to be clear and
understandable, as such there will be many opportunities for optimisations and
other improvements (please let me know if you have any&amp;nbsp;suggestions).&lt;/p&gt;
&lt;p&gt;For instructions on how to build and run the examples, see&amp;nbsp;the &lt;code&gt;README.md&lt;/code&gt;
file. Note that Boost is required&amp;nbsp;for &lt;code&gt;multi_array&lt;/code&gt; and Threading Building
Blocks to parallelise the training over minibatches and accuracy evaluation by
performing inferences in parallel, up to the minibatch size.  It should be
straightforward to build other network configurations or to modify the
implementations or to experiment with new&amp;nbsp;features.&lt;/p&gt;
&lt;p&gt;Included in&amp;nbsp;the &lt;code&gt;extra&lt;/code&gt; folder, are implementations of the example programs
in &lt;a href="https://www.tensorflow.org/"&gt;TensorFlow&lt;/a&gt;, adapted from the &lt;a href="https://www.tensorflow.org/tutorials/mnist/pros/"&gt;&lt;span class="caps"&gt;MNIST&lt;/span&gt;
tutorial&lt;/a&gt;. I found these
useful as a point of comparison to validate the behaviour of the&amp;nbsp;networks.&lt;/p&gt;
&lt;h1&gt;Equations&lt;/h1&gt;
&lt;p&gt;The following notation roughly follows the notation in the Neural Networks and
Deep Learning&amp;nbsp;book:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$l$ is an index of a&amp;nbsp;layer;&lt;/li&gt;
&lt;li&gt;$w$ is a&amp;nbsp;weight;&lt;/li&gt;
&lt;li&gt;$z$ is a weighted&amp;nbsp;input;&lt;/li&gt;
&lt;li&gt;$a$ is an&amp;nbsp;activation;&lt;/li&gt;
&lt;li&gt;$y$ is a&amp;nbsp;label;&lt;/li&gt;
&lt;li&gt;$\delta$ is an&amp;nbsp;error;&lt;/li&gt;
&lt;li&gt;$\sigma$ is the activation function, $\sigma&amp;#8217;$ is the derivative of&amp;nbsp;it;&lt;/li&gt;
&lt;li&gt;$C$ is the cost&amp;nbsp;function.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;For a fully-connected&amp;nbsp;layer&lt;/h2&gt;
&lt;p&gt;In the forward pass, each neuron takes a weighted sum of its inputs, adds the bias
and uses the result as the input to the activation function:
$$z_i^l = \sum_j w_{j,i}^{l-1} a_j^{l-1} + b^l$$
$$a_i^l =&amp;nbsp;\sigma(z_i^l)$$&lt;/p&gt;
&lt;p&gt;The error of a neuron $i$ in the output layer is given by
$\delta_i = (a_i -y_i)\sigma&amp;#8217;(z_i)$
for the sigmoid activation function and by
$\delta_i = a_i - y_i$
for the cross-entropy activation&amp;nbsp;function.&lt;/p&gt;
&lt;p&gt;In the backwards pass, errors are propagated to a neuron from neurons that are
connected as outputs.  The weighted sum of the output neuron&amp;#8217;s errors and
connection weight is calculated and this value is then multiplied by the
derivative of the activation function:
$$\delta_i^l = \sum_j w_{j,i}^{l+1} \delta_j^{l+1}&amp;nbsp;\sigma&amp;#8217;(z_i^l)$$&lt;/p&gt;
&lt;p&gt;The delta for a weight is calculated from the error held by a neuron and the
activation from the neuron connected by the input:
$$\frac{\partial C}{\partial w_i^l} =&amp;nbsp;a_i^{l-1}\delta_i^l$$&lt;/p&gt;
&lt;p&gt;The delta for the bias is equal to the error held by a neuron:
$$\frac{\partial C}{\partial b_i^l} =&amp;nbsp;\delta_i^l$$&lt;/p&gt;
&lt;h2&gt;For a convolutional&amp;nbsp;layer&lt;/h2&gt;
&lt;p&gt;Assuming a two-dimensional input of size $N\times N$ and convolutional mask of
size $m\times&amp;nbsp;m$.&lt;/p&gt;
&lt;p&gt;In the forward pass, each neuron convolves the weights with its receptive field:
$$z_{x,y}^l = \sum_{a=0}^{m-1}\sum_{b=0}^{m-1} w_{a,b}^{l-1}a_{x+a,y+b}^{l-1} + b^l$$
$$a_{x,y}^l =&amp;nbsp;\sigma(z_{x,y}^l)$$&lt;/p&gt;
&lt;p&gt;In the backwards pass, errors are propagated to a neuron from the neurons
connected as outputs in the next layer:
$$\delta_{x,y}^l = \sum_{a=0}^{m-1}\sum_{b=0}^{m-1} w_{a,b}^{l+1}\delta_{x-a,y-b}^{l+1}\sigma&amp;#8217;(z_{x,y}^l)$$
One way to simplify this is to &lt;a href="https://grzegorzgwardys.wordpress.com/2016/04/22/8/"&gt;think of the convolutional layer as one
dimensional&lt;/a&gt; (as with a
fully-connected layer), where each neuron has only $m\times m$ inputs connections.
Then, back propagation operates in the same way as it does with fully-connected
layers. You can in fact use this approach to derive the above&amp;nbsp;equation.&lt;/p&gt;
&lt;p&gt;The delta of a weight is calculated from the activations in the previous layer
that influence that weight and the errors held by the neurons that use it:
$$\frac{\partial C}{\partial w_{a,b}^l} = \sum_{i=0}^{N-m}\sum_{j=0}^{N-m} a_{i+a,&amp;nbsp;j+b}^{l-1}\delta_{i,j}^l$$&lt;/p&gt;
&lt;p&gt;The delta of a bias is calculated from the errors held by the neurons that
use it:
$$\frac{\partial C}{\partial b^l} = \sum_{i=0}^{N-m}\sum_{j=0}^{N-m}&amp;nbsp;\delta_{i,j}^l$$&lt;/p&gt;
&lt;p&gt;With three-dimensional inputs, convolutional layers convolve a
three-dimensional mask into the depth of the input. Convolutional layers can
themselves produce three-dimensional outputs by stacking up separate
convolutional processes in the same layer (called feature maps or channels),
each contributing one element in the depth of the output. In this case, the
backpropagation of the error must sum over the feature maps to get the
contributions of each expression that contribute to the error. The weight and
bias updates must sum errors over the input volume they are applied&amp;nbsp;to.&lt;/p&gt;
&lt;h1&gt;Further&amp;nbsp;reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://deeplearning.net/tutorial/lenet.html"&gt;Convolutional neural networks&amp;nbsp;tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cs231n.github.io/"&gt;CS231n Convolutional Neural Networks for Visual&amp;nbsp;Recognition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://russellsstewart.com/notes/0.html"&gt;Introduction to debugging neural&amp;nbsp;networks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="machine-intelligence"/></entry><entry><title>Reducing memory use in deep neural networks</title><link href="https://jameswhanlon.com/reducing-memory-use-in-deep-neural-networks.html" rel="alternate"/><published>2017-02-05T00:00:00+01:00</published><updated>2017-02-05T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2017-02-05:/reducing-memory-use-in-deep-neural-networks.html</id><summary type="html">&lt;p&gt;A review of state-of-the-art techniques&amp;nbsp;used.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The memory requirements for modern deep neural networks can be significant,
however memory on-chip is expensive relative to computational resources such as
integer and floating-point units, and access to external &lt;span class="caps"&gt;DRAM&lt;/span&gt; memory is orders
of magnitude slower. This article surveys some recent results that demonstrate
the economy of reducing memory use by reuse and&amp;nbsp;re-computation.&lt;/p&gt;
&lt;p&gt;Memory in neural networks is required to store input data, weight parameters,
and activations as an input propagates through the network. In training,
activations from an forward pass must be retained until they can be used to
calculate the error gradients in the backwards pass. A 50-layer ResNet network,
for example, has 25 million weight parameters and computes 16 million
activations in the forward pass. With a batch of 32, this data alone occupies 5
&lt;span class="caps"&gt;GB&lt;/span&gt;; additional memory is required to store the program&amp;#8217;s instructions, input
data and temporary values, the last of which is multiplied by the level
of parallelism in the execution. Measuring the memory use of ResNet-50 training
on a Maxwell-generation Nvidia TitanX &lt;span class="caps"&gt;GPU&lt;/span&gt; shows that it uses up to 7.5 &lt;span class="caps"&gt;GB&lt;/span&gt; of
the 12 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;available.&lt;/p&gt;
&lt;p&gt;Reducing memory use is beneficial for neural networks for several reasons.
First, it enables deeper networks to be trained, which have been shown to
deliver superior performance for specific tasks and generalisation to new
tasks. Second, it allows larger batch sizes to be used, which improves
throughput and parallelisation. And third, and perhaps most importantly, it
allows data to remain closer to where it is being operated on, reducing the
effects of longer latency and lower bandwidth of larger-capacity off-chip
memory, and consequently improving performance. To illustrate the challenge of
last point with modern &lt;span class="caps"&gt;GPU&lt;/span&gt; architectures, it has been observed that &lt;a href="http://jmlr.org/proceedings/papers/v48/diamos16.pdf"&gt;the
Maxwell TitanX &lt;span class="caps"&gt;GPU&lt;/span&gt; processor cores have only 1 &lt;span class="caps"&gt;KB&lt;/span&gt; of memory that can be read
fast enough to saturate the floating-point
datapath&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Two techniques to reduce memory use draw on the dataflow analysis that has been
developed over decades of work with compilers for sequential programming
languages. First, &lt;a href="http://mxnet.io/architecture/note_memory.html#in-place-operations"&gt;operations such as activation functions can be performed in
place when the input data can be overwritten directly by the output, so the
memory is
reused&lt;/a&gt;.
Second, memory can be reused by &lt;a href="http://mxnet.io/architecture/note_memory.html#standard-memory-sharing"&gt;analysing the data dependencies between
operations in a network and allocating the same memory to operations that do
not use it
concurrently&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The second approach is particularly effective when the entire neural network
can be analysed at compile time to create a fixed allocation of memory since
the runtime overheads of memory management reduce to almost zero. The
combination of these techniques have been shown &lt;a href="https://arxiv.org/pdf/1604.06174v2.pdf"&gt;to reduce memory in neural
networks by a factor of two to three&lt;/a&gt;.
These optimisation techniques are analogous to the dataflow in a sequential
program graph to allow the reuse of registers and stack memory, with their
relatively higher efficiency compared to dynamic memory allocation&amp;nbsp;routines.&lt;/p&gt;
&lt;p&gt;Another approach is to trade reduced memory for an increase in computation.
When the computational resources are underused, as they typically are in GPUs,
an increase in computation won’t necessarily increase runtime, and if it does,
can produce relatively higher savings of memory compared to the additional
computation. A simple technique in this vein is to discard values that are
relatively cheap to compute, such as activation functions, and re-compute them
when necessary. More substantial reductions can be achieved by discarding
retained activations in sets of consecutive layers of a network and re-computing
them when they are required during the backwards pass, from the closest set of
remaining activations. Recomputing activations over sets of layers has been
demonstrated by the &lt;a href="https://mxnet.io"&gt;MXNet team&lt;/a&gt; to deliver a factor-of-four
memory reduction for a ResNet-50 network, but more importantly, results in
memory use that scales sub-linearly with respect to the number of layers. The
team also demonstrated &lt;a href="https://arxiv.org/pdf/1604.06174v2.pdf"&gt;training of a 1000-layer ResNet in under 12 &lt;span class="caps"&gt;GB&lt;/span&gt; on the
same Maxwell TitanX &lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A similar memory-reuse approach has been developed by researchers ar &lt;a href="https://deepmind.com/"&gt;Google
DeepMind&lt;/a&gt; with recurrent neural networks (RNNs). RNNs
are a special type of &lt;span class="caps"&gt;DNN&lt;/span&gt; that allows cycles in their structure to encode
behaviour over sequences of inputs.  For RNNs, &lt;a href="https://arxiv.org/pdf/1606.03401v1.pdf"&gt;re-computation has been shown
to reduce memory by a factor of 20 for sequences of length 1000 with only a 30%
performance overhead&lt;/a&gt;. The Baidu &lt;a href="http://research.baidu.com/"&gt;Deep
Speech team&lt;/a&gt; recently showed how they applied
various memory-saving techniques obtain a factor of 16 reduction in memory for
activations, enabling them to &lt;a href="http://jmlr.org/proceedings/papers/v48/diamos16.pdf"&gt;train networks with 100 layers on a Maxwell
TitanX, when previously they could only train
9&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Relative to memory, compute resources are cheap. The state-of-the-art results
surveyed show efficient use of memory through reuse and trading increased
computation for reduced memory use can deliver dramatic improvements in the
performance of neural networks. However, these results are for a processor with
very limited on-chip memory, just a few megabytes, and just &lt;span class="caps"&gt;1KB&lt;/span&gt; of fast memory
per core. A processor with a better balance between memory and compute,
allowing more of a neural network to be stored on-chip, may facilitate much
more dramatic&amp;nbsp;improvements.&lt;/p&gt;
&lt;p&gt;[An adapted version of this article first appeared on the &lt;a href="https://www.graphcore.ai/blog/why-is-so-much-memory-needed-for-deep-neural-networks"&gt;Graphcore
blog&lt;/a&gt;
and there was some discussion of it on &lt;a href="https://news.ycombinator.com/item?id=13928523"&gt;Hacker
News&lt;/a&gt;]&lt;/p&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="machine-intelligence"/></entry><entry><title>Machine learning challenges for computer architecture</title><link href="https://jameswhanlon.com/machine-learning-challenges-for-computer-architecture.html" rel="alternate"/><published>2016-11-04T00:00:00+01:00</published><updated>2016-11-04T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2016-11-04:/machine-learning-challenges-for-computer-architecture.html</id><summary type="html">&lt;p&gt;Neural networks have become a hot topic in computing and their development is
progressing rapidly. They have a long history with some of the first …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Neural networks have become a hot topic in computing and their development is
progressing rapidly. They have a long history with some of the first designs
proposed in the 1940s.  But despite being an active area of research since
then, it has not been until the last five to ten years that the field has
started to deliver state-of-the-art results, with deep neural network-based
algorithms displacing conventional machine-learning and programmed ones in many&amp;nbsp;areas.&lt;/p&gt;
&lt;p&gt;The recent developments in neural networks, since around 2010,  has coincided
with the availability of commodity high-performance GPUs. These devices provide
enough memory and compute that networks can be trained with large datasets, in
the order of hours or days, to perform classification tasks for practical and
interesting problems such as image and speech recognition. Although GPUs have
established themselves as the standard way to accelerate neural networks, they
have done this by transitioning relatively quickly from applications in
traditional &lt;span class="caps"&gt;HPC&lt;/span&gt;, but they are already evolving to meet the needs of machine
learning. In this article I want to discuss some of the challenges that neural
networks and their development present to GPUs, and indeed more generally to
the status quo of computer&amp;nbsp;architecture.&lt;/p&gt;
&lt;h2&gt;Compute and&amp;nbsp;memory&lt;/h2&gt;
&lt;p&gt;The fundamental operations of a neural network are floating-point
multiplications and additions. These are used to combine input data with the
parameters of the network that control the influence of connections between
neurons.  Modern networks require considerable resources to store millions of
parameters and perform billions of operations per&amp;nbsp;input.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Artificial_neuron"&gt;Neurons&lt;/a&gt; in &lt;a href="http://neuralnetworksanddeeplearning.com/chap1.html#the_architecture_of_neural_networks"&gt;fully-connected layers&lt;/a&gt; take
weighted sums of their inputs (a multiplication and an accumulation, &lt;span class="caps"&gt;MAC&lt;/span&gt;, for
each input) from every neuron in the previous layer. The number of MACs grows
with the square of the layer size, and the number of layers, so even with
modest numbers of layers and neurons per layer, the number of MACs can be
large. In the &lt;a href="https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf"&gt;AlexNet network&lt;/a&gt;, the last three layers are
fully connected with 4,096, 4,096 and 1,000 neurons respectively, requiring
58.6 million parameters and, for the &lt;a href="http://neuralnetworksanddeeplearning.com/chap2.html"&gt;forward pass&lt;/a&gt; to classify
a single input image with a trained network, the same number of&amp;nbsp;MACs.&lt;/p&gt;
&lt;p&gt;The use of &lt;a href="http://deeplearning.net/tutorial/lenet.html"&gt;convolutional layers&lt;/a&gt; reduces the number of
parameters by sharing a small sets between the neurons. The five
convolutional layers preceding the fully-connected layers in AlexNet contain
just 2.5 million neurons, but require 655.6 million MACs per input. AlexNet was
state of the art in 2009 and networks since then have developed with many more
convolutional layers and a smaller fully connected component, resulting in
relatively slow growth in the number of parameters but significant increases in
the number of MACs. A variant of the &lt;a href="https://arxiv.org/abs/1409.1556"&gt;&lt;span class="caps"&gt;VGG&lt;/span&gt; network&lt;/a&gt;
(2014) with 19 layers (three fully connected) has 143.6 million parameters and
requires a total of 19.6 million MACs in the forward pass. A variant of the
&lt;a href="https://arxiv.org/abs/1512.03385"&gt;ResNet network&lt;/a&gt; (2015) with 50 layers (one fully connected) has
25.5 million parameters and 3.8 billion MACs for the forward pass. More &lt;a href="https://arxiv.org/abs/1603.09382"&gt;recent
work&lt;/a&gt; has demonstrated benefits of networks with more than
1,000&amp;nbsp;layers.&lt;/p&gt;
&lt;p&gt;When a network is being trained, more compute is required by an additional
backwards pass and and memory requirements increase since intermediate values
for each parameter must be maintained from the forward&amp;nbsp;pass.&lt;/p&gt;
&lt;p&gt;The challenge for computer architecture here is to deliver the huge number of
MACs required for training and inference, whilst minimising the movement of
data between fast local memory and slower main memory, or via a communication
link.  This will of course require corresponding developments in the
implementation of neural networks. A &lt;a href="http://jmlr.org/proceedings/papers/v48/diamos16.pdf"&gt;recent result&lt;/a&gt;
demonstrated that when data is kept on chip, much better use of &lt;span class="caps"&gt;GPU&lt;/span&gt; compute
resource can be made to achieve an order of magnitude improvement in the depth
of network that could be trained. Another has &lt;a href="https://arxiv.org/pdf/1604.06174v2.pdf"&gt;demonstrated&lt;/a&gt;
that compute can be traded for a logarithmic reduction of memory in the number
of&amp;nbsp;layers.&lt;/p&gt;
&lt;h2&gt;Precision&lt;/h2&gt;
&lt;p&gt;Reducing the precision of arithmetic reduces the cost of memory and compute
since lower-precision floating-point numbers require less bits of storage and
require smaller more power-efficient structures in silicon to implement
arithmetic operations. Recent research has demonstrated that representations
between 8 and 16 bits can deliver &lt;a href="https://arxiv.org/abs/1412.7024"&gt;similar results&lt;/a&gt; to
32-bit precision for inference and training. This has already has an impact on
architecture: Google has claimed a &lt;a href="http://www.tomshardware.com/news/google-tensor-processing-unit-machine-learning,31834.html"&gt;10x increase in efficiency&lt;/a&gt; with
it&amp;#8217;s Tensor Processing Unit (&lt;span class="caps"&gt;TPU&lt;/span&gt;) using &lt;a href="https://petewarden.com/2016/05/03/how-to-quantize-neural-networks-with-tensorflow/"&gt;8-bit precision&lt;/a&gt;, and
Nvidia&amp;#8217;s new Pascal architecture supports &lt;a href="https://blogs.nvidia.com/blog/2015/03/17/pascal/"&gt;16-bit floating-point
arithmetic&lt;/a&gt; at twice the rate of single precision, and &lt;a href="https://www.hpcwire.com/2016/09/12/nvidia-aims-gpus-deep-learning-inferencing/"&gt;8-bit
integer arithmetic&lt;/a&gt; at four times the rate. Intel have also
&lt;a href="http://www.anandtech.com/show/10575/intel-announces-knights-mill-a-xeon-phi-for-deep-learning"&gt;recently announced&lt;/a&gt; a variant of their Xeon Phi processor,
code named Knights Mill, that will be optimised for deep learning with variable
precision floating-point&amp;nbsp;arithmetic.&lt;/p&gt;
&lt;h2&gt;Structure&lt;/h2&gt;
&lt;p&gt;There is no single structure for data movement in deep neural networks. The
simplest networks have connections between adjacent layers, which are evaluated
in sequence, but many &lt;a href="https://culurciello.github.io/tech/2016/06/04/nets.html"&gt;more complex structures have been
proposed&lt;/a&gt;. For example, &lt;a href="https://arxiv.org/abs/1512.03385"&gt;residual connections&lt;/a&gt;
provide a pathway between non-adjacent layers, &lt;a href="https://arxiv.org/pdf/1605.07648v1.pdf"&gt;fractal
architectures&lt;/a&gt; have self-similar structures at different
scales and entire neural networks can be &lt;a href="https://arxiv.org/abs/1312.4400"&gt;used as basic building
blocks&lt;/a&gt;. There can also by dynamism in the structure;
&lt;a href="https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf"&gt;dropout&lt;/a&gt; prevents overfitting by randomly removing connections
during training to &amp;#8216;thin&amp;#8217; the network, and networks with &lt;a href="https://arxiv.org/abs/1603.09382v1"&gt;stochastic
depth&lt;/a&gt; randomly exclude subsets of layers during training
to make deep networks more&amp;nbsp;shallow.&lt;/p&gt;
&lt;p&gt;These neural-network structures contrast with traditional &lt;span class="caps"&gt;HPC&lt;/span&gt;-style programs,
which have long been the focus of parallel computing research and development
and are characterised by a &lt;a href="http://view.eecs.berkeley.edu/wiki/Dwarfs"&gt;single structure and algorithm&lt;/a&gt;. The
challenge here is for computing hardware and the programming models targeting
it to support complex, highly-connected and potentially dynamic communication&amp;nbsp;structures.&lt;/p&gt;
&lt;h2&gt;Programming&lt;/h2&gt;
&lt;p&gt;There are &lt;a href="https://github.com/josephmisiti/awesome-machine-learning"&gt;many languages, frameworks and libraries&lt;/a&gt;
available for creating deep-learning applications and they are having to
evolve quickly though to keep up with the pace of research. This is a strong
indication that the means by which we program neural networks need to be
general enough to facilitate experimentation but also deliver reasonable
performance so that it is practical to explore different designs and
hyper&amp;nbsp;parameters.&lt;/p&gt;
&lt;p&gt;However, there is a gulf between the high-level representations of neural
networks used by researchers and their actual implementation on hardware.  For
example, Google&amp;#8217;s &lt;a href="https://www.tensorflow.org/"&gt;TensorFlow&lt;/a&gt; programming framework is written in
C++ and interfaces with GPUs via an abstraction layer that calls &lt;span class="caps"&gt;CUDA&lt;/span&gt; library
routines. On top of this, Google have released a high-level Python wrapper for
TensorFlow, called &lt;a href="https://research.googleblog.com/2016/08/tf-slim-high-level-library-to-define.html"&gt;TensorFlow-Slim&lt;/a&gt;.  But despite the
abstraction and generality of the TensorFlow framework, achieving good
computational efficiency on GPUs depends on a heavily-optimised high-level deep
neural network library, such as &lt;a href="https://developer.nvidia.com/cudnn"&gt;cuDNN&lt;/a&gt; or &lt;a href="https://github.com/NervanaSystems/neon"&gt;&lt;span class="caps"&gt;NEON&lt;/span&gt;&lt;/a&gt;.
The problem for all high-level programming approaches is that the performance
of neural network designs that cannot exploit an underlying optimised library
directly will degrade significantly. Closing the gap between the methods used
to build neural networks and their mapping to a machine architecture would
deliver more performance for a wider range of&amp;nbsp;programs.&lt;/p&gt;
&lt;h2&gt;Deployment and&amp;nbsp;portability&lt;/h2&gt;
&lt;p&gt;Finally, a unique aspect of machine-learning algorithms is the separation
between the phase in which they are trained and their subsequent deployment for
inference.  Since training demands more compute and memory resources and is
typically carried out in a data-centre environment where space, power and, to
some extent, time are not constraining issues.  A trained neural network can be
deployed in more constrained environments, such as mobile or robotics, where
they may be reacting in real time, to a voice user interface or sensor input
for example, with limited memory and power. They may also continue to learn as
they are exposed to more&amp;nbsp;data.&lt;/p&gt;
&lt;p&gt;The result of training is a set of parameter values and portability to another
platform requires the weights to be loaded in an implementation of the same
neural network. The implementation may differ in the numerical precision it
uses since trained networks are known to be robust to low-precision parameter
representations, and doing so takes advantage of the associated memory,
performance and power benefits. A portable neural network might therefore need
separate implementations for training and inference, optimised for the memory
and compute constraints and to be targeted at different machine architectures.
A standardised specification of neural networks, including trained parameters,
would further improve portability between&amp;nbsp;platforms.&lt;/p&gt;
&lt;p&gt;There have been some efforts to try to measure aspects of the implementation,
deployment and performance of deep neural networks. In particular
&lt;a href="https://github.com/DeepMark/deepmark"&gt;Deepmark&lt;/a&gt;, which is based on specific networks, and
&lt;a href="https://github.com/baidu-research/DeepBench"&gt;Deepbench&lt;/a&gt;, which takes a simpler approach by just looking at
important&amp;nbsp;kernels.&lt;/p&gt;
&lt;h2&gt;In&amp;nbsp;summary&lt;/h2&gt;
&lt;p&gt;Modern deep neural networks are now state-of-the-art in many application areas
of computing but with their unique characteristics, they pose a significant
challenge to conventional computer architecture. This challenge however is also
an opportunity to build new machines and programming languages that break away
from the status quo of sequential shared-memory von Neumann&amp;nbsp;machines.&lt;/p&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="computer-architecture"/><category term="machine-intelligence"/></entry><entry><title>The XC Programming Language</title><link href="https://jameswhanlon.com/the-xc-programming-language.html" rel="alternate"/><published>2014-12-13T00:00:00+01:00</published><updated>2014-12-13T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2014-12-13:/the-xc-programming-language.html</id><summary type="html">&lt;p&gt;An overview of the key features of the language, many of which derive
from&amp;nbsp;occam.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;span class="caps"&gt;XC&lt;/span&gt; is a programming language developed by &lt;span class="caps"&gt;XMOS&lt;/span&gt; for real-time embedded parallel
programming of their XCore processor architecture. &lt;span class="caps"&gt;XC&lt;/span&gt; is based on the features
for parallelism and communication in occam, and the syntax and some sequential
features of C. In addition, &lt;span class="caps"&gt;XC&lt;/span&gt; provides primitives to expose hardware
resources: locks, ports and timers. &lt;span class="caps"&gt;XC&lt;/span&gt; programs can be executed with levels of
I/O real-time performance that is usually attributed to &lt;span class="caps"&gt;FPGA&lt;/span&gt; or &lt;span class="caps"&gt;ASIC&lt;/span&gt; devices.
The design of &lt;span class="caps"&gt;XC&lt;/span&gt; was heavily influenced by the occam programming language,
which first introduced channel communication, alternation, ports and timers.
Occam was developed by &lt;a href="https://en.wikipedia.org/wiki/David_May_(computer_scientist)"&gt;David
May&lt;/a&gt; and built on
the &lt;a href=""&gt;Communicating Sequential Processes&lt;/a&gt; formalism, a process algebra
developed by &lt;a href="https://en.wikipedia.org/wiki/Tony_Hoare"&gt;Tony Hoare&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This note was originally written for
&lt;a href="https://en.wikipedia.org/w/index.php?title=XC_(programming_language)"&gt;Wikipedia&lt;/a&gt;,
but the content was removed owing to it being too much like a manual. To save
it from being lost, I&amp;#8217;ve posted it here (December&amp;nbsp;2021).&lt;/p&gt;
&lt;h2&gt;Architectural&amp;nbsp;model&lt;/h2&gt;
&lt;p&gt;An &lt;span class="caps"&gt;XC&lt;/span&gt; program executes on a collection of XCore tiles. Each tile contains one
or more processing cores and resources that can be shared between the cores,
including I/O and memory. All tiles are connected by a communication network
that allows any tile to communicate with any other tile. A given target system
is specified during compilation and the compiler ensures that a sufficient
number of tiles, cores and resources are available to execute the program being&amp;nbsp;compiled.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;The following sections outline the key features of &lt;span class="caps"&gt;XC&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Parallelism&lt;/h3&gt;
&lt;p&gt;Statements in &lt;span class="caps"&gt;XC&lt;/span&gt; are executed in sequence (as they are in C), so that in the
execution&amp;nbsp;of:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the&amp;nbsp;function &lt;code&gt;g&lt;/code&gt; is only executed once the execution of the&amp;nbsp;function &lt;code&gt;f&lt;/code&gt; has
completed. A set of statements can be made to execute in parallel using&amp;nbsp;a &lt;code&gt;par&lt;/code&gt;
statement, so that the&amp;nbsp;statement&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;causes &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; to be executed simultaneously. The execution of parallel
statement only completes when each of the component statements have completed.
The component statements are called tasks in &lt;span class="caps"&gt;XC&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Because the sharing of variables can lead to race conditions and
non-deterministic behaviour, &lt;span class="caps"&gt;XC&lt;/span&gt; enforces parallel disjointness. Disjointness
means that a variable that is changed in one component statement of a par may
not be used in any other&amp;nbsp;statement.&lt;/p&gt;
&lt;p&gt;Parallel statements can be written with a replicator, in a similar fashion to a
for loop, so that many similar instances of a task can be created without
having to write each one separately, so that the&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;is equivalent&amp;nbsp;to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The tasks in a parallel statement are executed by creating threads on the
processor executing the statement. Tasks can be placed on different tiles by
using&amp;nbsp;an &lt;code&gt;on&lt;/code&gt; prefix. In following&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the&amp;nbsp;task &lt;code&gt;f&lt;/code&gt; is placed on any available core of tile 0 and instances of the task
g placed on cores 0, 1, 2 and 3 of tile 1. Task placement is restricted to the
main function of an &lt;span class="caps"&gt;XC&lt;/span&gt; program. Conceptually, this is because when an &lt;span class="caps"&gt;XC&lt;/span&gt;
program is compiled, it is divided up at its top level, into separately
executable programs for each&amp;nbsp;tile.&lt;/p&gt;
&lt;h3&gt;Communication&lt;/h3&gt;
&lt;p&gt;Parallel tasks are able to communicate with each other using interfaces or channels.&amp;nbsp;Interfaces&lt;/p&gt;
&lt;p&gt;An interface specifies a set of transaction types, where each type is defined
as a function with parameter and return types. When two tasks are connected via
an interface, one operates as a server and the other as a client. The client is
able to initiate a transaction with the corresponding server, with syntax
similar to a conventional function call. This interaction can be seen as a
remote procedure call. For example, in the parallel&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Received %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// client&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the client initiates the&amp;nbsp;transaction &lt;code&gt;f&lt;/code&gt;, with the parameter value 42, from the&amp;nbsp;interface &lt;code&gt;i&lt;/code&gt;. The server waits on the transaction (as a case in the select
statement) and responds when the client initiates it by printing out a message
with the received parameter value. Transaction functions can also be used for
two-way communication by using reference parameters, allowing data to be
transferred from a client to a server, and then back&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;Interfaces can only be used by two tasks; they do not allow multiple clients to
be connected to one server. The types of either end of an interface connection
of&amp;nbsp;type &lt;code&gt;T&lt;/code&gt; are server&amp;nbsp;interface &lt;code&gt;T&lt;/code&gt; and client&amp;nbsp;interface &lt;code&gt;T&lt;/code&gt;. Therefore, when
interface types are passed as parameters, the type of connection must also be
specified, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Transaction functions in an interface restrict servers to reacting only in
response to client requests, but in some circumstances it is useful for a
server to be able to trigger a response from the client. This can be achieved
by annotating a function in the interface with no parameters and a void return
type,&amp;nbsp;with &lt;code&gt;[[notification]]&lt;/code&gt; slave. The client waits on the notification
transaction in a select statement for the server to initiate it. A
corresponding function can be annotated&amp;nbsp;with &lt;code&gt;[[clears_notification]]&lt;/code&gt;, which is
called by the slave to clear the notification. In the following simple&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;[notification&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slave&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;[clears_notification&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;i2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;when client 2 initiates the transaction&amp;nbsp;function &lt;code&gt;f&lt;/code&gt;, the server notifies client
1 via the transaction&amp;nbsp;function &lt;code&gt;isReady&lt;/code&gt;. Client 1 waits for the server
notification, and then&amp;nbsp;initiates &lt;code&gt;getValue&lt;/code&gt; when it is&amp;nbsp;received.&lt;/p&gt;
&lt;p&gt;So that it is easier to connect many clients to one server, interfaces can also
be declared as arrays. A server can select over an interface array using an
index&amp;nbsp;variable.&lt;/p&gt;
&lt;p&gt;Interfaces can also be extended, so that basic client interfaces can be
augmented with new functionality. In particular, client interface extensions
can invoke transaction functions in the base interface to provide a layer of
additional&amp;nbsp;complexity.&lt;/p&gt;
&lt;h3&gt;Channels&lt;/h3&gt;
&lt;p&gt;Communication channels provide a more primitive way of communicating between
tasks than interfaces. A channel connects two tasks and allows them to send and
receive data, using the&amp;nbsp;in &lt;code&gt;&amp;lt;:&lt;/code&gt; and&amp;nbsp;out &lt;code&gt;:&amp;gt;&lt;/code&gt; operators respectively. A
communication only occurs when an input is matched with an output, and because
either side waits for the other to be ready, this also causes the tasks to
synchronise. In the&amp;nbsp;following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the value 42 is sent over the&amp;nbsp;channel &lt;code&gt;c&lt;/code&gt; and assigned to the&amp;nbsp;variable &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Streaming&amp;nbsp;channels&lt;/h3&gt;
&lt;p&gt;A streaming channel does not require each input and matching output to
synchronise, so communication can occur&amp;nbsp;asynchronously.&lt;/p&gt;
&lt;h3&gt;Event&amp;nbsp;handling&lt;/h3&gt;
&lt;p&gt;The select statement waits for events to occur. It is similar to the
alternation process in occam. Each component of a select is an event, such as
an interface transaction, channel input or port input (see #&lt;span class="caps"&gt;IO&lt;/span&gt;), and an
associated action. When a select is executed, it waits until the first event is
enabled and then executes that event&amp;#8217;s action. In the following&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the select statement merges data from left and right channels on to an out&amp;nbsp;channel.&lt;/p&gt;
&lt;p&gt;A select case can be guarded, so that the case is only selected if the guard
expression is true at the same time the event is enabled. For example, with a&amp;nbsp;guard:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the left-hand channel of the above example can only input data when the
variable enable is&amp;nbsp;true.&lt;/p&gt;
&lt;p&gt;The selection of events is arbitrary, but event priority can be enforced with&amp;nbsp;the &lt;code&gt;[[ordered]]&lt;/code&gt; attribute for selects. The effect is that higher-priority
events occur earlier in the body of the&amp;nbsp;statement.&lt;/p&gt;
&lt;p&gt;To aid in creating reusable components and libraries, select functions can be
used to abstract multiple cases of a select into a single unit. The following
select function encapsulates the cases of the above select&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;so that the select statement can be&amp;nbsp;written:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Timing&lt;/h3&gt;
&lt;p&gt;Every tile has a reference clock that can be accessed via timer variables.
Performing an output operation on a timer reads the current time in cycles. For
example, to calculate the elapsed execution time of a&amp;nbsp;function &lt;code&gt;f&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nl"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Elapsed time %u s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;CYCLES_PER_SEC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;where &lt;code&gt;CYCLES_PER_SEC&lt;/code&gt; is defined to be the number of cycles per&amp;nbsp;second.&lt;/p&gt;
&lt;p&gt;Timers can also be used in select statements to trigger events. For example,
the select&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;timerafter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Action to be performed after the delay&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;waits for the&amp;nbsp;timer &lt;code&gt;t&lt;/code&gt; to exceed the value of time before reacting to it. The
value&amp;nbsp;of &lt;code&gt;t&lt;/code&gt; is discarded with the&amp;nbsp;syntax &lt;code&gt;:&amp;gt; void&lt;/code&gt;, but it can be assigned to a&amp;nbsp;variable &lt;code&gt;x&lt;/code&gt; with the&amp;nbsp;syntax &lt;code&gt;:&amp;gt; int x&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;IO&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Variables of the type port provide access to &lt;span class="caps"&gt;IO&lt;/span&gt; pins on an XCore device in &lt;span class="caps"&gt;XC&lt;/span&gt;.
Ports can have power-of-two widths, allowing the same number of bits to be
input or output every cycle. The same channel input and output&amp;nbsp;operators &lt;code&gt;&amp;lt;&lt;/code&gt;
and &lt;code&gt;&amp;gt;&lt;/code&gt; respectively are used for&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;The following program continuously reads the value on one port and outputs it
on&amp;nbsp;another:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;xs1.h&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;XS1_PORT_1A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;XS1_PORT_1B&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The declaration of ports must have global scope and each port must specify
whether it is inputting or outputting, and is assigned a fixed value to specify
which pins it corresponds to. These values are defined as macros in a system
header file&amp;nbsp;(&lt;code&gt;xs1.h&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;By default, ports are driven at the tile&amp;#8217;s reference clock. However, clock
block resources can be used to provide different clock signals, either by
dividing the reference clock, or based on an external signal. Ports can be
further configured to use buffering and to synchronise with other ports. This
configuration is performed using library functions. Port&amp;nbsp;events&lt;/p&gt;
&lt;p&gt;Ports can generate events, which can be handled in select statements. For
example, the&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;pinseq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Received input %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;uses the predicate&amp;nbsp;when &lt;code&gt;pinseq&lt;/code&gt; to wait for the value on the&amp;nbsp;port &lt;code&gt;p&lt;/code&gt; to&amp;nbsp;equal &lt;code&gt;v&lt;/code&gt;
before triggering the response to print a&amp;nbsp;notification.&lt;/p&gt;
&lt;h3&gt;Port&amp;nbsp;timing&lt;/h3&gt;
&lt;p&gt;To be able to control when outputs on a port occur with respect to the port&amp;#8217;s
clock, outputs can be timestamped or timed. The timestamped&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;causes the&amp;nbsp;value &lt;code&gt;v&lt;/code&gt; to be output on the&amp;nbsp;port &lt;code&gt;p&lt;/code&gt; and for count to be set to the
value of the port&amp;#8217;s counter (incremented by one each reference clock cycle).
The timed output&amp;nbsp;statement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;causes the port to wait until its counter reaches the value of count before the
value v is&amp;nbsp;output.&lt;/p&gt;
&lt;h3&gt;Multiplexing tasks onto&amp;nbsp;cores&lt;/h3&gt;
&lt;p&gt;By default, each task maps to one core on a tile. Because the number of cores
is limited (eight in current XCore devices), &lt;span class="caps"&gt;XC&lt;/span&gt; provides two ways to map
multiple tasks to cores and better exploit the available&amp;nbsp;cores.&lt;/p&gt;
&lt;p&gt;Server tasks that are composed of a never-ending loop containing a select
statement can be marked as combinable with the&amp;nbsp;attribute &lt;code&gt;[[combinable]]&lt;/code&gt;. This
allows the compiler to combine two or more combinable tasks to run on the same
core, by merging the cases into a single&amp;nbsp;select.&lt;/p&gt;
&lt;p&gt;Tasks of the same form as combinable ones, except that each case of the select
handles a transaction function, can be marked with the&amp;nbsp;attribute
&lt;code&gt;[[distributable]]&lt;/code&gt;. This allows the compiler to convert the select cases into
local function&amp;nbsp;calls.&lt;/p&gt;
&lt;h3&gt;Memory&amp;nbsp;access&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;XC&lt;/span&gt; has two models of memory access: safe and unsafe. Safe access is the default
in which checks are made to ensure&amp;nbsp;that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;memory accesses do not occur outside of their&amp;nbsp;bounds;&lt;/li&gt;
&lt;li&gt;memory aliases are not&amp;nbsp;created;&lt;/li&gt;
&lt;li&gt;dangling pointers are not&amp;nbsp;created.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These guarantees are achieved through a combination of a different kinds of
pointers (restricted, aliasing, movable), static checking during compilation
and run-time&amp;nbsp;checks.&lt;/p&gt;
&lt;p&gt;Unsafe pointers provide the same behaviour as pointers in C. An unsafe pointer
must be declared with the unsafe keyword, and they can only be used&amp;nbsp;within
&lt;code&gt;unsafe { ... }&lt;/code&gt; regions.&lt;/p&gt;
&lt;h3&gt;Additional&amp;nbsp;features&lt;/h3&gt;
&lt;h4&gt;References&lt;/h4&gt;
&lt;p&gt;&lt;span class="caps"&gt;XC&lt;/span&gt; provides references, that are similar to those in C++ and are specified with
the &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; symbol after the type. A reference provides another name for an existing
variable, such that reading and writing it is the same as reading and writing
the original variable. References can refer to elements of an array or
structure and can be used as parameters to regular and transaction&amp;nbsp;functions.&lt;/p&gt;
&lt;h4&gt;Nullable&amp;nbsp;types&lt;/h4&gt;
&lt;p&gt;Resource types such as interfaces, channel ends, ports and clocks must always
have a valid value. The nullable qualifier allows these types to have no value,
which is specified with&amp;nbsp;the &lt;code&gt;?&lt;/code&gt; symbol. For example, a nullable channel is
declared&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nullable resource types can also be used to implement optional resource
arguments for functions.&amp;nbsp;The &lt;code&gt;isnull()&lt;/code&gt; builtin function can be used to check
if a resource is&amp;nbsp;null.&lt;/p&gt;
&lt;h4&gt;Multiple&amp;nbsp;returns&lt;/h4&gt;
&lt;p&gt;In &lt;span class="caps"&gt;XC&lt;/span&gt;, functions can return multiple values. For example, the following
function implements the swap&amp;nbsp;operation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function swap is called with a multiple&amp;nbsp;assignment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Multicore Hello&amp;nbsp;World&lt;/h2&gt;
&lt;p&gt;The following program&amp;nbsp;prints &lt;code&gt;Hello World&lt;/code&gt; on four&amp;nbsp;processors:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;platform.h&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from core %d!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tile&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;References and further&amp;nbsp;reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;David May. The &lt;span class="caps"&gt;XMOS&lt;/span&gt; &lt;span class="caps"&gt;XS1&lt;/span&gt; Architecture
   (&lt;a href="http://www.xmos.com/download/public/The-XMOS-XS1-Architecture(X7879A).pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Douglas R. Watt. Programming &lt;span class="caps"&gt;XC&lt;/span&gt; on &lt;span class="caps"&gt;XMOS&lt;/span&gt; Devices
   (&lt;a href="https://www.xmos.com/download/public/XC-Programming-Guide(X1009B).pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The &lt;span class="caps"&gt;XMOS&lt;/span&gt; programming guide
   (&lt;a href="https://web.archive.org/web/20141129060750/https://www.xmos.com/support/xtools/documentation?subcategory=Programming%20in%20C%20and%20XC&amp;amp;component=17653"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/a&gt;,
   &lt;a href="https://www.xmos.com/download/public/XMOS-Programming-Guide-(documentation)(E).pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;span class="caps"&gt;XC&lt;/span&gt; Language Specification
   (&lt;a href="https://web.archive.org/web/20141129060737/https://www.xmos.com/support/xtools/documentation?subcategory=Programming%20in%20C%20and%20XC&amp;amp;component=14805"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.teigfam.net/oyvind/home/technology/141-xc-is-c-plus-x/"&gt;xC is C plus x&lt;/a&gt;, Øyvind&amp;nbsp;Teig.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="computer-architecture"/><category term="programming-languages"/></entry><entry><title>The XMOS XMP-64</title><link href="https://jameswhanlon.com/the-xmos-xmp-64.html" rel="alternate"/><published>2014-12-04T00:00:00+01:00</published><updated>2014-12-04T00:00:00+01:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2014-12-04:/the-xmos-xmp-64.html</id><summary type="html">&lt;p&gt;The &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 is an experimental single-board distributed-memory parallel computer
with 512 hardware threads  and is programmable with a C-like language.  It was
developed by …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 is an experimental single-board distributed-memory parallel computer
with 512 hardware threads  and is programmable with a C-like language.  It was
developed by &lt;a href="https://www.xmos.com&amp;gt;"&gt;&lt;span class="caps"&gt;XMOS&lt;/span&gt;&lt;/a&gt; in 2009 to demonstrate the
scalablility of the &lt;a href="https://en.wikipedia.org/wiki/XCore_XS1"&gt;&lt;span class="caps"&gt;XS1&lt;/span&gt; architecture&lt;/a&gt;.
Since then it has been &lt;a href="https://www.xmos.com/published/xmp-64-end-life"&gt;discontinued&lt;/a&gt;
but remains a fascinating device from the point of view of providing a huge amount of
parallelism that is programmable in a simple way. As such, I thought I would
record some details and images of it&amp;nbsp;here.&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 board contains a four-by-four grid of &lt;a href="https://en.wikipedia.org/wiki/XCore_XS1-G"&gt;&lt;span class="caps"&gt;XS1&lt;/span&gt;-G4
chips&lt;/a&gt;, each with four processor
cores, and with core providing eight hardware threads. The G4 chips themselves
are connected in an order-four hypercube topology, with every G4 connected
directly to four others. The G4 has 16 links, so four links are used to connect
each direction.  The data rate of each link is 400 Mbits/second, or 1.6
Gbits/second in each edge of the hypercube. The bisection bandwidth of the
entire network is four times this again, at 6.4 Gbits/second. Each processor
core has 64 &lt;span class="caps"&gt;KB&lt;/span&gt; of &lt;span class="caps"&gt;SRAM&lt;/span&gt; memory and runs at 400 MHz. The whole &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 array
therefore provides 512 threads, 4 &lt;span class="caps"&gt;MB&lt;/span&gt; of memory and a peak performance of 25.6
&lt;span class="caps"&gt;GOPS&lt;/span&gt;. (There are more details in the performance experiment document linked&amp;nbsp;below)&lt;/p&gt;
&lt;p&gt;Since the G4 is an embedded processor, these performance numbers are not
competitive with contemporary &lt;span class="caps"&gt;CPU&lt;/span&gt; or &lt;span class="caps"&gt;GPU&lt;/span&gt; devices; it does however burn only a
few tens of watts of power, provides deterministic (completely predictable)
execution of 512 threads and provides a very simple programming&amp;nbsp;interface.&lt;/p&gt;
&lt;div class="text-center"&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-1.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-1_320x320.JPG" alt="XMP-64 top"&gt;&lt;/a&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-2.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-2_320x320.JPG" alt="XMP-64 bottom"&gt;&lt;/a&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-3.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-3_320x320.JPG" alt="XMP-64 top/down"&gt;&lt;/a&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-4.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-4_320x320.JPG" alt="XMP-64 left side"&gt;&lt;/a&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-5.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-5_320x320.JPG" alt="XMP-64 right side"&gt;&lt;/a&gt;
&lt;a href="https://jwh.ams3.digitaloceanspaces.com/homepage/XMP-64/xmp64-6.JPG" class="glightbox" data-gallery="xmp64"&gt;&lt;img class="thumbnail rounded" src="thumbs/xmp64-6_320x320.JPG" alt="XMP-64 in case"&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;As you can see in the pictures, there are two Ethernet interfaces at the top of
the board, which could be used to daisy chain multiple &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 boards together.
Additionally there are 64-pin headers on either side that expose
general-purpose I/O pins connected directly to processors in the&amp;nbsp;array.&lt;/p&gt;
&lt;p&gt;Below is an example program for the &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 written in
&lt;a href="https://en.wikipedia.org/wiki/XC_(programming_language)"&gt;&lt;span class="caps"&gt;XC&lt;/span&gt;&lt;/a&gt;, a programming
language based on
&lt;a href="https://en.wikipedia.org/wiki/Occam_(programming_language)"&gt;occam&lt;/a&gt; designed to
target the features of the &lt;span class="caps"&gt;XS1&lt;/span&gt; architecture. The program uses a ring topology
of communication channels to connect one thread on each chip. As a token is
passed around, the &lt;span class="caps"&gt;LED&lt;/span&gt; connected to each G4 is switched on for a short&amp;nbsp;period.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;xs1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NUM_CHIPS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;STEP&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leds&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;28&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;36&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;44&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;48&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;52&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;56&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XS1_PORT_1E&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="ow"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flash_led&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;chanend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;led&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;led&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;delay_milliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;led&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NUM_CHIPS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NUM_CHIPS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;STEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stdcore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flash_led&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NUM_CHIPS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leds&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;STEP&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As an intern at &lt;span class="caps"&gt;XMOS&lt;/span&gt; in 2009, I did some work to investigate the performance of
the &lt;span class="caps"&gt;XMP&lt;/span&gt;-64. This is written up in the document linked below. It looks at the
performance of barrier synchronisations and exchanges of various permutations
of source-destination pairs. Sadly though, to my knowledge, the &lt;span class="caps"&gt;XMP&lt;/span&gt;-64 didn&amp;#8217;t
see much further use or experimental application development. However, a
similar board was developed by the &lt;a href="https://www.cs.bris.ac.uk/home/simon/many-core/Swallow/Swallow.html"&gt;Swallow
project&lt;/a&gt;,
which used &lt;span class="caps"&gt;XS1&lt;/span&gt; chips (12 cores per board) and allowed direct expansion of the
network with multiple boards up to 480 cores. See the &lt;a href="http://arxiv.org/pdf/1504.06357.pdf"&gt;research
paper&lt;/a&gt; (ArXiv) for more&amp;nbsp;details.&lt;/p&gt;
&lt;h2&gt;More information and&amp;nbsp;links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="/files/xmp64experiments.pdf"&gt;&lt;span class="caps"&gt;XMP&lt;/span&gt;-64 performance experiments document&lt;/a&gt; (&lt;span class="caps"&gt;PDF&lt;/span&gt;),&amp;nbsp;2010,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/jameshanlon/xmp64-experiments"&gt;&lt;span class="caps"&gt;XMP&lt;/span&gt;-64 performance experiments source code&lt;/a&gt;&amp;nbsp;(GitHub).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://ieeexplore.ieee.org/document/5948572"&gt;The &lt;span class="caps"&gt;XMOS&lt;/span&gt; &lt;span class="caps"&gt;XK&lt;/span&gt;-&lt;span class="caps"&gt;XMP&lt;/span&gt;-64 development board&lt;/a&gt;, a writeup based on the
  above for the Networks on Chip 2011 symposium, (&lt;span class="caps"&gt;IEEE&lt;/span&gt;&amp;nbsp;Xplore).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/xcore/proj_xmp64"&gt;Example programs and &lt;span class="caps"&gt;PCB&lt;/span&gt; design files&lt;/a&gt;&amp;nbsp;(GitHub).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.xcore.com/wiki/index.php/XK-XMP-64_Development_Board"&gt;XCore wiki page&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.xmos.com/xmp64"&gt;&lt;span class="caps"&gt;XK&lt;/span&gt;-&lt;span class="caps"&gt;XMP&lt;/span&gt;-64 Development Board&lt;/a&gt; (&lt;span class="caps"&gt;XMOS&lt;/span&gt;&amp;nbsp;website).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="electronics"/></entry><entry><title>Scalable abstractions for general-purpose parallel computation</title><link href="https://jameswhanlon.com/scalable-abstractions-for-general-purpose-parallel-computation.html" rel="alternate"/><published>2014-10-01T00:00:00+02:00</published><updated>2014-10-01T00:00:00+02:00</updated><author><name>James W. Hanlon</name></author><id>tag:jameswhanlon.com,2014-10-01:/scalable-abstractions-for-general-purpose-parallel-computation.html</id><summary type="html">&lt;p&gt;An overview of my PhD&amp;nbsp;thesis.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is my Ph.D. thesis that I completed at the University of Bristol in March
2014. I was supervised by &lt;a href="https://www.cs.bris.ac.uk/~dave/"&gt;David May&lt;/a&gt; and
&lt;a href="http://www.cs.bris.ac.uk/staff/simon/"&gt;Simon Hollis&lt;/a&gt;. I have licensed this work
under the
&lt;a href="http://creativecommons.org/licenses/by-nc-nd/4.0/"&gt;Creative Commons &lt;span class="caps"&gt;BY&lt;/span&gt;-&lt;span class="caps"&gt;NC&lt;/span&gt;-&lt;span class="caps"&gt;ND&lt;/span&gt; 4.0 license&lt;/a&gt;,
so that it can be shared but not modified. I was awarded an
&lt;a href="http://www.bristol.ac.uk/engineering/postgraduate/commendations/hanlon.html"&gt;Engineering Faculty commendation&lt;/a&gt;
for the&amp;nbsp;work.&lt;/p&gt;
&lt;h1&gt;Abstract&lt;/h1&gt;
&lt;p&gt;Parallelism has become the principal means of sustaining growth in
computational performance but there has been relatively little development in
general-purpose computer architectures or programming models that can deal
effectively with large amounts of it. A new general-purpose model of parallel
computing would enable standardisation between architectures, high-volume
production and software that is portable between different machines, now and as
they develop with future technology. There is substantial opportunity to
support this in emerging areas of embedded computing, where the problems of
sensing, interaction and decision making can exploit large amounts of&amp;nbsp;parallelism.&lt;/p&gt;
&lt;p&gt;This thesis demonstrates the essential aspects of a scalable general-purpose
model of parallel computation by proposing a Universal Parallel Architecture
(&lt;span class="caps"&gt;UPA&lt;/span&gt;), based on a highly-connected communication network, and a high-level
parallel programming language for it called sire that can be compiled using
simple techniques. The design of sire combines the essential capabilities of
shared-memory programming with the benefits of message passing to support a
range of programming paradigms and to provide powerful capabilities for
abstraction to build and compose subroutines and data structures in a
distributed context. The design also enables program code to be distributed at
run time to reuse memory and for processor allocation to be dealt with during
compilation so that the overheads of using distributed parallelism are&amp;nbsp;minimal.&lt;/p&gt;
&lt;p&gt;To evaluate whether the &lt;span class="caps"&gt;UPA&lt;/span&gt; is practical to build, a high-level implementation
model using current technologies is described. It demonstrates that the cost of
generality is relatively small; for a system with 4,096 processors, an overall
investment of around 25% of the system is required for the communication
network. Executing on specific &lt;span class="caps"&gt;UPA&lt;/span&gt; implementations, sire&amp;#8217;s primitives for
parallelism, communication and abstraction incur minimal overheads,
demonstrating its close correspondence to the &lt;span class="caps"&gt;UPA&lt;/span&gt; and its scalability.
Furthermore, as well as executing highly-parallel programs, the &lt;span class="caps"&gt;UPA&lt;/span&gt; can support
sequential programming techniques by emulating large memories, allowing general
sequential programs to be executed with a factor of 2 to 3 overhead when
compared to contemporary sequential&amp;nbsp;machines.&lt;/p&gt;
&lt;h1&gt;Published&amp;nbsp;as&lt;/h1&gt;
&lt;p&gt;James W. Hanlon, &lt;em&gt;Scalable abstractions for general-purpose parallel
computation&lt;/em&gt;.  Ph.D. thesis, Department of Computer Science, University of
Bristol, March&amp;nbsp;2014.&lt;/p&gt;
&lt;h1&gt;Download&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/files/thesis.pdf"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/files/thesis-print.pdf"&gt;Print &lt;span class="caps"&gt;PDF&lt;/span&gt;&lt;/a&gt; (no hyperlink&amp;nbsp;colours)&lt;/li&gt;
&lt;/ul&gt;</content><category term="Computing and Silicon"/><category term="computing"/><category term="computer-architecture"/></entry></feed>