<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>The Spade Blog</title>
    <link rel="self" type="application/atom+xml" href="/atom.xml"/>
    <link rel="alternate" type="text/html" href="/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-05T00:00:00+00:00</updated>
    <id>/atom.xml</id>
    <entry xml:lang="en">
        <title>Spade 0.17.0</title>
        <published>2026-03-05T00:00:00+00:00</published>
        <updated>2026-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-17-0/"/>
        <id>/v0-17-0/</id>
        
        <content type="html" xml:base="/v0-17-0/">&lt;div id=&quot;release-links&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.17.0&#x2F;CHANGELOG.md#anchor-017&quot;&gt;Associated changelog&lt;&#x2F;a&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.17.0&#x2F;CHANGELOG.md#anchor-017&quot;&gt;Swim changelog&lt;&#x2F;a&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.17.0&quot;&gt;Git&lt;&#x2F;a&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.18876809&quot;&gt;DOI&lt;&#x2F;a&gt;&lt;&#x2F;div&gt;
&lt;p&gt;Today we release Spade v0.17.0, a release with 22 individual changelog entries making lots of big and small improvements to the language!&lt;&#x2F;p&gt;
&lt;h2&gt;Operator Overloading&lt;&#x2F;h2&gt;
&lt;p&gt;You can now overload many of the operators in Spade allowing you to build better abstractions. For example, you can now define a &lt;code&gt;Vec2&lt;&#x2F;code&gt; struct like this&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color: #d73948&quot;&gt;struct&lt;&#x2F;span&gt; &lt;span style=&quot;color: #4b69c6&quot;&gt;Vec2&lt;&#x2F;span&gt;&amp;lt;T&amp;gt; {&lt;br&#x2F;&gt;    x: T,&lt;br&#x2F;&gt;    y: T,&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then implement the &lt;code&gt;WrappingAdd&lt;&#x2F;code&gt; trait to allow using &lt;code&gt;+.&lt;&#x2F;code&gt; on the new type. By constraining the &lt;code&gt;T&lt;&#x2F;code&gt; generic to any type that also implements &lt;code&gt;WrappingAdd&lt;&#x2F;code&gt;, you can use this Vector struct on any “addable” inner type, including integers, fixed point numbers, complex number, and anything else&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;T: WrappingAdd&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; WrappingAdd &lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt; Vec2&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;T&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt; wrapping_add(&lt;span class=&quot;z-self&quot;&gt;self&lt;&#x2F;span&gt;, other: Self) &lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; Self {&lt;br&#x2F;&gt;        Vec2(&lt;br&#x2F;&gt;            &lt;span class=&quot;z-self&quot;&gt;self&lt;&#x2F;span&gt;.x &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt;. other.x&lt;br&#x2F;&gt;            &lt;span class=&quot;z-self&quot;&gt;self&lt;&#x2F;span&gt;.y &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt;. other.y&lt;br&#x2F;&gt;        )&lt;br&#x2F;&gt;    }&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This initial version of operator overloading supports the following operators:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Eq&lt;&#x2F;code&gt;: &lt;code&gt;==&lt;&#x2F;code&gt; and &lt;code&gt;!=&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Ord&lt;&#x2F;code&gt;: &lt;code&gt;&amp;lt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;=&lt;&#x2F;code&gt;, &lt;code&gt;&amp;gt;=&lt;&#x2F;code&gt; and &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Not&lt;&#x2F;code&gt;: &lt;code&gt;!&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;And&lt;&#x2F;code&gt;: &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Or&lt;&#x2F;code&gt;: &lt;code&gt;||&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Xor&lt;&#x2F;code&gt;: &lt;code&gt;^^&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;BitNot&lt;&#x2F;code&gt;: &lt;code&gt;~&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;BitAnd&lt;&#x2F;code&gt;: &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;BitOr&lt;&#x2F;code&gt;: &lt;code&gt;|&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;BitXor&lt;&#x2F;code&gt;: &lt;code&gt;^&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;WrappingAdd&lt;&#x2F;code&gt;: &lt;code&gt;+.&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;WrappingSub&lt;&#x2F;code&gt;: &lt;code&gt;-.&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;WrappingMul&lt;&#x2F;code&gt;: &lt;code&gt;*.&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;WrappingUsub&lt;&#x2F;code&gt;: &lt;code&gt;-.&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This list will be expanded soon to support more operators, but doing so requires a few improvements to the type system.&lt;&#x2F;p&gt;
&lt;h2&gt;Wrapping Operators&lt;&#x2F;h2&gt;
&lt;p&gt;What is that &lt;code&gt;+.&lt;&#x2F;code&gt; operator in the previous example? It is a new family of wrapping operators that wrap around instead of growing their size. If you’ve used Spade you’ll be used to having to write &lt;code&gt;trunc&lt;&#x2F;code&gt; a lot, which hurt readability. With wrapping operators, you can now write&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;reg&lt;&#x2F;span&gt;(clk) value &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; value &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt;. &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;instead of&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;reg&lt;&#x2F;span&gt;(clk) value &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; trunc(value &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;);&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;&lt;code&gt;impl Trait&lt;&#x2F;code&gt; and return position type expressions&lt;&#x2F;h2&gt;
&lt;p&gt;In the past, Spade has required adding some additional type parameters to generic functions just to be able to specify some additional types. What used to be&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt; growing_op&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;#&lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt; N, #&lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt; Out, Op&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;(x: &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, op: Op) &lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Out&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt; Out: {N &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;      Op: Fn(&lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;N&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;Out&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;{&lt;br&#x2F;&gt;    &lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;can now be written as&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt; growing_op&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;#&lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt; N&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;(x: &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, op: &lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt; Fn(&lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;N&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;{N&lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;}&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;{N&lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;}&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;&lt;code&gt;if let&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When matching on an enum where you only want to unwrap one variant, a &lt;code&gt;match&lt;&#x2F;code&gt; block becomes pretty verbose:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; unwrapped &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control&quot;&gt;match&lt;&#x2F;span&gt; value {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-builtin&quot;&gt;Some&lt;&#x2F;span&gt;(val) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; {&lt;br&#x2F;&gt;        compute(val)&lt;br&#x2F;&gt;    },&lt;br&#x2F;&gt;    _ &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;if let&lt;&#x2F;code&gt; allows writing this in a more readable way&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; unwrapped &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-builtin&quot;&gt;Some&lt;&#x2F;span&gt;(val) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; value {&lt;br&#x2F;&gt;    compute(val)&lt;br&#x2F;&gt;} &lt;span class=&quot;z-keyword z-control&quot;&gt;else&lt;&#x2F;span&gt; {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;&lt;code&gt;name @ pattern&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes you may want to both look at the content of a pattern, and refer to the whole value at once. &lt;code&gt;name @&lt;&#x2F;code&gt; syntax allows you to bind a sub-pattern to a name. For example, you can filter tuples to select only those whose elements have the same value like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;match&lt;&#x2F;span&gt; maybe_tuple {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-builtin&quot;&gt;Some&lt;&#x2F;span&gt;(tuple @ (left, right)) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt; left &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; right {&lt;span class=&quot;z-builtin&quot;&gt;Some&lt;&#x2F;span&gt;(tuple)} &lt;span class=&quot;z-keyword z-control&quot;&gt;else&lt;&#x2F;span&gt; {&lt;span class=&quot;z-builtin&quot;&gt;None&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    &lt;span class=&quot;z-builtin&quot;&gt;None&lt;&#x2F;span&gt; &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-builtin&quot;&gt;None&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;Default Type Parameters&lt;&#x2F;h2&gt;
&lt;p&gt;You can now specify default parameters for type expressions. This function&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt; two_type_params&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;#&lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt; N, #&lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt; M: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;()&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;can now be instantiated either as&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;two_type_params::&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;()&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;two_type_params::&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;10&lt;&#x2F;span&gt;, &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;()&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;&lt;code&gt;verilog_attrs&lt;&#x2F;code&gt; on calls&lt;&#x2F;h2&gt;
&lt;p&gt;When interacting with Verilog black boxes, it is sometimes necessary to add attributes to the instantiation. For example, when working with the ecp5 PLL block. You can now use &lt;code&gt;#[verilog_attrs(...)]&lt;&#x2F;code&gt; on instantiations place Verilog attributes on the resulting Verilog instantiation.&lt;&#x2F;p&gt;
&lt;h2&gt;Type Aliases&lt;&#x2F;h2&gt;
&lt;p&gt;You can now define type aliases like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;type i32 &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;32&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;Super Traits&lt;&#x2F;h2&gt;
&lt;p&gt;Super traits allow one trait to require another trait to also be implemented on a type. This is now supported in Spade as&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;trait Eq: PartialEq {}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which says that for a type to implement the &lt;code&gt;Eq&lt;&#x2F;code&gt; trait, &lt;code&gt;PartialEq&lt;&#x2F;code&gt; has to be implemented first.&lt;&#x2F;p&gt;
&lt;h2&gt;&lt;code&gt;#[inline]&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can now annotate units with &lt;code&gt;#[inline]&lt;&#x2F;code&gt; to inline them instead of generating a Verilog instance. This can be useful when doing things like operator overloading where adding additional hierarchy would make debugging harder. It is also used internally in some cases by the compiler in order to avoid some performance issues during Verilog generation and subsequent reading by synthesis tools.&lt;&#x2F;p&gt;
&lt;h2&gt;Other changes&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Added &lt;code&gt;#[deprecated = &quot;...&quot;]&lt;&#x2F;code&gt; and &lt;code&gt;#[deprecated(...)]&lt;&#x2F;code&gt; attributes that allow deprecating items.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Added support for &lt;code&gt;#bool&lt;&#x2F;code&gt; generic parameters and logical operations on them inside const generics&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Added &lt;code&gt;inout&amp;lt;[T; N]&amp;gt;::read_write_items&lt;&#x2F;code&gt; to access &lt;code&gt;inout&lt;&#x2F;code&gt; arrays element-wise&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Allow methods to be implemented on tuples&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Fixed incorrect behaviour when capturing a variable more than once in a lambda.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Fixed warnings not being shown unless errors were produced too&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Reduce the chance of seeing &lt;code&gt;Number&amp;lt;_&amp;gt; has no method &amp;lt;x&amp;gt;&lt;&#x2F;code&gt; errors&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Fixed compiler panic when declaring variables inside pipelines using &lt;code&gt;decl&lt;&#x2F;code&gt; syntax&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Automatically inline &lt;code&gt;gen_if&lt;&#x2F;code&gt; temporary units&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Integer literals can now specify a type suffix with no size (e.g., &lt;code&gt;120u&lt;&#x2F;code&gt;, &lt;code&gt;33i&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;gen if&lt;&#x2F;code&gt; expressions now can be written without an &lt;code&gt;else&lt;&#x2F;code&gt; block&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Integer comparison operators &lt;code&gt;&amp;lt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;=&lt;&#x2F;code&gt; and &lt;code&gt;&amp;gt;=&lt;&#x2F;code&gt; now can be used at the type level&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Start and end bounds on &lt;code&gt;..&lt;&#x2F;code&gt; range indexing are now optional, defaulting to &lt;code&gt;0&lt;&#x2F;code&gt; and the target array size&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.16.0</title>
        <published>2026-01-22T00:00:00+00:00</published>
        <updated>2026-01-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-16-0/"/>
        <id>/v0-16-0/</id>
        
        <content type="html" xml:base="/v0-16-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.16.0&#x2F;CHANGELOG.md#anchor-015&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.16.0&#x2F;CHANGELOG.md#anchor-015&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.16.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.18338540&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today we are releasing Spade v0.16.0, a release packed with several improvements to several parts of the language.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;10x-performance-improvement&quot;&gt;&amp;gt;10x Performance Improvement&lt;a class=&quot;zola-anchor&quot; href=&quot;#10x-performance-improvement&quot; aria-label=&quot;Anchor link for: 10x-performance-improvement&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The compiler is now much faster than before. On one project the comile time went from &quot;hours&quot;  to 17 seconds, and on the project I used for benchmarking we see a 10x improvement in runtime.
While these projects are slight outliers, the compiler should be faster across the board.&lt;&#x2F;p&gt;
&lt;p&gt;Our goal is for the compile time to be under one second for all projects, so if you encounter code that takes longer to compile, please get in touch so we can improve things further.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;visibility-markers&quot;&gt;Visibility markers&lt;a class=&quot;zola-anchor&quot; href=&quot;#visibility-markers&quot; aria-label=&quot;Anchor link for: visibility-markers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Spade now supports visibility markers like &lt;code&gt;pub&lt;&#x2F;code&gt; and &lt;code&gt;pub(lib)&lt;&#x2F;code&gt;. Like &lt;code&gt;public&lt;&#x2F;code&gt; and &lt;code&gt;private&lt;&#x2F;code&gt; in most languages, this allows you as a library author to only expose parts of your library to the outside world.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;import-and-namespace-system-improvements&quot;&gt;Import and Namespace System Improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#import-and-namespace-system-improvements&quot; aria-label=&quot;Anchor link for: import-and-namespace-system-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;We have made several improvements to to the namespace system. You can now &lt;code&gt;use&lt;&#x2F;code&gt; more than
one item in a single &lt;code&gt;use statement&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;use std::{array::{zip, interleave_arrays}, conv::transmute};
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also use &lt;code&gt;self&lt;&#x2F;code&gt; and &lt;code&gt;super&lt;&#x2F;code&gt; in namespaces to traverse the module tree&lt;&#x2F;p&gt;
&lt;h1 id=&quot;match-conditionals&quot;&gt;Match Conditionals&lt;a class=&quot;zola-anchor&quot; href=&quot;#match-conditionals&quot; aria-label=&quot;Anchor link for: match-conditionals&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Match branches now support conditionals after the pattern, like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl Option&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt; {
  fn inner_is_even(self) -&amp;gt; bool {
    match self {
      Some(val) if val &amp;amp; 1 == 1 =&amp;gt; true,
      Some(_) =&amp;gt; false,
      None =&amp;gt; false
    }
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;type-expressions-in-traits&quot;&gt;Type Expressions in Traits&lt;a class=&quot;zola-anchor&quot; href=&quot;#type-expressions-in-traits&quot; aria-label=&quot;Anchor link for: type-expressions-in-traits&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;For a long time, it has been impossible to write things like&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl&amp;lt;T, #uint N&amp;gt; [T; N] {
  fn append(self, new: T) -&amp;gt; [T; {N + 1}] {
    self.concat([new])
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;instead, you had to introduce an additional type variable on the function. This restriction
has now been lifted and the above code now compiles!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;syntax-changes&quot;&gt;Syntax Changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#syntax-changes&quot; aria-label=&quot;Anchor link for: syntax-changes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;We have made several changes to improve the Spade syntax. Most of these are simply warnings for now allowing you to gracefully migrate your projects&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The function traits that were previously written as &lt;code&gt;Fn((Arg1, Arg2...), Out)&lt;&#x2F;code&gt; are now written as &lt;code&gt;Fn(Arg1, Arg2..) -&amp;gt; Out&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Tuple indexing is now written as &lt;code&gt;tuple.0&lt;&#x2F;code&gt; instead of &lt;code&gt;tuple#1&lt;&#x2F;code&gt;, mimicking Rust&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;more-verilog-interoperability&quot;&gt;More Verilog Interoperability&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-verilog-interoperability&quot; aria-label=&quot;Anchor link for: more-verilog-interoperability&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now annotate some things with &lt;code&gt;#[verilog_attrs(..)]&lt;&#x2F;code&gt; which gets translated to &lt;code&gt;(* ... *)&lt;&#x2F;code&gt; in the generated Verilog. This is useful for vendor primitives that need attributes for configuration.&lt;&#x2F;p&gt;
&lt;p&gt;You can now also use &lt;code&gt;r#ident&lt;&#x2F;code&gt; to write identifiers that conflict with Spade keywords, making it possible to interoperate with Verilog modules that, for example, use &lt;code&gt;reset&lt;&#x2F;code&gt; as an input or output signal.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;improved-self&quot;&gt;Improved &lt;code&gt;Self&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#improved-self&quot; aria-label=&quot;Anchor link for: improved-self&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;code&gt;Self&lt;&#x2F;code&gt; can now be used in more contexts in impl blocks. For example, you can now do&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;enum Thing&amp;lt;T&amp;gt; {
  A,
  B{val: T}
}
impl Thing&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt; {
  fn inner_eq(self, val: uint&amp;lt;8&amp;gt;) -&amp;gt; bool {
    match self {
      Self::A =&amp;gt; false,
      Self::B(inner) =&amp;gt; inner == val
    }
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;ascii-literals&quot;&gt;ASCII literals&lt;a class=&quot;zola-anchor&quot; href=&quot;#ascii-literals&quot; aria-label=&quot;Anchor link for: ascii-literals&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now write ascii char literals like &lt;code&gt;b&#x27;a&#x27;&lt;&#x2F;code&gt; and &lt;code&gt;b&quot;This is a\nmulti line string&quot;&lt;&#x2F;code&gt;. This is very useful when working with human readable strings, such as when sending things back and forth via UART, or when solving advent of code 😉 https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;aoc2025&lt;&#x2F;p&gt;
&lt;h1 id=&quot;array-labels&quot;&gt;Array Labels&lt;a class=&quot;zola-anchor&quot; href=&quot;#array-labels&quot; aria-label=&quot;Anchor link for: array-labels&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now add labels to arrays and refer to those labels later to get the corresponding indices. For example&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;  Insn::Set(0, 0),
&amp;#x27;loop_start
  Insn::Addi(0, 1),
  Insn::Branchi(0, Cond::Eq, 255, @loop_start.index)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;for more details on this, and how it can be used, see our &lt;a href=&quot;https:&#x2F;&#x2F;blog.spade-lang.org&#x2F;processor-for-aoc&#x2F;&quot;&gt;previous blog post&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thanks&quot;&gt;Thanks&lt;a class=&quot;zola-anchor&quot; href=&quot;#thanks&quot; aria-label=&quot;Anchor link for: thanks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This release marks a small milestone for external contributions to Spade. Out of the 17 merge requests in the changelog, 12 of them are by José Miguel Sánchez García, making it the first release where Frans hasn&#x27;t made the majority of the changes! Thanks José 🎉&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I Built a Processor for Advent of Code Day 8</title>
        <published>2025-12-15T00:00:00+00:00</published>
        <updated>2025-12-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/processor-for-aoc/"/>
        <id>/processor-for-aoc/</id>
        
        <content type="html" xml:base="/processor-for-aoc/">&lt;p&gt;It may or may not have been a massive waste of time, but at least I had fun and get to showcase some fun things Spade can do! Especially the new labels that allow the Spade compiler to act as a rudimentary assembler.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;adventofcode.com&quot;&gt;Advent of Code&lt;&#x2F;a&gt; is a yearly programming challenge where a new programming problem is unlocked every day starting on December 1. This year, a few of us are doing advent of code in hardware for &lt;a href=&quot;https:&#x2F;&#x2F;blog.janestreet.com&#x2F;advent-of-fpga-challenge-2025&#x2F;&quot;&gt;Advent of FPGA&lt;&#x2F;a&gt; and of course this means I’m using Spade.&lt;&#x2F;p&gt;
&lt;p&gt;I set myself the additional rule that as far as possible, &lt;em&gt;everything&lt;&#x2F;em&gt; should be done in Spade, including input parsing, and until day 8 I had kept that streak up with only minor difficulties. However, day 8 this year was less suited to hardware solutions than previous problems, and honestly, after a week of solving similar problems I was starting to get a bit bored. For a while a thought had been brewing in the back of my mind that it is possible to build a simple CPU for a one-off instruction set using &lt;a href=&quot;https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;enums.html&quot;&gt;Spade’s enums&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So, armed with a problem being annoying to do in hardware, relatively simple in software, and this latest brainworm, I decided to try my hand at solving day 8 with a custom processor to maintain my 100% Spade streak.&lt;&#x2F;p&gt;
&lt;h2&gt;The Initial Processor&lt;&#x2F;h2&gt;
&lt;p&gt;I had already &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;agile-tutorial&#x2F;-&#x2F;blob&#x2F;main&#x2F;processor&#x2F;src&#x2F;main.spade?ref_type=heads&quot;&gt;prototyped&lt;&#x2F;a&gt; an enum-based processor for a guest lecture I gave in early november.&lt;&#x2F;p&gt;
&lt;p&gt;That meant I could write the insturction set, processor like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F;&#x2F; The definition of the instructions that the processor supports.&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enum&lt;&#x2F;span&gt; Insn {&lt;br&#x2F;&gt;    Nop,&lt;br&#x2F;&gt;    Set{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Add{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Jump{target: &lt;span class=&quot;z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Out{op: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;}&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then write a program for this processor like this&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F;&#x2F; The instruction memory containing the program to be executed. To fit in block&lt;span class=&quot;z-operator&quot;&gt;-&lt;&#x2F;span&gt;ram this&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;&lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F;&#x2F; has a single cycle read latency.&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; mem &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword&quot;&gt;inst&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;mem&lt;&#x2F;span&gt;::clocked_memory_init(clk, [], [&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Set$(dest: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Set$(dest: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Add$(dest: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Out$(op: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Jump$(target: &lt;span class=&quot;z-literal&quot;&gt;2&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Jump$(target: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;)&lt;br&#x2F;&gt;]);&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;agile-tutorial&#x2F;-&#x2F;blob&#x2F;main&#x2F;processor&#x2F;src&#x2F;main.spade?ref_type=heads#L35&quot;&gt;processor implementation is another hundred lines&lt;&#x2F;a&gt;, a bit too much for inlining in this blog post.&lt;&#x2F;p&gt;
&lt;h2&gt;Turning the Spade Compiler Into an Assembler&lt;&#x2F;h2&gt;
&lt;p&gt;However, there was one annoying thing about this: All the jumps need hard-coded offsets and that makes writing any non-trivial program super annoying and error prone. After some brief discussion in the &lt;a href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;YtXbeamxEX&quot;&gt;Spade Discord&lt;&#x2F;a&gt; we realized that we can solve that problem by adding labels to arrays. Just like an assembler, you can put a label before an array element, and then use that label to refer to its index later.&lt;&#x2F;p&gt;
&lt;p&gt;Half an hour of implementation and another hour of syntax bike shedding later, Spade had &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;539&quot;&gt;support for this new feature&lt;&#x2F;a&gt; albeit with a placeholder syntax, meaning the previous example program can now be written as&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; mem &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword&quot;&gt;inst&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;mem&lt;&#x2F;span&gt;::clocked_memory_init(clk, [], [&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Set$(dest: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Set$(dest: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;  &#x27;loop&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Add$(dest: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-literal&quot;&gt;1&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Out$(op: &lt;span class=&quot;z-literal&quot;&gt;0&lt;&#x2F;span&gt;),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Jump$(target: @loop.index),&lt;br&#x2F;&gt;]);&lt;br&#x2F;&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;Fearlessly Extending the Processor&lt;&#x2F;h2&gt;
&lt;p&gt;One of my favourite things about Spade is how it enables “fearless refactoring”. If you make a change, the compiler will yell at you to update all the places where the change may affect things. Take for example the instruction set above. It is clearly not enough for any real world tasks, so I had to add quite a few instructions to it.&lt;&#x2F;p&gt;
&lt;p&gt;That means first extending the &lt;code&gt;Insn&lt;&#x2F;code&gt; enum, for example with an &lt;code&gt;Addi{dest: uint&amp;lt;4&amp;gt;, opa: uint&amp;lt;4&amp;gt;, value: uint&amp;lt;32&amp;gt;}&lt;&#x2F;code&gt; instruction&lt;&#x2F;p&gt;
&lt;p&gt;Now the compiler will complain about all the places where this new instruction is not handled, for example, in the ALU:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-comment z-prose&quot;&gt;&#x2F;&#x2F; Perform any computation the instruction requires&lt;&#x2F;span&gt;&lt;br&#x2F;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt; alu_out &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control&quot;&gt;match&lt;&#x2F;span&gt; insn {&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Nop &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;undef&lt;&#x2F;span&gt;::undef(),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Set$(dest: _, value: _) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;undef&lt;&#x2F;span&gt;::undef(),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Add$(opa: _, opb: _, dest: _) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; trunc(reg_a &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; reg_b),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Jump(_) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;undef&lt;&#x2F;span&gt;::undef(),&lt;br&#x2F;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Out(_) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-namespace&quot;&gt;std&lt;&#x2F;span&gt;::&lt;span class=&quot;z-namespace&quot;&gt;undef&lt;&#x2F;span&gt;::undef(),&lt;br&#x2F;&gt;};&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Adding supprt for &lt;code&gt;Addi&lt;&#x2F;code&gt; here is simple, I just had to add an additional branch&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;    &lt;span class=&quot;z-namespace&quot;&gt;Insn&lt;&#x2F;span&gt;::Add$(opa: _, opb: _, value) &lt;span class=&quot;z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; trunc(reg_a &lt;span class=&quot;z-operator&quot;&gt;+&lt;&#x2F;span&gt; value),&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And repeating for the other &lt;code&gt;match&lt;&#x2F;code&gt; expressions in the processor I ended up with a slightly more powerful processor without putting too much thought into it!&lt;&#x2F;p&gt;
&lt;p&gt;This is also very helpful when adjusting instructions. If I realized that the parameters to any instruction were not ideal, I could just change it in the definition, and the compiler would tell me where to update, both in the processor and also &lt;strong&gt;in the program&lt;&#x2F;strong&gt; thanks to the assembler just being the Spade compiler!&lt;&#x2F;p&gt;
&lt;p&gt;All in all, this worked really well, while I of course had minor bugs from getting things wrong, I was able to build up my processor to quite a few instructions: which s which s&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;spade&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enum&lt;&#x2F;span&gt; Insn {&lt;br&#x2F;&gt;    Nop,&lt;br&#x2F;&gt;    Set{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;72&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Move{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, source: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Add{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Addi{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;72&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Mul{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Div2{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Inc{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Dec{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    ReadCoord{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, source_addr: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    SqDist3d{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opb: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Jump{target: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    JumpAndLink{target: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    JumpReg{target: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Branch{target: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, opa: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, cmp: Cmp, opb: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Out{op: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Outi{value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;72&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    GetNumCoords{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    WaitParsingDone,&lt;br&#x2F;&gt;    ReadMem{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, source: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    ReadMemOffset{dest: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, offset: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, addr: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    WriteMem{dest_addr: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, dest_value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    WriteMemOffset{dest_addr: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, offset: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;, dest_value: &lt;span class=&quot;z-type&quot;&gt;uint&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-literal&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;},&lt;br&#x2F;&gt;    Halt,&lt;br&#x2F;&gt;}&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In addition, I was able to make late large scale changes when I realized I had failed to account for some things. For example, I doubled the number of registers in the processor, and increased the native word length from 48 to 72 bits without causing any existing code to fail!&lt;&#x2F;p&gt;
&lt;h2&gt;So Far, So Good&lt;&#x2F;h2&gt;
&lt;p&gt;Until now, everything has gone well! Spade did what it was supposed to, the new labels meant writing “assembly” in Spade was pretty comfortable, and I didn’t run into any hard to track down bugs in the processor! However, as it turns out solving a second week advent of code problem in assembler comes with some difficulties. Word lengths had to be massive, my naive solution needed N^2 memory and did not end up fitting in block RAM for the ECP5 FPGA I was going to run this on, and I misread the problem description at least twice. In addition, many of these problems only appeared for larger inputs which meant 500k clock cycles of simulation just to reproduce issues. I also uncovered a bug in the Spade Surfer plugin which meant that the instruction decoding that had been extremely pleasant to work with initially broke for long simulations, making debugging quite pleasant.&lt;&#x2F;p&gt;
&lt;p&gt;In the end, through painful debugging and comparing my results to the result of a friend’s python solution I eventually found all the bugs and earned that, sweet sweet &lt;em&gt;silver star&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And the runtime was only around 3 minutes. Here at Spade inc we have gone past hardware accceleration and are fast at work on revolutionary hardware &lt;em&gt;decceleration&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;h2&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;While this is probably not the best way to solve an advent of code problem, being able to define and program an ad-hoc processor like this is something I’m excited to have in the Spade toolbox, and I’m very pleased that the fearless refactoring that Spade provides extended to this technique.&lt;&#x2F;p&gt;
&lt;p&gt;I believe this will come in handy for “management tasks” where the task is “programmatically complicated” but where preformance isn’t top priority.&lt;&#x2F;p&gt;
&lt;p&gt;You can find all the source code for this project in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;aoc2025&quot;&gt;my advent of code repo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.15.0</title>
        <published>2025-11-20T00:00:00+00:00</published>
        <updated>2025-11-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-15-0/"/>
        <id>/v0-15-0/</id>
        
        <content type="html" xml:base="/v0-15-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.15.0&#x2F;CHANGELOG.md#anchor-015&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.15.0&#x2F;CHANGELOG.md#anchor-015&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.15.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.17660502&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;It is finally time for Spade v0.15.0 🎉. Like the previous release, this one is also delayed from our usual 6 week release schedule, but this time it also means that the release is unusually big!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;more-powerful-lambda-units&quot;&gt;More powerful Lambda units&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-powerful-lambda-units&quot; aria-label=&quot;Anchor link for: more-powerful-lambda-units&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In the last update, we introduced &lt;code&gt;lambda&lt;&#x2F;code&gt; functions and some corresponding utilities in the standard library. In this update we&#x27;re lifting two significant limitations on the lambda functions&lt;&#x2F;p&gt;
&lt;h2 id=&quot;captures&quot;&gt;Captures&lt;a class=&quot;zola-anchor&quot; href=&quot;#captures&quot; aria-label=&quot;Anchor link for: captures&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Lambdas can now &quot;capture&quot; variables from their environment which allows you to do things like&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn fir_filter(x: Option&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt;, n: uint&amp;lt;8&amp;gt;) -&amp;gt; Option&amp;lt;uint&amp;lt;9&amp;gt;&amp;gt; {
  &amp;#x2F;&amp;#x2F; Capture the `n` parameter in this scope and use it inside the lambda.
  x.map(fn |x| {x + n})
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;pipelines&quot;&gt;Pipelines&lt;a class=&quot;zola-anchor&quot; href=&quot;#pipelines&quot; aria-label=&quot;Anchor link for: pipelines&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Lambdas can now be pipelines. The primary use case for this is transformations of data
that spans multiple clock cycles, where you want to preserve things like validity. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;pipeline(3) pipelined_multiplier(val: Option&amp;lt;(int&amp;lt;18&amp;gt;, int&amp;lt;18&amp;gt;)&amp;gt;) -&amp;gt; Option&amp;lt;int&amp;lt;36&amp;gt;&amp;gt; {
  val
    .inst(_) pmap(pipeline(3) |(x, y)| {
      let result = x * y;
    reg * 3;
      result
    })
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;new-syntax&quot;&gt;New syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#new-syntax&quot; aria-label=&quot;Anchor link for: new-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The syntax for defining lambdas has been changed from &lt;code&gt;fn (a, b) ...&lt;&#x2F;code&gt; to &lt;code&gt;fn |a, b|&lt;&#x2F;code&gt; to more closely align with Rust.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pipeline-methods&quot;&gt;Pipeline methods&lt;a class=&quot;zola-anchor&quot; href=&quot;#pipeline-methods&quot; aria-label=&quot;Anchor link for: pipeline-methods&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Previously, methods were limited to entities and functions, but now you can
also implement pipeline methods. For example, you can now make the read mehtod
on memories a method, making it nicer to use in things like method chains.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;struct port MemoryReadPort&amp;lt;T&amp;gt; {
  addr: inv &amp;amp;uint&amp;lt;16&amp;gt;,
  data: &amp;amp;T
}

impl MemoryReadPort {
  pipeline(1) read(self, clk: clock, addr: uint&amp;lt;16&amp;gt;) {
    set self.addr = addr;
  reg;
    *self.data
  }
}

&amp;#x2F;&amp;#x2F; Before
inst(1) read_memory(clk, read_port)
&amp;#x2F;&amp;#x2F; Now
read_port
  .inst(1) read(clk)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;inferred-pipeline-depth&quot;&gt;Inferred pipeline depth&lt;a class=&quot;zola-anchor&quot; href=&quot;#inferred-pipeline-depth&quot; aria-label=&quot;Anchor link for: inferred-pipeline-depth&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;When instantiating pipelines, it is now possible to use &lt;code&gt;inst(_)&lt;&#x2F;code&gt; to infer the depth of the instantiated pipeline.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;transitive-dependencies&quot;&gt;Transitive dependencies&lt;a class=&quot;zola-anchor&quot; href=&quot;#transitive-dependencies&quot; aria-label=&quot;Anchor link for: transitive-dependencies&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Until now, if multiple libraries depended on the same library in a project, values could not be passed between them despite ostensibly being of the same type. With this release, &lt;code&gt;swim&lt;&#x2F;code&gt; now allows this allowing more complex projects to be built.&lt;&#x2F;p&gt;
&lt;p&gt;Note that this comes with a minor caveat that only one version of each library will be used throughout the project.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;standard-library-improvements&quot;&gt;Standard library improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#standard-library-improvements&quot; aria-label=&quot;Anchor link for: standard-library-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The standard library has received several new additions in this release&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;zip&lt;&#x2F;code&gt; on arrays joins two arrays together element by element (&lt;code&gt;[a, b].zip([c, d])&lt;&#x2F;code&gt; becomes &lt;code&gt;[(a, c), (b, d)]&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;interleave&lt;&#x2F;code&gt; interleaves the elements of two arrays (&lt;code&gt;[a, b].interleave([c, d])&lt;&#x2F;code&gt; becomes &lt;code&gt;[a, c, b, d]&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pmap&lt;&#x2F;code&gt; on the &lt;code&gt;Option&lt;&#x2F;code&gt; type behaves like &lt;code&gt;map&lt;&#x2F;code&gt;, but with a pipeline instead of a function&lt;&#x2F;li&gt;
&lt;li&gt;The memory ports in the standard library now have &lt;code&gt;.read&lt;&#x2F;code&gt; and &lt;code&gt;.write&lt;&#x2F;code&gt; methods instead of the now legacy &lt;code&gt;read_read_port&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;improvements-to-external-verilog&quot;&gt;Improvements to External Verilog&lt;a class=&quot;zola-anchor&quot; href=&quot;#improvements-to-external-verilog&quot; aria-label=&quot;Anchor link for: improvements-to-external-verilog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The language now supports type level strings, for example&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn tlstring&amp;lt;#str message&amp;gt;() {...}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;while they don&#x27;t do anything in Spade, they are very useful when interfacing with external
Verilog modules which often take strings as configuration parameters, for example, PLLs &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;spade-sdram&#x2F;-&#x2F;blob&#x2F;959b1cb17357aea591e5a4870f316027e6bae423&#x2F;hwtest_tangnano20k&#x2F;src&#x2F;pll.spade&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;spade-sdram&#x2F;-&#x2F;blob&#x2F;959b1cb17357aea591e5a4870f316027e6bae423&#x2F;hwtest_tangnano20k&#x2F;src&#x2F;pll.spade&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With this change, nearly every Verilog module is instantiatable from Spade, the only thing missing as far as we know is being able to add Verilog attributes to instances which is also used by some PLLs.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;unsafe&quot;&gt;Unsafe&lt;a class=&quot;zola-anchor&quot; href=&quot;#unsafe&quot; aria-label=&quot;Anchor link for: unsafe&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;In the past, a few methods in the standard library were in an &lt;code&gt;unsafe&lt;&#x2F;code&gt; namespace because they violate some guarantees that spade provide and assume to be true. In particular, Spade does not allow you to create a value of a type with a bit pattern that isn&#x27;t valid for that specific type. In some cases, you know what you are doing and want to work around such a constraint, which is when you want to use an &quot;unsafe&quot; function.&lt;&#x2F;p&gt;
&lt;p&gt;With 0.15, we&#x27;re adding an &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword which you can add as a label on a &lt;code&gt;unit&lt;&#x2F;code&gt;, like the &lt;code&gt;transmute&lt;&#x2F;code&gt; function in the standard library&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;&amp;#x2F;&amp;#x2F;&amp;#x2F; Reinterpret the bits of `t` as an `O`
unsafe fn transmute&amp;lt;T, O&amp;gt;(t: T) -&amp;gt; O {&amp;#x2F;* *&amp;#x2F;}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; functions can only be called in the newly introduced &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let reinterpreted: uint&amp;lt;16&amp;gt; = unsafe { transmute((uint&amp;lt;8&amp;gt;, uint&amp;lt;8&amp;gt;)) }
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which allows you to quickly find all instances of potentially dangerous code.&lt;&#x2F;p&gt;
&lt;p&gt;As the language evolves in the future to provide more guarantees, such as clock domains, &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions will become more important.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;improved-inout-support&quot;&gt;Improved &lt;code&gt;inout&lt;&#x2F;code&gt; support&lt;a class=&quot;zola-anchor&quot; href=&quot;#improved-inout-support&quot; aria-label=&quot;Anchor link for: improved-inout-support&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;inout&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; type has also seen some improvements, including a new &lt;code&gt;read_write_inout&lt;&#x2F;code&gt; for interacting with them inside Spade.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;changes-to-set&quot;&gt;Changes to &lt;code&gt;set&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#changes-to-set&quot; aria-label=&quot;Anchor link for: changes-to-set&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;set&lt;&#x2F;code&gt; statement now requires the right hand side to be a wire. This allows the use &lt;code&gt;set&lt;&#x2F;code&gt; on &lt;code&gt;inv clock&lt;&#x2F;code&gt;. Existing code needs to be patched to replace &lt;code&gt;set x = y;&lt;&#x2F;code&gt; with &lt;code&gt;set x = &amp;amp;y;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;structs-and-enums-in-const-scenarios&quot;&gt;Structs and enums in &lt;code&gt;const&lt;&#x2F;code&gt; scenarios&lt;a class=&quot;zola-anchor&quot; href=&quot;#structs-and-enums-in-const-scenarios&quot; aria-label=&quot;Anchor link for: structs-and-enums-in-const-scenarios&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now use structs and enums in places which expect compile time values, most importantly &lt;code&gt;clocked_memory_init&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;automatic-surfer-integration&quot;&gt;Automatic Surfer integration&lt;a class=&quot;zola-anchor&quot; href=&quot;#automatic-surfer-integration&quot; aria-label=&quot;Anchor link for: automatic-surfer-integration&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;code&gt;swim&lt;&#x2F;code&gt; will now download or compiler the Surfer integration plugin making the Spade integration seamless. If you have not used Surfer with Spade integration yet, make sure to install the latest Surfer and swim versions to take advantage of this.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;mac-support-for-install-tools&quot;&gt;Mac support for &lt;code&gt;install-tools&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#mac-support-for-install-tools&quot; aria-label=&quot;Anchor link for: mac-support-for-install-tools&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;code&gt;swim&lt;&#x2F;code&gt; subcommand for installing the oss-cad-suite now works on Mac, making initial setup easier.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;contributors&quot;&gt;Contributors&lt;a class=&quot;zola-anchor&quot; href=&quot;#contributors&quot; aria-label=&quot;Anchor link for: contributors&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This release contains contributions from Astrid Lauenstein, DasLixou, Ethan Uppal, José Miguel Sánchez García, and Oscar Gustafsson making it the release with the largest number of contributors to date, thanks everyone!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Quickscope — A quick, but not dirty Integrated Logic Analyzer</title>
        <published>2025-11-10T00:00:00+00:00</published>
        <updated>2025-11-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/quickscope/"/>
        <id>/quickscope/</id>
        
        <content type="html" xml:base="/quickscope/">&lt;p&gt;How long would it take you to write an integrated logic analyzer? With Spade,
I was able to do it in around 3 hours and less than 100 lines of code! In this
post I will describe how it works.&lt;&#x2F;p&gt;
&lt;p&gt;Since the code is relatively short, we can put all of it here. Don&#x27;t worry, we&#x27;ll
walk through the whole thing together one piece at a time, but this gives a brief overview&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;use ready_valid::Rv;

entity quickscope&amp;lt;T, #uint NumBytes, #uint SampleBuffer&amp;gt;(
    clk: clock,
    rst: bool,
    trigger: bool,
    data: T,
) -&amp;gt; Rv&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt; {
    let empty = port;
    let full = port;

    reg(clk) triggered reset (rst: false) = {
        match (triggered, *empty#0, *full#0) {
            &amp;#x2F;&amp;#x2F; We only trigger if the fifo is empty
            (false, true, false) =&amp;gt; trigger,
            &amp;#x2F;&amp;#x2F; If the fifo is full, we un-trigger, i.e. we stop feeding more samples
            &amp;#x2F;&amp;#x2F; into the FIFO
            (true, _, true) =&amp;gt; false,
            &amp;#x2F;&amp;#x2F; In any other case, we keep the trigger state
            (_, _, _) =&amp;gt; triggered
        }
    };
    let triggered_now = inst std::io::rising_edge(clk, trigger);

    let data_in = if triggered { Some(data) } else { None };

    Rv(&amp;amp;data_in, full#1)
        .inst fifo_buffer::&amp;lt;SampleBuffer&amp;gt;(clk, rst)
        .read_empty(empty#1)
        .data
        .inst map(fn (sample) {
            unsafe{ std::conv::transmute::&amp;lt;_, [uint&amp;lt;8&amp;gt;; NumBytes]&amp;gt;(sample) }
        })
        .inst into_element_stream(clk, rst)
        .inst map(fn (byte) { ready_valid::escape_byte::Escaped::Yes(byte) })
        &amp;#x2F;&amp;#x2F; Emit end of packet header
        .inst append_lower_priority(
            inst emit_once(clk, rst, if triggered_now {Some([0xff, 0x01])} else {None})
                .inst into_element_stream(clk, rst)
                .inst map(fn (byte) {ready_valid::escape_byte::Escaped::No(byte)})
        )
        &amp;#x2F;&amp;#x2F; Emit start of packet header
        .inst append_higher_priority(
            inst emit_once(clk, rst, if triggered_now {Some([0xff, 0x00, NumBytes])} else {None})
                .inst into_element_stream(clk, rst)
                .inst map(fn (byte) {ready_valid::escape_byte::Escaped::No(byte)})
        )
        .inst escape_bytes$(
            clk,
            rst,
            escapees: [0xff, 0xfe],
            escape_fn: fn (byte) {byte ^ 0x80},
            escape_prefix: 0xfe,
        )
}

impl&amp;lt;T, #uint N&amp;gt; Rv&amp;lt;[T; N]&amp;gt; {
    entity into_element_stream(self, clk: clock, rst: bool) -&amp;gt; Rv&amp;lt;T&amp;gt;{
        let Rv(data, ready) = self;
        let ds_ready = port;
        reg(clk) (array, num_left): ([T; N], uint&amp;lt;{uint_bits_to_fit(N)}&amp;gt;) reset(rst: (std::undef::undef(), 0)) =
            match (*data, num_left, *ds_ready#0) {
                (Some(data), 0, _) =&amp;gt; (data, N),
                (_, _, false) =&amp;gt; (array, num_left),
                (None, 0, _) =&amp;gt; (array, num_left),
                (Some(data), 1, _) =&amp;gt; (data, N),
                (_, _, _) =&amp;gt; (array[1..N].concat([std::undef::undef()]), trunc(num_left-1))
            };

        set ready = &amp;amp;(num_left == 0 || num_left == 1 &amp;amp;&amp;amp; *ds_ready#0);

        Rv(
            &amp;amp;match num_left {
                0 =&amp;gt; None,
                _ =&amp;gt; Some(array[0]),
            },
            ds_ready#1
        )
    }
}

entity emit_once&amp;lt;T&amp;gt;(clk: clock, rst: bool, value: Option&amp;lt;T&amp;gt;) -&amp;gt; Rv&amp;lt;T&amp;gt; {
    let ds_ready = port;
    reg(clk) to_emit reset(rst: None) = match (to_emit, *ds_ready#0, value) {
        (None, _, Some(new)) =&amp;gt; Some(new),
        (None, _, None) =&amp;gt; None,
        (Some(value), true, None) =&amp;gt; None,
        (Some(value), true, Some(new)) =&amp;gt; Some(new),
        (Some(value), false, _) =&amp;gt; None
    };

    Rv(&amp;amp;to_emit, ds_ready#1)
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The source code for the whole project including the client is available at &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;quickscope&#x2F;&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;quickscope&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;external-interface-and-use&quot;&gt;External Interface and Use&lt;a class=&quot;zola-anchor&quot; href=&quot;#external-interface-and-use&quot; aria-label=&quot;Anchor link for: external-interface-and-use&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first line: &lt;code&gt;use ready_valid::Rv&lt;&#x2F;code&gt; is perhaps the most important line in the entire thing. It imports the &lt;code&gt;Rv&lt;&#x2F;code&gt; type from a library called &lt;code&gt;ready_valid&lt;&#x2F;code&gt;. As the name implies, this provides a type for ready&#x2F;valid interfaces with a ton of functions for working with it. As we will see, this is what does most of the heavy lifting here.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we define the interface to the logic analyzer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity quickscope&amp;lt;T, #uint NumBytes, #uint SampleBuffer&amp;gt;(
   clk: clock,
   rst: bool,
   trigger: bool,
   data: T,
) -&amp;gt; Rv&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt; { 
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, are a few generic parameters:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;T&lt;&#x2F;code&gt;: The type of the data samples we want to analyze. Since it is generic, we can give any Spade type we want and it will work.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;#uint NumBytes&lt;&#x2F;code&gt;: The number of bytes required to store the samples. (This is required because Spade currently does not have something like &lt;code&gt;sizeof&lt;&#x2F;code&gt;, but the compiler ensures that the number is correct)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;#uint SampleBuffer&lt;&#x2F;code&gt;: The number of samples we want to fit in the sample FIFO&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Next are the signals going into the analyzer:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;clk&lt;&#x2F;code&gt; and &lt;code&gt;rst&lt;&#x2F;code&gt; should be self-explanatory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;trigger&lt;&#x2F;code&gt;: When this is true, the analyzer will trigger and send a batch of consecutive samples&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;data&lt;&#x2F;code&gt;: The data we want to analyze&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, is the output of the entity is &lt;code&gt;Rv&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt;&lt;&#x2F;code&gt;: An 8-bit integer wrapped in a
ready&#x2F;valid interface. This means that the raw bytes that this outputs can be
handled by anything that can consume ready&#x2F;valid bytes, for example a UART
device, a UDP streamer, or whatever you can dream up.&lt;&#x2F;p&gt;
&lt;p&gt;In use, this means that we can use &lt;code&gt;quickscope&lt;&#x2F;code&gt; by simply instantiating it with the data of interest, for example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;inst quickscope::quickscope::&amp;lt;_, 11, {65536 &amp;#x2F; 8}&amp;gt;(
         clk,
         rst,
         &amp;#x2F;&amp;#x2F; Trigger signal
         state.is_read(),
         &amp;#x2F;&amp;#x2F; The data we want to analyze, here we&amp;#x27;re passing quite a large structure
         (
             state,
             DramPins$(
                 dq_out: (*pins.dq_out).map(fn (val) {trunc(val)}),
                 dq_in: (*dq_read).map(fn (val) {trunc(val)}),
                 a: *pins.a,
                 ba: *pins.ba,
                 n_we: *pins.n_we,
                 n_ras: *pins.n_ras,
                 n_cas: *pins.n_cas,
     
             ),
             value_expected_pairs.map(fn ((v, e)) {(trunc::&amp;lt;_, uint&amp;lt;10&amp;gt;&amp;gt;(v[0]), trunc::&amp;lt;_, uint&amp;lt;10&amp;gt;&amp;gt;(e[0]))}),
             is_ok,
             is_expected,
         )
     )
     &amp;#x2F;&amp;#x2F; In principle, we can transmit the bytes with anything, but the client currently only works
     &amp;#x2F;&amp;#x2F; with uart so let&amp;#x27;s use that
     .inst into_uart(
         clk,
         rst,
         protocols::uart::UartConfig$(bit_time: 234, parity: false, stop_bits: 2),
         uart_txp,
     );
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this unit instantiated and uploaded to our FPGA, we can run &lt;code&gt;quickscope &#x2F;dev&#x2F;ttyUSB0 115200&lt;&#x2F;code&gt; which will wait for a trigger, then write a &lt;code&gt;.vcd&lt;&#x2F;code&gt; file with the resulting samples. Finally, we can open the &lt;code&gt;.vcd&lt;&#x2F;code&gt; in &lt;code&gt;surfer&lt;&#x2F;code&gt; which, since it has Spade integration, will show the traced signals as a hierarchical structure. Here is a simple example of how that looks:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;quickscope.png&quot; alt=&quot;Quickscope in use, showing a hierarchical structure&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overall-architecture&quot;&gt;Overall Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#overall-architecture&quot; aria-label=&quot;Anchor link for: overall-architecture&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The architecture of the scope is relatively straight forward: the primary piece is a FIFO where samples are stored before being exfiltrated via whatever byte consumer is used. When the scope triggers, this FIFO starts filling up until it reaches its maximum capacity. Since the samples are not single bytes, some logic is required to convert the samples into bytes and stream them out, all of which is orchestrated by ready-valid interfacing.&lt;&#x2F;p&gt;
&lt;p&gt;There is one more thing that must be dealt with: we want to make sure that the client can see the start and end of triggers, and ensure that the data is contiguous, i.e. one batch of data comes from only a single sample. This is done by only allowing triggering when the FIFO is completely empty, and inserting headers for the start and end of data.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rest of the blog post will go through how this architecture is implemented, but you may want to go back to the big source code listing to see how much of it you can infer without any additional context.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#implementation&quot; aria-label=&quot;Anchor link for: implementation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first part of the implementation deals with triggering:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let empty = port;
let full = port;

reg(clk) triggered reset (rst: false) = {
    match (triggered, *empty#0, *full#0) {
       &amp;#x2F;&amp;#x2F; We only trigger if the fifo is empty
       (false, true, false) =&amp;gt; trigger,
       &amp;#x2F;&amp;#x2F; If the fifo is full, we un-trigger, i.e. we stop feeding more samples
       &amp;#x2F;&amp;#x2F; into the FIFO
       (true, _, true) =&amp;gt; false,
       &amp;#x2F;&amp;#x2F; In any other case, we keep the trigger state
       (_, _, _) =&amp;gt; triggered
    }
};
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first two lines define &lt;code&gt;empty&lt;&#x2F;code&gt; and &lt;code&gt;full&lt;&#x2F;code&gt; which we will connect to the sample FIFO later.
Next is the trigger logic which looks at the &lt;code&gt;trigger&lt;&#x2F;code&gt;
signal and the state of the FIFOs in order to start pushing samples into the
FIFO. Once the analyzer is triggered, we leave it triggered until the FIFO is
full at which point we &lt;em&gt;have&lt;&#x2F;em&gt; to stop, otherwise we will get gaps in our
samples. We&#x27;re not quite done yet however, we prevent triggering again until
the FIFO is empty again, in order to ensure that each batch of samples is contiguous and separated with a header&#x2F;footer.&lt;&#x2F;p&gt;
&lt;p&gt;For now, let&#x27;s skip the &lt;code&gt;triggered_now&lt;&#x2F;code&gt; signal.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let triggered_now = inst std::io::rising_edge(clk, trigger);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we use the &lt;code&gt;triggered&lt;&#x2F;code&gt; signal in order to define a &lt;code&gt;data_in&lt;&#x2F;code&gt; signal as
&lt;code&gt;Some(data)&lt;&#x2F;code&gt; when triggered, and &lt;code&gt;None&lt;&#x2F;code&gt; when not. &lt;code&gt;Some&lt;&#x2F;code&gt; and &lt;code&gt;None&lt;&#x2F;code&gt; are the
Spade way to write data with valid signals.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let data_in = if triggered { Some(data) } else { None };
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, this data is wrapped in an &lt;code&gt;Rv&lt;&#x2F;code&gt;, a ready&#x2F;valid interface where we connect the ready signal to the &lt;code&gt;full&lt;&#x2F;code&gt; signal we defined earlier. With this, we can push samples into a FIFO&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;Rv(data_in, full#1)
    .inst fifo_buffer::&amp;lt;SampleBuffer&amp;gt;(clk, rst)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the read side of the FIFO, there are quite a few method instantiations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;    .read_empty(empty#1)
    .data
    .inst map(fn (sample) {
       unsafe{ std::conv::transmute::&amp;lt;_, [uint&amp;lt;8&amp;gt;; NumBytes]&amp;gt;(sample) }
    })
    .inst into_element_stream(clk, rst)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First, we connect the &lt;code&gt;empty&lt;&#x2F;code&gt; signal we defined earlier to the empty signal of the FIFO. Next, we take the samples, which can have any type, and transform them into an array of bytes. Since arbitrary transformations of data is something one should be careful about, Spade requires this operation to be done inside an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block, indicating that extra care is required.
The final method in this block is the &lt;code&gt;.into_element_stream&lt;&#x2F;code&gt; method. It transforms a ready&#x2F;valid-interface of an array with N elements &lt;code&gt;Rv&amp;lt;[T; N]&lt;&#x2F;code&gt; into one of single array elements, &lt;code&gt;T&lt;&#x2F;code&gt;. Here, &lt;code&gt;T&lt;&#x2F;code&gt; is &lt;code&gt;uint&amp;lt;8&amp;gt;&lt;&#x2F;code&gt;, i.e. a byte.&lt;&#x2F;p&gt;
&lt;p&gt;While we could simply send these bytes straight off to the host, the hosts job becomes easier if it receives start and end headers, which is what the next piece of code does:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;.inst map(fn (byte) { ready_valid::escape_byte::Escaped::Yes(byte) })
&amp;#x2F;&amp;#x2F; Emit end of packet header
.inst append_lower_priority(
    inst emit_once(clk, rst, if triggered_now {Some([0xff, 0x01])} else {None})
        .inst into_element_stream(clk, rst)
        .inst map(fn (byte) {ready_valid::escape_byte::Escaped::No(byte)})
)
&amp;#x2F;&amp;#x2F; Emit start of packet header
.inst append_higher_priority(
    inst emit_once(clk, rst, if triggered_now {Some([0xff, 0x00, NumBytes])} else {None})
        .inst into_element_stream(clk, rst)
        .inst map(fn (byte) {ready_valid::escape_byte::Escaped::No(byte)})
)
.inst escape_bytes$(
    clk,
    rst,
    escapees: [0xff, 0xfe],
    escape_fn: fn (byte) {byte ^ 0x80},
    escape_prefix: 0xfe,
)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To do this unambiguously we want to have a few values we can use for these control signals. The &lt;code&gt;escape_bytes&lt;&#x2F;code&gt; method at the end of the chain allows us to do this. We pass it a list of &lt;code&gt;escapees&lt;&#x2F;code&gt; which we do not want to see in the data stream. Next, we give it an &lt;code&gt;escape_fn&lt;&#x2F;code&gt; which is used to transform any of the &lt;code&gt;escapee&lt;&#x2F;code&gt; bytes when encountered, here we flip the most significant bit. Of course, now we have duplicate bytes, both &lt;code&gt;0xff&lt;&#x2F;code&gt; and &lt;code&gt;0x7f&lt;&#x2F;code&gt; will result in &lt;code&gt;0x7f&lt;&#x2F;code&gt;, so we insert an &lt;code&gt;escape_prefix&lt;&#x2F;code&gt; before any escaped byte.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, we do not want to escape any headers, only data, so the first method in the chain marks the raw data as bytes to escape.&lt;&#x2F;p&gt;
&lt;p&gt;This leaves two method calls, &lt;code&gt;apped_lower_priority&lt;&#x2F;code&gt; and
&lt;code&gt;append_higher_priority&lt;&#x2F;code&gt;, which as the names imply, put data into the stream
with different priorities. The &lt;code&gt;emit_once&lt;&#x2F;code&gt; instances create &lt;code&gt;Rv&lt;&#x2F;code&gt; streams with
some headers if the scope was triggered &lt;em&gt;now&lt;&#x2F;em&gt;, and since these are headers they
are wrapped in &lt;code&gt;Escaped::No&lt;&#x2F;code&gt;.
The effect of all this logic is that once triggered, all three streams will
have data. The highest priority stream containing the headers will emit its
bytes first, then the main data stream which has higher priority will emit its
data, and only once that is done will the lowest priority &quot;footer&quot; be emitted.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wait-is-this-hls&quot;&gt;Wait, is this HLS?&lt;a class=&quot;zola-anchor&quot; href=&quot;#wait-is-this-hls&quot; aria-label=&quot;Anchor link for: wait-is-this-hls&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A natural question that often arises when talking about Spade is &quot;Wait, is this high level synthesis?&quot;, there sure are a lot of high level things going on here. The answer is no. While things like method chains on ready&#x2F;valid interfaces allow a pretty high level description of the architecture, behind each method is some RTL level description that you have full control over. An example of this is the &lt;code&gt;.into_element_stream&lt;&#x2F;code&gt; method which we used earlier. It transforms a ready&#x2F;valid-interface of an array with N elements &lt;code&gt;Rv&amp;lt;[T; N]&lt;&#x2F;code&gt; into one of single array elements, &lt;code&gt;T&lt;&#x2F;code&gt;. Most methods used in the project are implemented in the &lt;code&gt;ready_valid&lt;&#x2F;code&gt; library, but this one is defined in the quickscope project itself, in the&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl&amp;lt;T, #uint N&amp;gt; Rv&amp;lt;[T; N]&amp;gt; {
    entity into_element_stream(self, clk: clock, rst: bool) -&amp;gt; Rv&amp;lt;T&amp;gt;{
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;block. The details here are not super interesting to talk about, it is essentially an FSM that pulls one value from the upstream stream, then emits each element in turn, before pulling another element&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rv-ecosystem&quot;&gt;&lt;code&gt;Rv&lt;&#x2F;code&gt; ecosystem&lt;a class=&quot;zola-anchor&quot; href=&quot;#rv-ecosystem&quot; aria-label=&quot;Anchor link for: rv-ecosystem&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This project clearly leans heavily on that &lt;code&gt;Rv&lt;&#x2F;code&gt; library which you can find at &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;lib&#x2F;ready_valid&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;lib&#x2F;ready_valid&lt;&#x2F;a&gt;. For this project, I ended up adding a few more features to that library, as well as moving a few utilities I wrote elsewhere into the &quot;mainline&quot; project. Being able to have a set of reusable components like this is a big enabler for projects like this, and requires support both from the build tool for dependency management, and from the language which must be able to write generic and re-usable libraries.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-client&quot;&gt;The client&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-client&quot; aria-label=&quot;Anchor link for: the-client&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The client is less interesting to discuss here, and even took longer to write than the hardware implementation. If you are curious, the source code is available at &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;quickscope&#x2F;-&#x2F;tree&#x2F;main&#x2F;client?ref_type=heads&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;quickscope&#x2F;-&#x2F;tree&#x2F;main&#x2F;client?ref_type=heads&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.14.0</title>
        <published>2025-06-26T00:00:00+00:00</published>
        <updated>2025-06-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-14-0/"/>
        <id>/v0-14-0/</id>
        
        <content type="html" xml:base="/v0-14-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.14.0&#x2F;CHANGELOG.md#anchor-014&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.14.0&#x2F;CHANGELOG.md#anchor-014&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.14.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.15746414&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;After a brief hiatus while Frans finished his PhD thesis, we are finally
releasing Spade 0.14.0. This includes long awaited support for lambda
functions, standard library features to go along with that, and, a much more
usable LSP implementation that will no longer bail on the first error.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;lambda-functions&quot;&gt;Lambda functions&lt;a class=&quot;zola-anchor&quot; href=&quot;#lambda-functions&quot; aria-label=&quot;Anchor link for: lambda-functions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Lambda functions are &quot;anonymous&quot; functions that are written in-line where they are used. Their primary use case is to specify transformation on data contained in &quot;containers&quot; like arrays and the &lt;code&gt;Option&lt;&#x2F;code&gt; type.&lt;&#x2F;p&gt;
&lt;p&gt;For example, to add one to the value inside an &lt;code&gt;Option&lt;&#x2F;code&gt; type, you could write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;match value {
  Some(inner) =&amp;gt; Some(inner + 1),
  None =&amp;gt; None
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With lambda functions, you can now use the &lt;code&gt;map&lt;&#x2F;code&gt; function instead&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;value.map(fn (inner) {inner + 1})
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which is much more concise, and chainable. In addition, the map function can be implemented on many types including arrays and the ready valid &lt;code&gt;Rv&lt;&#x2F;code&gt; type, allowing you to change the container without affecting the computation being performed.&lt;&#x2F;p&gt;
&lt;p&gt;The definition of the map function on &lt;code&gt;Option&lt;&#x2F;code&gt; looks like this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl&amp;lt;T&amp;gt; Option&amp;lt;T&amp;gt; {
  fn map&amp;lt;F, O&amp;gt;(self, f: F)
  where F: Fn((T), O)
  {
    match value {
      Some(inner) =&amp;gt; Some(f.call((inner,))),
      None =&amp;gt; None
    }
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I.e. lambda functions are just values which implement the &lt;code&gt;Fn&lt;&#x2F;code&gt; trait which has a &lt;code&gt;.call&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;standard-library-additions&quot;&gt;Standard library additions&lt;a class=&quot;zola-anchor&quot; href=&quot;#standard-library-additions&quot; aria-label=&quot;Anchor link for: standard-library-additions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;With lambda functions implemented, the standard library has gained a few new &quot;combinator&quot; functions that make use of this new functionality&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Option&lt;&#x2F;code&gt; and &lt;code&gt;[T; N]&lt;&#x2F;code&gt; now have a &lt;code&gt;map&lt;&#x2F;code&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Option&lt;&#x2F;code&gt; now has an &lt;code&gt;and_then&lt;&#x2F;code&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[T; N]&lt;&#x2F;code&gt; now has &lt;code&gt;zip&lt;&#x2F;code&gt; for joining two arrays pair-wise and &lt;code&gt;concat&lt;&#x2F;code&gt; for concatenating them together.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Option&lt;&#x2F;code&gt; now has &lt;code&gt;unwrap_or&lt;&#x2F;code&gt;, &lt;code&gt;unwrap_or_undef&lt;&#x2F;code&gt; for getting the inner value out of the option without a match block&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Option&lt;&#x2F;code&gt; now has &lt;code&gt;sliding_window&lt;&#x2F;code&gt; for keeping around the last &lt;code&gt;N&lt;&#x2F;code&gt; values.&lt;&#x2F;li&gt;
&lt;li&gt;The new &lt;code&gt;std::undef::undef&lt;&#x2F;code&gt; function allows you to create an undefined value (currently &lt;code&gt;X&lt;&#x2F;code&gt; in the Verilog backend)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;language-server-protocol-and-error-recovery&quot;&gt;Language Server Protocol and Error Recovery&lt;a class=&quot;zola-anchor&quot; href=&quot;#language-server-protocol-and-error-recovery&quot; aria-label=&quot;Anchor link for: language-server-protocol-and-error-recovery&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The Spade language server has supported inline errors, go to definition and hover for quite a while, but the compiler has been to eager to error out on the first sign of trouble making the LSP relatively useless. With 0.14.0, this is now much improved allowing the LSP to keep up.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, the hover information has been improved. You can now see the types of variables and expressions when hovering over them, function signatures and documentation are shown for both functions and methods, and the inferred output type of methods is also shown on hover&lt;&#x2F;p&gt;
&lt;p&gt;These mastodon posts have a few examples of this functionality:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;https:&#x2F;&#x2F;mastodon.social&#x2F;@thezoq2&#x2F;114649713513195455&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;mastodon.social&#x2F;@thezoq2&#x2F;114647080504928422&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;mastodon.social&#x2F;@thezoq2&#x2F;114647085989178649&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;surfer-webassembly-plugin&quot;&gt;Surfer WebAssembly plugin&lt;a class=&quot;zola-anchor&quot; href=&quot;#surfer-webassembly-plugin&quot; aria-label=&quot;Anchor link for: surfer-webassembly-plugin&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The integration with Surfer has long been in the source tree of &lt;code&gt;surfer&lt;&#x2F;code&gt;, requiring you to match your Surfer version with your Spade version. On the latest surfer version, it can now load web assembly plugins, so the Spade integration has been moved out into that system.&lt;&#x2F;p&gt;
&lt;p&gt;For now, this requires manual installation, by running &lt;code&gt;install.bash&lt;&#x2F;code&gt; in the &lt;code&gt;spade-surfer-plugin&lt;&#x2F;code&gt; directory, but automated install will be added to swim soon.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;surfer-name-translation&quot;&gt;Surfer name translation&lt;a class=&quot;zola-anchor&quot; href=&quot;#surfer-name-translation&quot; aria-label=&quot;Anchor link for: surfer-name-translation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The Spade compiler produces anonymous names &lt;code&gt;_e_...&lt;&#x2F;code&gt; for any intermediate signals it creates. As more and more functionality in Spade is written using more complex expressions like methods, this becomes hard to debug. With this update, Surfer can translate these names back to their source code location, allowing you to view signals not only for your named variables, but also intermediate expressions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;functions-can-now-contain-wires&quot;&gt;Functions can now contain wires&lt;a class=&quot;zola-anchor&quot; href=&quot;#functions-can-now-contain-wires&quot; aria-label=&quot;Anchor link for: functions-can-now-contain-wires&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Previously, the language did not allow &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; or &lt;code&gt;inv &amp;amp;&lt;&#x2F;code&gt; in functions. This ended
up being too restrictive as it is entirely possible to write combinatorial
functions using them. This restriction is now lifted.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.13.0</title>
        <published>2025-02-20T00:00:00+00:00</published>
        <updated>2025-02-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-13-0/"/>
        <id>/v0-13-0/</id>
        
        <content type="html" xml:base="/v0-13-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.13.0&#x2F;CHANGELOG.md#anchor-013&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.13.0&#x2F;CHANGELOG.md#anchor-013&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.13.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;TODO&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today we&#x27;re releasing Spade 0.13, one of the biggest Spade releases yet! It
includes &lt;code&gt;gen if&lt;&#x2F;code&gt; for compile time conditionals and recursion, lots of
namespacing fixes, improvements to handling external Verilog, and lots more.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gen-if&quot;&gt;&lt;code&gt;gen if&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#gen-if&quot; aria-label=&quot;Anchor link for: gen-if&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;code&gt;gen if&lt;&#x2F;code&gt; allows you to conditionally branch based on type parameters. The primary use
case for this is recursively iterating over arrays. For example, you can now write
a function that adds one to every element in an array like this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn add_one&amp;lt;#W, #N&amp;gt;(x: [int&amp;lt;W&amp;gt;; N]) -&amp;gt; [int&amp;lt;{W+1}&amp;gt;; N] {
  gen if N == 0 {
    []
  } else {
    [x[0] + 1] `concat_arrays` add_one(x[1:N])
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this is useful for some things in isolation, it is going to lay the
groundwork for more complex generic constructs in later releases, especially
once lambdas are implemented.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;interacting-with-external-verilog&quot;&gt;Interacting with external Verilog&lt;a class=&quot;zola-anchor&quot; href=&quot;#interacting-with-external-verilog&quot; aria-label=&quot;Anchor link for: interacting-with-external-verilog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This release changes the syntax of the old &lt;code&gt;__builtin__&lt;&#x2F;code&gt; marker to &lt;code&gt;extern&lt;&#x2F;code&gt; to make
it less hacky and more clear what it does. The &lt;code&gt;#[no_mangle]&lt;&#x2F;code&gt; attribute has also
been given a &lt;code&gt;all&lt;&#x2F;code&gt; parameter which blanket applies &lt;code&gt;#[no_mangle]&lt;&#x2F;code&gt; to all parameters.&lt;&#x2F;p&gt;
&lt;p&gt;What used to look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity external_verilog(
  #[no_mangle] clk: clock,
  #[no_mangle] a: uint&amp;lt;8&amp;gt;,
  #[no_mangle] b: uint&amp;lt;8&amp;gt;,
  #[no_mangle] out: inv &amp;amp;uint&amp;lt;8&amp;gt;
) __builtin__
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;now looks like this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;#[no_mangle(all)]
extern entity external_verilog(clk: clock, a: uint&amp;lt;8&amp;gt;, b: uint&amp;lt;8&amp;gt;, out: inv &amp;amp;uint&amp;lt;8&amp;gt;);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Including external Verilog in Swim has also been improved, there is now a
&lt;code&gt;[verilog]&lt;&#x2F;code&gt; and &lt;code&gt;[synthesis.verilog]&lt;&#x2F;code&gt; section in &lt;code&gt;swim.toml&lt;&#x2F;code&gt; which allows you
to both include specific Verilog files, and specify include directories.&lt;&#x2F;p&gt;
&lt;p&gt;You can now also use &lt;code&gt;where&lt;&#x2F;code&gt; clauses on extern units.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dQw4w9WgXcQ&quot;&gt;Ethan&lt;&#x2F;a&gt; for all these changes!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;namespacing-changes&quot;&gt;Namespacing changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#namespacing-changes&quot; aria-label=&quot;Anchor link for: namespacing-changes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The namespacing system has seen several improvements in this release. The most user
facing change is that all modules now need a &lt;code&gt;main.spade&lt;&#x2F;code&gt; at the root of the module,
and for other files to be included in the project, you need to add &lt;code&gt;mod filename;&lt;&#x2F;code&gt; to
the corresponding &lt;code&gt;main.spade&lt;&#x2F;code&gt;. For rust users, this will feel very familiar, what rust calls
&lt;code&gt;main.rs&lt;&#x2F;code&gt;, &lt;code&gt;lib.rs&lt;&#x2F;code&gt; and &lt;code&gt;mod.rs&lt;&#x2F;code&gt; are all called &lt;code&gt;main.spade&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The namespace of the &lt;code&gt;main.spade&lt;&#x2F;code&gt; file has also changed, a &lt;code&gt;main.spade&lt;&#x2F;code&gt; with&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn a() {}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;in a project called &lt;code&gt;project&lt;&#x2F;code&gt; would previously result in &lt;code&gt;project::main::a&lt;&#x2F;code&gt;, now it
results in &lt;code&gt;project::a;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There have also been several bug fixes and improvements in the name resolution system including&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;use&lt;&#x2F;code&gt; statements of undefined names now error on the &lt;code&gt;use&lt;&#x2F;code&gt; instead of when using the &lt;code&gt;use&lt;&#x2F;code&gt;d name.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;use&lt;&#x2F;code&gt; between namespaces now works as expected&lt;&#x2F;li&gt;
&lt;li&gt;No more stack overflows or infinite recursion if &lt;code&gt;use&lt;&#x2F;code&gt;-ing a single identifier&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;DasLixou&#x2F;&quot;&gt;DasLixou&lt;&#x2F;a&gt; for most of these fixes!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;expressions-are-now-statements&quot;&gt;Expressions are now statements&lt;a class=&quot;zola-anchor&quot; href=&quot;#expressions-are-now-statements&quot; aria-label=&quot;Anchor link for: expressions-are-now-statements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;If you wanted to call a unit with &quot;side effects&quot; previously, you would have had to write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let _ = inst unit(some_port);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;now you can just write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;inst unit(some_port);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;improved-const-generics&quot;&gt;Improved const generics&lt;a class=&quot;zola-anchor&quot; href=&quot;#improved-const-generics&quot; aria-label=&quot;Anchor link for: improved-const-generics&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can use const generics in unit parameter and output types, which means you no longer
have to add &quot;internal&quot; type parameters and &lt;code&gt;where&lt;&#x2F;code&gt; clauses. For example, you can now
write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn weird_operation&amp;lt;#uint N&amp;gt;(a: uint&amp;lt;N&amp;gt;, b: uint&amp;lt;{N+5}&amp;gt;) -&amp;gt; uint&amp;lt;{N&amp;#x2F;2}&amp;gt; {}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;synchronous-resets&quot;&gt;Synchronous Resets&lt;a class=&quot;zola-anchor&quot; href=&quot;#synchronous-resets&quot; aria-label=&quot;Anchor link for: synchronous-resets&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Spade now uses synchronous resets for all registers instead of asynchronous.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;other-fixes&quot;&gt;Other fixes&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-fixes&quot; aria-label=&quot;Anchor link for: other-fixes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;There have also been numerous small fixes and improvements that don&#x27;t fit in
this blog post, you can read them all in the
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.13.0&#x2F;CHANGELOG.md#anchor-013&quot;&gt;Changelog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;spadetid&quot;&gt;SPADETID!&lt;a class=&quot;zola-anchor&quot; href=&quot;#spadetid&quot; aria-label=&quot;Anchor link for: spadetid&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Frans has started regularly streaming Spade development on
&lt;a href=&quot;https:&#x2F;&#x2F;www.twitch.tv&#x2F;thezoq2&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.twitch.tv&#x2F;thezoq2&#x2F;&lt;&#x2F;a&gt;. If you want
to be notified when this happens, you can join the
&lt;a href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;YtXbeamxEX&quot;&gt;discord&lt;&#x2F;a&gt; and give yourself the &lt;code&gt;SPADETID&lt;&#x2F;code&gt; role.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.12.0</title>
        <published>2025-01-09T00:00:00+00:00</published>
        <updated>2025-01-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-12-0/"/>
        <id>/v0-12-0/</id>
        
        <content type="html" xml:base="/v0-12-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.12.0&#x2F;CHANGELOG.md#anchor-012&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.12.0&#x2F;CHANGELOG.md#anchor-012&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.12.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;zenodo.org&#x2F;records&#x2F;14623297&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Happy new year everyone! Today we&#x27;re releasing Spade 0.12.0. All in all, this is quite a
boring release (in a good way) that mostly fixes a ton of bugs, but there are some new features too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;swim-changes&quot;&gt;Swim changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#swim-changes&quot; aria-label=&quot;Anchor link for: swim-changes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The build tool has seen quite a few nice improvements in this release&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gowin-support&quot;&gt;Gowin support&lt;a class=&quot;zola-anchor&quot; href=&quot;#gowin-support&quot; aria-label=&quot;Anchor link for: gowin-support&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Gowin FPGAs are now supported by swim which makes using Spade on one as simple as&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;swim init --board tangnano9k
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have one of these FPGAs lying around, now is a great time to try Spade!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;less-chatty-swim-output&quot;&gt;Less Chatty Swim Output&lt;a class=&quot;zola-anchor&quot; href=&quot;#less-chatty-swim-output&quot; aria-label=&quot;Anchor link for: less-chatty-swim-output&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Swim will now only print output from commands that fail or those that end up
running for more than a few seconds. This makes it easier to filter out the
unimportant parts of the log, and it looks a bit cleaner. You can see it in
action here: [https:&#x2F;&#x2F;asciinema.org&#x2F;a&#x2F;j9HRvwzAWnoFBVCt4Zj8wM2LE]&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-swim-changes&quot;&gt;Other Swim changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-swim-changes&quot; aria-label=&quot;Anchor link for: other-swim-changes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you use &lt;code&gt;swim install-tools&lt;&#x2F;code&gt; we now use a bleeding edge &lt;code&gt;oss-cad-suite&lt;&#x2F;code&gt;
again. Beyond enabling the gowin support, this should give a nice improvement
in performance thanks to improvements in yosys and nextpnr that we&#x27;ve been
missing out on due to the pinned cad suite.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;methods-on-arrays-and-wires&quot;&gt;Methods on Arrays and Wires&lt;a class=&quot;zola-anchor&quot; href=&quot;#methods-on-arrays-and-wires&quot; aria-label=&quot;Anchor link for: methods-on-arrays-and-wires&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now add methods to arrays and wires. This is of course useful in user
code, and also allows us to add some missing conversion functions to the
standard library.&lt;&#x2F;p&gt;
&lt;p&gt;You can now use &lt;code&gt;.to_int()&lt;&#x2F;code&gt; and &lt;code&gt;.to_uint()&lt;&#x2F;code&gt; on arrays of bools (&lt;code&gt;[bool; N]&lt;&#x2F;code&gt;),
where you previously had to use &lt;code&gt;bits_to_int()&lt;&#x2F;code&gt; and &lt;code&gt;bits_to_uint()&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bug-squashing&quot;&gt;Bug Squashing&lt;a class=&quot;zola-anchor&quot; href=&quot;#bug-squashing&quot; aria-label=&quot;Anchor link for: bug-squashing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve fixed quite a few bugs with this release. A lot of them related to
compiler panics or miscompilations when writing zero size types.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fix a few codegen bugs around enums with 1 variant and no members&lt;&#x2F;li&gt;
&lt;li&gt;Fix codegen bug when matching on zero size literals&lt;&#x2F;li&gt;
&lt;li&gt;Fix codegen bug when using zero size integers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Beyond fixing these specific cases, we&#x27;ve made the handling of zero size
types much more robust to errors since that has been a source of nasty bugs.&lt;&#x2F;p&gt;
&lt;p&gt;We fixed another nasty codegen bug that has been around for a while when
indexing nested inverted wire structures&lt;&#x2F;p&gt;
&lt;p&gt;We also fixed a few errors with patterns&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Report error when integer patterns are out of bounds&lt;&#x2F;li&gt;
&lt;li&gt;Fix panic when pattern matching arrays of integers with more than 4 elements&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Verilog annoyingly requires special handing for arrays of single bit values.
This was missing from the code generator for memories which prevented the
synthesis tool from inferring memories for &lt;code&gt;clocked_memory&amp;lt;bool&amp;gt;&lt;&#x2F;code&gt;. This has now
been fixed&lt;&#x2F;p&gt;
&lt;p&gt;Nearly all of these bugs were reported by users, so thanks to everyone that
has been trying out the language and reporting issues!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parser-tweaks&quot;&gt;Parser tweaks&lt;a class=&quot;zola-anchor&quot; href=&quot;#parser-tweaks&quot; aria-label=&quot;Anchor link for: parser-tweaks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Finally, we made some small but important tweaks to the parser&lt;&#x2F;p&gt;
&lt;p&gt;You no longer need to have a new line at the end of a line comment at the end of a file&lt;&#x2F;p&gt;
&lt;p&gt;The compiler no longer allows non-block expressions in if branches.&lt;&#x2F;p&gt;
&lt;p&gt;And finally, we adjusted the precedence of the dereference (&lt;code&gt;*&lt;&#x2F;code&gt;) and bitwise
operators to make more sense and require fewer parenthesis.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.11.0</title>
        <published>2024-11-27T00:00:00+00:00</published>
        <updated>2024-11-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-11-0/"/>
        <id>/v0-11-0/</id>
        
        <content type="html" xml:base="/v0-11-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.11.0&#x2F;CHANGELOG.md#anchor-011&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.11.0&#x2F;CHANGELOG.md#anchor-011&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.11.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.14237394&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today we&#x27;re releasing Spade 0.11.0, a release which makes working with &lt;em&gt;ports&lt;&#x2F;em&gt; a lot easier, among other things.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;mut-is-dead-long-live-inv&quot;&gt;&amp;amp;mut is dead, long live inv &amp;amp;&lt;a class=&quot;zola-anchor&quot; href=&quot;#mut-is-dead-long-live-inv&quot; aria-label=&quot;Anchor link for: mut-is-dead-long-live-inv&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Until this release, Spade had values (&lt;code&gt;T&lt;&#x2F;code&gt;), wires (&lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt;), mutable wires &lt;code&gt;(&amp;amp;mut T)&lt;&#x2F;code&gt; and inverted ports (&lt;code&gt;~T&lt;&#x2F;code&gt;). Importantly &lt;code&gt;~&amp;amp;T&lt;&#x2F;code&gt; and &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; were effectively
the same thing, but did not mix well together. Mutable wires also required the
user of ugly intrinsic functions like &lt;code&gt;new_mut_wire()&lt;&#x2F;code&gt; and &lt;code&gt;read_mut_wire&lt;&#x2F;code&gt; for
creation and reading, while &lt;code&gt;(T, ~T)&lt;&#x2F;code&gt; pairs could be created just by &lt;code&gt;let (x, x_inv) = port&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;With 0.11, we&#x27;re cleaning up this mess. First &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; is gone, and &lt;code&gt;~&amp;amp;T&lt;&#x2F;code&gt; has been
fixed to work in all places that previously expected &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt;. Second, in order to
avoid operator soup, the syntax of inverted types has changed to &lt;code&gt;inv &amp;amp;T&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is obviously a breaking change, but the compiler should tell you what you
need to change. Just replacing all &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; with &lt;code&gt;inv &amp;amp;T&lt;&#x2F;code&gt; should be enough.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;These changes also have fresh documentation at https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;wires.html&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;testing-of-ports&quot;&gt;Testing of ports&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing-of-ports&quot; aria-label=&quot;Anchor link for: testing-of-ports&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;With wires and ports being cleaned up, we also refactored the cocotb testbench wrappers
to make testing ports easier. Previously, if you wanted to test a function like&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl IpStream {
    entity into_ethernet(
        self,
        clk: clock,
        rst: bool,
        source_mac: MacAddr,
        dest_mac: MacAddr,
    ) -&amp;gt; EthernetStream {
        let HeaderPayloadStreamO$(headers, bytes) = self
            .inner
            .inst lower(clk, rst, EthStreamLowerer$(source_mac, dest_mac));
        EthernetStream$(header: headers, payload: bytes)
    }

    entity buffer_header(self, clk: clock, rst: bool) -&amp;gt; IpStream {
        IpStream(self.inner.inst buffer_header(clk, rst))
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You had to write a wrapper to turn all ports with inverted wires into non-inverted wires,&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;struct IpStreamOut {
    eth_byte: Option&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt;,
    headers_ready: bool,
    payload_ready: bool,
}

entity ip_stream_th(
    clk: clock,
    rst: bool,
    ip_headers: Option&amp;lt;IpHeader&amp;gt;,
    payload: Option&amp;lt;uint&amp;lt;8&amp;gt;&amp;gt;
) -&amp;gt; IpStreamOut {
    let headers_ready = inst new_mut_wire();
    let bytes_ready = inst new_mut_wire();
    let s = IpStream(HeaderPayloadStreamO(
        Rv(&amp;amp;ip_headers, headers_ready),
        Rv(&amp;amp;payload, bytes_ready),
    ));
    let out = s
        .inst into_ethernet$(
            clk,
            rst,
            source_mac: MacAddr([1,2,3,4,5,6]),
            dest_mac: MacAddr([11,12,13,14,15,16])
        )
        .inst into_ethernet_bytes(clk, rst);

    IpStreamOut$(
        eth_byte: match out {
            Some(b) =&amp;gt; Some(b.inner),
            None =&amp;gt; None
        },
        headers_ready: inst read_mut_wire(headers_ready),
        payload_ready: inst read_mut_wire(bytes_ready)
    )
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the updates to 0.11, this is no longer necessary, you can now set values on inverted
inputs, and read values on inverted outputs directly from testbenches.&lt;&#x2F;p&gt;
&lt;p&gt;(In this case, you still need a small wrapper because we don&#x27;t directly support testing methods, but it is much less tedious to write)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity into_ethernet_th(
    _self: IpStream,
    clk: clock,
    rst: bool,
    source_mac: MacAddr,
    dest_mac: MacAddr,
) -&amp;gt; EthernetStream {
  _self.into_ethernet$(clk, rst, source_mac, dest_mac)
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;support-for-parametric-verilog&quot;&gt;Support for parametric Verilog&lt;a class=&quot;zola-anchor&quot; href=&quot;#support-for-parametric-verilog&quot; aria-label=&quot;Anchor link for: support-for-parametric-verilog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;ethanuppal&quot;&gt;Ethan Uppal&lt;&#x2F;a&gt; has added support for mapping Spade generics
to Verilog parameters when instantiating external Verilog.&lt;&#x2F;p&gt;
&lt;p&gt;As a simple example, this means we can now directly instantiate&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;verilog&quot; class=&quot;language-verilog &quot;&gt;&lt;code class=&quot;language-verilog&quot; data-lang=&quot;verilog&quot;&gt;module add_constant #(parameter int N = 0, parameter int M = 0) (
    input[7:0] in, 
    output[7:0] out
);
    assign out = in + N + M;
endmodule
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;as&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;mod extern {
    #[no_mangle]
    entity add_constant&amp;lt;#uint N, #uint M&amp;gt;(
        #[no_mangle] in: int&amp;lt;8&amp;gt;,
        #[no_mangle] out: inv &amp;amp;int&amp;lt;8&amp;gt;
    ) __builtin__
}

entity harness(input: int&amp;lt;8&amp;gt;, named: bool) -&amp;gt; int&amp;lt;8&amp;gt; {
  let (out, out_inv) = port;
  let _ = inst extern::add_constant::$&amp;lt;N: 1, M: 2&amp;gt;(input, out_inv);
  out
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This brings new exciting possibilities such as interop with the &lt;a href=&quot;http:&#x2F;&#x2F;www.jhauser.us&#x2F;arithmetic&#x2F;HardFloat.html&quot;&gt;Berkeley
HardFloat&lt;&#x2F;a&gt; library.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;parser-recovery&quot;&gt;Parser Recovery&lt;a class=&quot;zola-anchor&quot; href=&quot;#parser-recovery&quot; aria-label=&quot;Anchor link for: parser-recovery&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Spade has long been plagued by the parser bailing out on the first error. With
this release, this has been improved so it can now do recovery in a lot of
cases.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity main() {
    not valid syntax
}

struct X {
    bool
}

enum Y {
    Variant(a)
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;would previously fail on the first line with no more diagnostics, but now keeps going:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;error: Unexpected `identifier`, expected `}`
  ┌─ testinput:2:9
  │
2 │     not valid syntax
  │         ^^^^^ expected `}`

error: Unexpected `}`, expected `:`
  ┌─ testinput:7:1
  │
7 │ }
  │ ^ expected `:`

error: Unexpected `(`, expected `{`, `,` or `}`
   ┌─ testinput:10:12
   │
10 │     Variant(a)
   │            ^  
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally reporting around semicolons are now better to avoid the &quot;unexpected X
expected ;&quot; in confusing places, and we&#x27;re now resistant to the infamous greek semicolon prank :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;error_recovery.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;const-generics-in-arrays&quot;&gt;Const generics in arrays&lt;a class=&quot;zola-anchor&quot; href=&quot;#const-generics-in-arrays&quot; aria-label=&quot;Anchor link for: const-generics-in-arrays&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now use const generics in range index expressions and array shorthand initialization. This makes it possible to define a generic &quot;shift register&quot; of array elements&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity sreg&amp;lt;#uint ISize, #uint N&amp;gt;(
  clk: clock,
  rst: bool,
  next: Option&amp;lt;int&amp;lt;ISize&amp;gt;&amp;gt;
) -&amp;gt; [int&amp;lt;ISize&amp;gt;; N]  {
  reg(clk) val reset(rst: [0; N]) = match next {
    Some(x) =&amp;gt; val[1:N] `concat_arrays` [x],
    None =&amp;gt; val,
  };
  val
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;test-bench-chattyness-reduction&quot;&gt;Test bench chattyness reduction&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-bench-chattyness-reduction&quot; aria-label=&quot;Anchor link for: test-bench-chattyness-reduction&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The output of test benches is now much cleaner&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is no longer excessive indentation on messages&lt;&#x2F;li&gt;
&lt;li&gt;When Spade stuff fails, you no longer get a generic python backtrace,
instead you get something much easier to parse quickly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre&gt;&lt;code&gt;error: Expected type uint&amp;lt;8&amp;gt;, got bool
  ┌─ py:1:1
  │
1 │ true
  │ ^^^^ Expected uint&amp;lt;8&amp;gt;
  │
  ┌─ py:1:1
  │
1 │ o.a
  │ --- Type uint&amp;lt;8&amp;gt; inferred here
  │
  = note: Expected: uint&amp;lt;8&amp;gt;
               Got: bool



note: A Spade expression failed to compile
    ┌─ field_accesses.py:47
    │
 47 │ _ = s.o.a == &amp;quot;true&amp;quot;
    │ ^^^^^^^^^^^^^^^^^^^ When executing this
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.10.0</title>
        <published>2024-09-18T00:00:00+00:00</published>
        <updated>2024-09-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-10-0/"/>
        <id>/v0-10-0/</id>
        
        <content type="html" xml:base="/v0-10-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.10.0&#x2F;CHANGELOG.md#anchor-090&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.10.0&#x2F;CHANGELOG.md#anchor-090&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.10.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.13789171&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;After an extended summer break, it is time for us to release a new Spade
version! This release includes several new exciting features, most notably: trait bounds,
much improved support for methods, as well as pipelines with inferred depth.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;traits&quot;&gt;Traits&lt;a class=&quot;zola-anchor&quot; href=&quot;#traits&quot; aria-label=&quot;Anchor link for: traits&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now specify trait requirements on generic parameters, for example, you can now describe a UART driver that can send any type as long as it has a method to convert it into a byte&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;trait AsByte {
  fn as_byte(self) -&amp;gt; uint&amp;lt;8&amp;gt;;
}

entity uart&amp;lt;T&amp;gt;(clk: clock, rst: bool, to_send: Option&amp;lt;T&amp;gt;)
  where T: AsByte
{ ... }
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This feature was contributed by Fabian Bleck, Alex Pichler and Rene Wimmer, as
part of their bachelor thesis at Johannes Kepler University. Thanks!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;multiple-non-overlaping-methods-on-generic-types&quot;&gt;Multiple non-overlaping methods on generic types&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiple-non-overlaping-methods-on-generic-types&quot; aria-label=&quot;Anchor link for: multiple-non-overlaping-methods-on-generic-types&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It is now possible to have more than one method on a type, as long as the generic parameters
do not overlap. For example, the standard library now includes &lt;code&gt;to_be_bytes&lt;&#x2F;code&gt; and &lt;code&gt;to_le_bytes&lt;&#x2F;code&gt; for 16, 24 and 32 bit integers&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl uint&amp;lt;16&amp;gt; {
    &amp;#x2F;&amp;#x2F;&amp;#x2F; Converts `self` into an array of bytes in big-endian order. 0x1234
    &amp;#x2F;&amp;#x2F;&amp;#x2F; becomes [0x12, 0x34].
    fn to_be_bytes(self) -&amp;gt; [uint&amp;lt;8&amp;gt;; 2] {
        [trunc(self &amp;gt;&amp;gt; 8), trunc(self)]
    }

    &amp;#x2F;&amp;#x2F;&amp;#x2F; Converts `self` into an array of bytes in little-endian order. 0x1234
    &amp;#x2F;&amp;#x2F;&amp;#x2F; becomes [0x34, 0x12].
    fn to_le_bytes(self) -&amp;gt; [uint&amp;lt;8&amp;gt;; 2] {
        std::conv::flip_array(self.to_be_bytes())
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;turbofishes-on-method&quot;&gt;Turbofishes on method&lt;a class=&quot;zola-anchor&quot; href=&quot;#turbofishes-on-method&quot; aria-label=&quot;Anchor link for: turbofishes-on-method&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now also specify type parameters on methods using turbofishes. This is required if a method has type parameters that cannot be inferred, such as the size of a FIFO.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;stream
  .inst into_fifo::&amp;lt;1024&amp;gt;(...) &amp;#x2F;&amp;#x2F; FIFO with 1024 elements
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;turbofish-wildcards&quot;&gt;Turbofish wildcards&lt;a class=&quot;zola-anchor&quot; href=&quot;#turbofish-wildcards&quot; aria-label=&quot;Anchor link for: turbofish-wildcards&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;If you only want to specify some type parameter and infer the rest, you can now use wildcards (&lt;code&gt;_&lt;&#x2F;code&gt;). These can be placed anywhere in a type, for example, if you want to specify that a type parameter is an unsigned integer of an inferred size, you can use&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;inst method::&amp;lt;_, uint&amp;lt;_&amp;gt;&amp;gt;(...)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;const-generics-in-turbofishes&quot;&gt;Const generics in turbofishes&lt;a class=&quot;zola-anchor&quot; href=&quot;#const-generics-in-turbofishes&quot; aria-label=&quot;Anchor link for: const-generics-in-turbofishes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The final change to the turbofishes and type specifications in this release allows using const generics inside the type specification.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let x: uint&amp;lt;{10 + 12}&amp;gt; = ...;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;pipelines-with-a-type-inferred-depth&quot;&gt;Pipelines with a type-inferred depth&lt;a class=&quot;zola-anchor&quot; href=&quot;#pipelines-with-a-type-inferred-depth&quot; aria-label=&quot;Anchor link for: pipelines-with-a-type-inferred-depth&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Generic parameters can now be used in pipeline depths, allowing pipelines whose
depth depends on the type of their inputs. For now, this is hard to make use of
in practice, but in the future it will open up more possibilities, and making
the change required a significant change in the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;An actual use case that is supported today is to define a pipeline which delays its inputs a configurable amount&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;pipeline({N}) delay&amp;lt;#uint N&amp;gt;(clk: clock, t: T) -&amp;gt; T {
  reg * {N};
    t
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;more-type-expressions&quot;&gt;More type expressions&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-type-expressions&quot; aria-label=&quot;Anchor link for: more-type-expressions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now use &lt;code&gt;-&lt;&#x2F;code&gt;, &lt;code&gt;*&lt;&#x2F;code&gt; and &lt;code&gt;uint_bits_to_fit&lt;&#x2F;code&gt; in const generics. The latter is extra exciting as you can now write a counter whose internal size will be inferred based on the maximum value&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity blink&amp;lt;#uint Period&amp;gt;(clk: clock, rst: bool) -&amp;gt; bool {
  reg(clk) counter: uint&amp;lt;{uint_bits_to_fit(Period)}&amp;gt; =
    if counter == Period {
      0
    } else {
      trunc(counter + 1)
    };
  counter &amp;gt; Period&amp;#x2F;2
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;pattern-matching-on-arrays&quot;&gt;Pattern matching on arrays&lt;a class=&quot;zola-anchor&quot; href=&quot;#pattern-matching-on-arrays&quot; aria-label=&quot;Anchor link for: pattern-matching-on-arrays&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Arrays can now be pattern-matched in match expressions, or unpacked in let bindings.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let [x0, x1] = array;

let xor = match array {
  [true, false] =&amp;gt; true,
  [false, true] =&amp;gt; true,
  _ =&amp;gt; false,
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;array-shorthand-syntax&quot;&gt;Array shorthand syntax&lt;a class=&quot;zola-anchor&quot; href=&quot;#array-shorthand-syntax&quot; aria-label=&quot;Anchor link for: array-shorthand-syntax&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Arrays with &lt;code&gt;N&lt;&#x2F;code&gt; identical elements can now be constructed using &lt;code&gt;[x; N]&lt;&#x2F;code&gt;, for example&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let all_false = [false; 8];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;change-syntax-of-generic-numbers-to-use-uint-or-int-instead-of&quot;&gt;Change syntax of generic numbers to use #uint or #int instead of&lt;a class=&quot;zola-anchor&quot; href=&quot;#change-syntax-of-generic-numbers-to-use-uint-or-int-instead-of&quot; aria-label=&quot;Anchor link for: change-syntax-of-generic-numbers-to-use-uint-or-int-instead-of&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;As part of the changes made in this release, we had to change the syntax of
units taking generic methods from &lt;code&gt;#N&lt;&#x2F;code&gt; to &lt;code&gt;#uint N&lt;&#x2F;code&gt; or &lt;code&gt;#int N&lt;&#x2F;code&gt; depending on
the use case. Existing code can be easily ported by replacing &lt;code&gt;#&lt;&#x2F;code&gt; with &lt;code&gt;#uint&lt;&#x2F;code&gt;,
&lt;code&gt;#int N&lt;&#x2F;code&gt; was not expressible in the language before.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.9.0</title>
        <published>2024-07-04T00:00:00+00:00</published>
        <updated>2024-07-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-9-0/"/>
        <id>/v0-9-0/</id>
        
        <content type="html" xml:base="/v0-9-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.9.0&#x2F;CHANGELOG.md#anchor-090&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.9.0&#x2F;CHANGELOG.md#anchor-090&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.9.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;zenodo.org&#x2F;records&#x2F;12656265&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Happy summer everyone, today we&#x27;re releasing v0.9.0 of Spade. This is one of our
biggest releases yet and packs several really exciting improvements, especially
around writing generic code.&lt;&#x2F;p&gt;
&lt;p&gt;As always, this blog post highlights the most exciting changes and you can read
the whole change log
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.9.0&#x2F;CHANGELOG.md#anchor-090&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;generic-impl-blocks&quot;&gt;Generic impl blocks&lt;a class=&quot;zola-anchor&quot; href=&quot;#generic-impl-blocks&quot; aria-label=&quot;Anchor link for: generic-impl-blocks&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Spade has had &lt;code&gt;impl&lt;&#x2F;code&gt; blocks for a while, but until now they have only been usable
on non-generic types limiting their usefulness. With 0.9.0 you can now write
generic &lt;code&gt;impl&lt;&#x2F;code&gt; blocks such as the new standard library addition &lt;code&gt;is_some&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;impl&amp;lt;T&amp;gt; Option&amp;lt;T&amp;gt; {
  fn is_some(self) -&amp;gt; bool {
    match self {
      Some(_) =&amp;gt; true,
      None =&amp;gt; false,
    }
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thanks to Alex, Rene and Fabian for &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;318&quot;&gt;implementing
this&lt;&#x2F;a&gt; as part of
their bachelor project at JKU!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;where-clauses&quot;&gt;Where clauses&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-clauses&quot; aria-label=&quot;Anchor link for: where-clauses&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You can now use &lt;code&gt;where&lt;&#x2F;code&gt; clauses to constrain integer parameters in generic units. For example, it is now possible to define a function with the same type signature as the &lt;code&gt;+&lt;&#x2F;code&gt; operator for integers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fn add&amp;lt;#In, #Out&amp;gt;(x: int&amp;lt;In&amp;gt;, y: int&amp;lt;In&amp;gt;) -&amp;gt; int&amp;lt;Out&amp;gt;
  where Out: In + 1
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;fixed-point-library&quot;&gt;Fixed point library&lt;a class=&quot;zola-anchor&quot; href=&quot;#fixed-point-library&quot; aria-label=&quot;Anchor link for: fixed-point-library&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Combining generic &lt;code&gt;impl&lt;&#x2F;code&gt; blocks and where clauses, it is now possible to start working on a &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;lib&#x2F;fixed&quot;&gt;fixed point math library in Spade&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As an example, here are the implementations of various arithmetic operators from that library&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;struct Fp&amp;lt;#Size, #FracBits&amp;gt; {
    inner: int&amp;lt;Size&amp;gt;
}

impl&amp;lt;#Size, #FracBits&amp;gt; Fp&amp;lt;Size, FracBits&amp;gt; {
    fn add&amp;lt;#OutSize&amp;gt;(self, other: Fp&amp;lt;Size, FracBits&amp;gt;) -&amp;gt; Fp&amp;lt;OutSize, FracBits&amp;gt;
        where OutSize: Size + 1,
    {
        Fp(self.inner + other.inner)
    }

    fn sub&amp;lt;#OutSize&amp;gt;(self, other: Fp&amp;lt;Size, FracBits&amp;gt;) -&amp;gt; Fp&amp;lt;OutSize, FracBits&amp;gt;
        where OutSize: Size + 1,
    {
        Fp(self.inner - other.inner)
    }

    fn mul&amp;lt;#OutSize, #OutBits&amp;gt;(self, other: Fp&amp;lt;Size, FracBits&amp;gt;) -&amp;gt; Fp&amp;lt;OutSize, OutBits&amp;gt;
        where OutSize: Size+Size,
              OutBits: FracBits+FracBits
    {
        Fp(self.inner * other.inner)
    }

    fn abs&amp;lt;#OutSize&amp;gt;(self) -&amp;gt; Fp&amp;lt;OutSize, FracBits&amp;gt;
        where OutSize: Size + 1
    {
        if self.inner &amp;lt; 0 {
            Fp(0 - self.inner)
        } else {
            Fp(sext(self.inner))
        }
    }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;named-turbofish-arguments&quot;&gt;Named turbofish arguments&lt;a class=&quot;zola-anchor&quot; href=&quot;#named-turbofish-arguments&quot; aria-label=&quot;Anchor link for: named-turbofish-arguments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The final improvements to generics in this release is named turbofish arguments. The &lt;a href=&quot;http:&#x2F;&#x2F;turbo.fish&#x2F;&quot;&gt;turbofish&lt;&#x2F;a&gt; (&lt;code&gt;::&amp;lt;&amp;gt;&lt;&#x2F;code&gt;) is used to specify generic parameters if they cannot be inferred, however, previously you had to specify them positionally which gets confusing if you have a complex generic, for example&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;  fn mul_fp&amp;lt;#Size, #FracBits, #OutSize, #OutBits&amp;gt;(self, other: Fp&amp;lt;Size, FracBits&amp;gt;) -&amp;gt; Fp&amp;lt;OutSize, OutBits&amp;gt;
    where OutSize: Size+Size,
          OutBits: FracBits+FracBits
{
    Fp(self.inner * other.inner)
}

fp_mul::&amp;lt;16, 8, 20, 16&amp;gt;(...)
      &amp;#x2F;&amp;#x2F; ^^^^^^^^^^^^^ Hard to know what these numbers mean
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With named turbofish parameters (&lt;code&gt;::$&amp;lt;&amp;gt;&lt;&#x2F;code&gt;), you can specify the arguments by name, similar to specifying unit arguments&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;fp_mul::$&amp;lt;Size: 16, FracBits: 8, OutSize: 20, OutBits: 16&amp;gt;(...)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The keen reader may wonder why we don&#x27;t use new fancy &lt;code&gt;mul&lt;&#x2F;code&gt; method on
our &lt;code&gt;FixedPoint&lt;&#x2F;code&gt; type. Unfortunately, methods don&#x27;t support turbofish yet
:(&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;impl-blocks-in-modules&quot;&gt;&lt;code&gt;impl&lt;&#x2F;code&gt; blocks in modules&lt;a class=&quot;zola-anchor&quot; href=&quot;#impl-blocks-in-modules&quot; aria-label=&quot;Anchor link for: impl-blocks-in-modules&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The final change to generics is a fix for &lt;code&gt;impl&lt;&#x2F;code&gt; blocks being broken when used in a &lt;code&gt;mod&lt;&#x2F;code&gt;, for example&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;mod {
  impl X {
    ... &amp;#x2F;&amp;#x2F; Oh no, compiler bug! 😱
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;DasLixou&quot;&gt;DasLixou&lt;&#x2F;a&gt; for fixing this and other
issues after looking at the code around namespacing and realizing it was
terrible in general!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;test-improvements&quot;&gt;Test improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-improvements&quot; aria-label=&quot;Anchor link for: test-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Moving on from generics and impl blocks, the cocotb test bench API has seen 2
nice convenience improvements.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;native-python-type-support&quot;&gt;Native python type support&lt;a class=&quot;zola-anchor&quot; href=&quot;#native-python-type-support&quot; aria-label=&quot;Anchor link for: native-python-type-support&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First, it is now possible to assign
integers, booleans and lists directly to Spade types, resolving the need for
some annoying stringifying&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# Before you had to do this if you wanted to assign a python bool to a Spade input
s.i.bool_value = &amp;quot;true&amp;quot; if value else &amp;quot;false&amp;quot;
# Now you can just do
s.i.bool_value = value

# You also no longer need to stringify integers
s.i.int_value = 5

# And you can use python lists natively
s.i.some_integers = [i for i in range(0, 8)]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;operator&quot;&gt;== operator&lt;a class=&quot;zola-anchor&quot; href=&quot;#operator&quot; aria-label=&quot;Anchor link for: operator&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a smaller change, but fixes an anoying issue where if you wanted to compare the output of a module with a Spade expression, you had to do&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;s.o.value_eq(&amp;quot;[1,2,3]&amp;quot;)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can simply write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;s.o == &amp;quot;[1,2,3]&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or combining both changes&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;s.o == [1,2,3]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;small-fixes&quot;&gt;Small fixes&lt;a class=&quot;zola-anchor&quot; href=&quot;#small-fixes&quot; aria-label=&quot;Anchor link for: small-fixes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;This release also includes several small convenience changes&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You can now suffix int literals with a signedness and size to help the type
inferer. For example &lt;code&gt;512u32&lt;&#x2F;code&gt; or &lt;code&gt;123i64&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; and &lt;code&gt;%&lt;&#x2F;code&gt; operators. These work for dividing by constant powers of
two. For other values, the resulting hardware is likely too slow to be what
you want so the compiler gives an error suggesting a different approach. If
you do want to do combinational division or mod, you can use
&lt;code&gt;std::ops::comb_div&lt;&#x2F;code&gt; or &lt;code&gt;std::ops::comb_mod&lt;&#x2F;code&gt; which is suggested by the
compiler&lt;&#x2F;li&gt;
&lt;li&gt;Fixed incorrect code gen for enums with a single variant&lt;&#x2F;li&gt;
&lt;li&gt;Swim cocotb tests now work on more operating systems&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.8.0</title>
        <published>2024-05-14T00:00:00+00:00</published>
        <updated>2024-05-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-8-0/"/>
        <id>/v0-8-0/</id>
        
        <content type="html" xml:base="/v0-8-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.8.0&#x2F;CHANGELOG.md#anchor-080&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.8.0&#x2F;CHANGELOG.md#anchor-080&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.8.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.11192224&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today we&#x27;re releasing &lt;code&gt;v0.8.0&lt;&#x2F;code&gt; of Spade. This release adds a bunch of new stuff
to the standard library, fixes a bunch of papercuts around test and adds
&lt;code&gt;inout&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; to work with inout ports. We also had 2 new contributors in this
release which is very fun to see, thanks @0xC01DC0FFEE and @phire&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-reduce-functions-first-contribution&quot;&gt;Add &lt;code&gt;reduce_*&lt;&#x2F;code&gt; functions (first contribution)&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-reduce-functions-first-contribution&quot; aria-label=&quot;Anchor link for: add-reduce-functions-first-contribution&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;@0xC01DC0FFEE added three new functions to &lt;code&gt;std::ops&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fn reduce_and&amp;lt;#N&amp;gt;(x: uint&amp;lt;N&amp;gt;) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;fn reduce_or&amp;lt;#N&amp;gt;(x: uint&amp;lt;N&amp;gt;) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;fn reduce_xor&amp;lt;#N&amp;gt;(x: uint&amp;lt;N&amp;gt;) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These compute the &lt;code&gt;and&lt;&#x2F;code&gt;, &lt;code&gt;or&lt;&#x2F;code&gt; and &lt;code&gt;xor&lt;&#x2F;code&gt; of all bits in a number. &lt;code&gt;reduce_xor&lt;&#x2F;code&gt;
is especially useful for computing parity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stage-improvements-first-contribution&quot;&gt;&lt;code&gt;stage&lt;&#x2F;code&gt; improvements (first contribution)&lt;a class=&quot;zola-anchor&quot; href=&quot;#stage-improvements-first-contribution&quot; aria-label=&quot;Anchor link for: stage-improvements-first-contribution&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Scott Mansell (@phire) has fixed several issues this release. The most
important fix resolves a long-standing issue where referencing pipeline
variables using &lt;code&gt;stage&lt;&#x2F;code&gt; inside blocks would cause a panic. With this change,
you can now write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;    let x = if condition {stage(+1).y} else {stage(+2).y}
  reg;
    let y = &amp;#x2F;* ... *&amp;#x2F;;
  reg;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;higher-level-memory-primitives-in-std-mem&quot;&gt;Higher level memory primitives in &lt;code&gt;std::mem&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#higher-level-memory-primitives-in-std-mem&quot; aria-label=&quot;Anchor link for: higher-level-memory-primitives-in-std-mem&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;std::mem::dp_bram&lt;&#x2F;code&gt; provides a more structured primitive for working with dual
port memories. Unlike the raw &lt;code&gt;std::mem::clocked_memory&lt;&#x2F;code&gt; primitive which can be
used to model any memory but is quite clunky to use in the common case, the
&lt;code&gt;dp_bram&lt;&#x2F;code&gt; provides a memory with one read port and one write port that can
belong to different clock domains.&lt;&#x2F;p&gt;
&lt;p&gt;Writing to the memory is done using the &lt;code&gt;std::Mem::WritePort&lt;&#x2F;code&gt; struct&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity writer(
    clk: clock,
    wport: WritePort&amp;lt;10, uint&amp;lt;16&amp;gt;&amp;gt;,
) {
    let (addr0, write_val0) = &amp;#x2F;* ... *&amp;#x2F;;

    set wport.addr = addr0;
    set wport.write = write_val0;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And reads are done on the &lt;code&gt;ReadPort&lt;&#x2F;code&gt; struct, preferably using &lt;code&gt;std::mem::read_read_port&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;pipeline(1) reader(
    clk: clock,
    rport: ReadPort&amp;lt;10, uint&amp;lt;16&amp;gt;&amp;gt;,
) -&amp;gt; [[uint&amp;lt;16&amp;gt;; 3]; 3] {
      let addr0 = &amp;#x2F;* ... *&amp;#x2F;;
      let addr1 = &amp;#x2F;* ... *&amp;#x2F;;

      let out0 = inst(1) read_read_port(clk, addr0, rport)
      &amp;#x2F;&amp;#x2F; Since the memory read unit is a pipeline, we can&amp;#x27;t accidentally forget that the memory
      &amp;#x2F;&amp;#x2F; has read latency
  reg;
      &amp;#x2F;&amp;#x2F; Do something fun with the read values!
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;dp_bram&lt;&#x2F;code&gt; module returns two ports which you can then pass along to the reader and writer&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity top(clk: clock) {
  let (write, read) = inst dp_bram::&amp;lt;1024, uint&amp;lt;16&amp;gt;, 10&amp;gt;$(write_clk: clk, read_clk: clk);

  let _ = inst writer(clk, write);
  let _ = inst reader(clk, read);
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One big advantage of this is that since the memory ports are &lt;code&gt;struct port&lt;&#x2F;code&gt;, the compiler
will ensure that there aren&#x27;t multiple users of the ports. For example, the following code results
in a compilation error&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity top(clk: clock) {
  let (write, read) = inst dp_bram::&amp;lt;1024, uint&amp;lt;16&amp;gt;, 10&amp;gt;$(write_clk: clk, read_clk: clk);

  let _ = inst writer(clk, write);
  let _ = inst reader(clk, read);
                        &amp;#x2F;&amp;#x2F; ^^^^ First use here
  let _ = inst reader(clk, read);
                        &amp;#x2F;&amp;#x2F; ^^^^
                        &amp;#x2F;&amp;#x2F; Use of consumed resource
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;clock-domain-crossing-primitives&quot;&gt;Clock domain crossing primitives&lt;a class=&quot;zola-anchor&quot; href=&quot;#clock-domain-crossing-primitives&quot; aria-label=&quot;Anchor link for: clock-domain-crossing-primitives&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The second addition to the stdlib is the new
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;main&#x2F;stdlib&#x2F;cdc.spade&quot;&gt;&lt;code&gt;std::cdc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
module which contains primitives for crossing clock domains. The primary
additions are &lt;code&gt;std::cdc::sync2_bool&lt;&#x2F;code&gt;, &lt;code&gt;std::cdc::sync_wide&lt;&#x2F;code&gt; and
&lt;code&gt;std::cdc::handshake&lt;&#x2F;code&gt; which provide primitives for a few different crossing
scenarios. All of these are &lt;em&gt;extremely danger&lt;&#x2F;em&gt; if used incorrectly, so make
sure to read the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;main&#x2F;stdlib&#x2F;cdc.spade?ref_type=heads&quot;&gt;documentation for the
modules&lt;&#x2F;a&gt;
to make sure that you satisfy the constraints they have to behave correctly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-improvements&quot;&gt;Test improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-improvements&quot; aria-label=&quot;Anchor link for: test-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We have made several improvements to the testing system in Spade&lt;&#x2F;p&gt;
&lt;p&gt;A minor but important change is that tests now support modules that return
&lt;code&gt;void&lt;&#x2F;code&gt;. In addition, the &lt;code&gt;verilator&lt;&#x2F;code&gt; wrapper now works on modules with &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;
inputs.&lt;&#x2F;p&gt;
&lt;p&gt;For &lt;code&gt;verilator&lt;&#x2F;code&gt; tests, we have also added &lt;code&gt;.spade_repr&lt;&#x2F;code&gt; to fields which returns
a human-readable Spade representation of the field. This is useful if you need
to, for example, print a result.&lt;&#x2F;p&gt;
&lt;p&gt;Using these changes, it is possible to use the simulation speed of &lt;code&gt;Verilator&lt;&#x2F;code&gt;
to write &quot;interactive&quot; test benches, here is an example of a testbench that
visualizes the memory access pattern of a camera project I&#x27;m working on:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;memory_visualizer.png&quot; alt=&quot;Screenshot of a window that visualizes the memory access pattern of a camera output&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;latch-up-presentation&quot;&gt;Latch-Up presentation&lt;a class=&quot;zola-anchor&quot; href=&quot;#latch-up-presentation&quot; aria-label=&quot;Anchor link for: latch-up-presentation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Two weeks ago, Frans presented Spade at Latch-Up 2024 in Boston. You can see a
recording of the talk here:&lt;&#x2F;p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;_EdOHbY2dlg?si=Kx6nkwxbEz9aq_L8&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.7.0</title>
        <published>2024-03-21T00:00:00+00:00</published>
        <updated>2024-03-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-7-0/"/>
        <id>/v0-7-0/</id>
        
        <content type="html" xml:base="/v0-7-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.7.0&#x2F;CHANGELOG.md#anchor-070&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.7.0&#x2F;CHANGELOG.md#anchor-070&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.7.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.10849819&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today we&#x27;re releasing &lt;code&gt;v0.7.0&lt;&#x2F;code&gt; of Spade. This release adds additional
capabilities when writing generic code, some new features to the standard
library, and fixes several small annoyances and bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-contributions-tada&quot;&gt;First contributions 🎉&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-contributions-tada&quot; aria-label=&quot;Anchor link for: first-contributions-tada&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Three bachelor students from JKU have started contributing to Spade as part of
their bachelor project. They have made several improvements to the language
this release:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In the previous release, we removed the need to use &lt;code&gt;()&lt;&#x2F;code&gt; after zero parameter
enum variants, but this was accidentally still needed when &lt;code&gt;use&lt;&#x2F;code&gt;ing enum
variants. This has now been fixed, so &lt;code&gt;None()&lt;&#x2F;code&gt; can be written as &lt;code&gt;None&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;You can now use the bitwise invert operator (&lt;code&gt;~&lt;&#x2F;code&gt;) on unsigned integers&lt;&#x2F;li&gt;
&lt;li&gt;Fixing a compiler panic when using the wrong number of arguments in a turbofish (&lt;code&gt;::&amp;lt;&amp;gt;&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thanks Alex, Rene and Fabian!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;generic-parameters-as-expressions&quot;&gt;Generic parameters as expressions&lt;a class=&quot;zola-anchor&quot; href=&quot;#generic-parameters-as-expressions&quot; aria-label=&quot;Anchor link for: generic-parameters-as-expressions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With this release, it is now possible to use generic integers as constants
inside modules, for example a counter with a constant maximum value can be
written as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity counter::&amp;lt;#Width, #Max&amp;gt;(clk: clock, rst: bool) -&amp;gt; uint&amp;lt;Width&amp;gt; {
    reg(clk) val reset(rst: 0) = if val == Max {0} else {trunc(val + 1)};
    val
}

&amp;#x2F;&amp;#x2F; Emits a tick every 10th clock cycle
entity count_to_10(clk: clock, rst: bool) -&amp;gt; bool {
  inst counter::&amp;lt;4, 9&amp;gt;(clk, rst) == 9
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As part of this change, it is now also possible to refer to generic parameters
inside the body of units, so you no no longer have to rely on the type inferer
to get what you mean. This is very useful when wrapping memories&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;entity&quot; class=&quot;language-entity &quot;&gt;&lt;code class=&quot;language-entity&quot; data-lang=&quot;entity&quot;&gt;entity fifo&amp;lt;#W, D, #C&amp;gt;(
    write_clk: clock,
    write_rst: bool,
    read_clk: clock,
    read_rst: bool
) -&amp;gt; (FifoWrite&amp;lt;D&amp;gt;, FifoRead&amp;lt;W, D&amp;gt;) {
    &amp;#x2F;&amp;#x2F; ...
    let (ram_write, ram_read) = inst dp_bram::&amp;lt;W, D, C&amp;gt;(write_clk, read_clk);
                                            &amp;#x2F;&amp;#x2F; ^^^^^^^ These had to be inferred previously
    &amp;#x2F;&amp;#x2F; ...
}

&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;misc-smaller-changes&quot;&gt;Misc smaller changes&lt;a class=&quot;zola-anchor&quot; href=&quot;#misc-smaller-changes&quot; aria-label=&quot;Anchor link for: misc-smaller-changes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;It is now possible to write &lt;code&gt;1-2&lt;&#x2F;code&gt;, previously a space was required.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;swim clean&lt;&#x2F;code&gt; no longer removes the compiled Spade compiler leading to faster clean build times.&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;code&gt;--use-sudo&lt;&#x2F;code&gt; to swim to run upload tools with superuser permissions. This can be helpful if you don&#x27;t have udev rules set up.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;spade-at-conferences&quot;&gt;Spade at conferences&lt;a class=&quot;zola-anchor&quot; href=&quot;#spade-at-conferences&quot; aria-label=&quot;Anchor link for: spade-at-conferences&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Frans will be at &lt;a href=&quot;https:&#x2F;&#x2F;www.date-conference.com&#x2F;&quot;&gt;DATE&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;osda.ws&#x2F;&quot;&gt;OSDA
2024&lt;&#x2F;a&gt; next week! If you&#x27;re also going to be there get in
touch!&lt;&#x2F;p&gt;
&lt;p&gt;Spade will also be presented at
&lt;a href=&quot;https:&#x2F;&#x2F;fossi-foundation.org&#x2F;latch-up&#x2F;2024&quot;&gt;LatchUp&lt;&#x2F;a&gt; in Boston on May 19-21,
and the week after that Frans is co-organizing &lt;a href=&quot;https:&#x2F;&#x2F;capra.cs.cornell.edu&#x2F;latte24&#x2F;&quot;&gt;LATTE
2024&lt;&#x2F;a&gt; which is co-located with
&lt;a href=&quot;https:&#x2F;&#x2F;www.asplos-conference.org&#x2F;&quot;&gt;ASPLOS&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.6.0</title>
        <published>2023-12-28T00:00:00+00:00</published>
        <updated>2023-12-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-6-0/"/>
        <id>/v0-6-0/</id>
        
        <content type="html" xml:base="/v0-6-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.6.0&#x2F;CHANGELOG.md#anchor-060&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.6.0&#x2F;CHANGELOG.md#anchor-060&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.6.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.10454664&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This holiday season we&#x27;re releasing 0.6.0 of Spade. The focus for this release has been
fixing small annoyances in the language to make it nicer to work with and more complete.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unsigned-integers&quot;&gt;Unsigned integers&lt;a class=&quot;zola-anchor&quot; href=&quot;#unsigned-integers&quot; aria-label=&quot;Anchor link for: unsigned-integers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For a long time, Spade has only had one integer type: &lt;code&gt;int&lt;&#x2F;code&gt; which has been primarily
used for signed integers but has been used to emulate unsigned integers where required.
However, &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@thezoq2&#x2F;111603404917456410&quot;&gt;as it turns
out&lt;&#x2F;a&gt;, this results in
incorrect values when additions add additional bits, as is the case for all
additions in Spade.&lt;&#x2F;p&gt;
&lt;p&gt;This finally gave us the motivation to add a proper unsigned type, &lt;code&gt;uint&lt;&#x2F;code&gt;. It
is a drop-in replacement for the old hacky signed-as-unsigned integer system
and all the basic operators are overloaded to work with both &lt;code&gt;int&lt;&#x2F;code&gt; and &lt;code&gt;uint&lt;&#x2F;code&gt;.
This uses a lot of compiler infrastructure that has been added for traits,
which means that user defined operator overloading is on the horizon.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;turbofish&quot;&gt;Turbofish&lt;a class=&quot;zola-anchor&quot; href=&quot;#turbofish&quot; aria-label=&quot;Anchor link for: turbofish&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For too long, the Spade language has not had any fish in the language itself.
That changes today! The &lt;a href=&quot;https:&#x2F;&#x2F;turbo.fish&quot;&gt;&quot;turbofish&quot;&lt;&#x2F;a&gt; &lt;code&gt;::&amp;lt;&amp;gt;&lt;&#x2F;code&gt; syntax can be
used to specify type parameters for units when they cannot be inferred, for example
&lt;code&gt;trunc::&amp;lt;int&amp;lt;8&amp;gt;, int&amp;lt;6&amp;gt;&amp;gt;(a)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cast-functions&quot;&gt;Cast functions&lt;a class=&quot;zola-anchor&quot; href=&quot;#cast-functions&quot; aria-label=&quot;Anchor link for: cast-functions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The standard library now contains several functions for casting between
bit-like types such as integers and arrays of bools.&lt;&#x2F;p&gt;
&lt;p&gt;The star of the show is the new &lt;code&gt;std::conv::unsafe::unsafe_cast&lt;&#x2F;code&gt; which simply
re-interprets the bits. As the name implies, the guarantees this provides for
most types are pretty much &quot;lmao, good luck&quot;, so it is primarily to be used
internally in &lt;code&gt;std::conv::int_to_bits&lt;&#x2F;code&gt; and &lt;code&gt;std::conv::bits_to_int&lt;&#x2F;code&gt; which are
safe to call.&lt;&#x2F;p&gt;
&lt;p&gt;For those times where you want to do cursed things with clocks, there is also
&lt;code&gt;std::conv::unsafe::clock_to_bool&lt;&#x2F;code&gt; and &lt;code&gt;std::conv::unsafe::bool_to_clock&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, there is now a &lt;code&gt;std::conv::flip_bits&lt;&#x2F;code&gt; which reverses the bits in an
array, since that is hard to express neatly in Spade without a builtin
function.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enum-variant-ergonomics&quot;&gt;Enum variant ergonomics&lt;a class=&quot;zola-anchor&quot; href=&quot;#enum-variant-ergonomics&quot; aria-label=&quot;Anchor link for: enum-variant-ergonomics&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In rust, if you instantiate an enum variant that has no parameters, like &lt;code&gt;None&lt;&#x2F;code&gt;, you don&#x27;t have to call it like a function, i.e. &lt;code&gt;None()&lt;&#x2F;code&gt;.
The same thing now applies in Spade, making the language feel more familiar to
rust users, and a bit more consistent, since the parentheses were already not
needed in match patterns.&lt;&#x2F;p&gt;
&lt;p&gt;To avoid massive breaking changes, the old style is also supported&lt;&#x2F;p&gt;
&lt;h2 id=&quot;array-range-indexing&quot;&gt;Array range indexing&lt;a class=&quot;zola-anchor&quot; href=&quot;#array-range-indexing&quot; aria-label=&quot;Anchor link for: array-range-indexing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can now index arrays by ranges, as long as the ranges are statically known. For example: the following code now compiles and runs without error&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let a = [1, 2, 3, 4];
assert a[1:3] == [2, 3];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;block-comments&quot;&gt;Block comments&lt;a class=&quot;zola-anchor&quot; href=&quot;#block-comments&quot; aria-label=&quot;Anchor link for: block-comments&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;3 years in, Spade finally has block comments naturally denoted by &lt;code&gt;&#x2F;*&lt;&#x2F;code&gt; and
&lt;code&gt;*&#x2F;&lt;&#x2F;code&gt;. Of course, block comments can be nested, unlike &lt;em&gt;some&lt;&#x2F;em&gt; languages&lt;&#x2F;p&gt;
&lt;h2 id=&quot;call-by-name&quot;&gt;Call by name&lt;a class=&quot;zola-anchor&quot; href=&quot;#call-by-name&quot; aria-label=&quot;Anchor link for: call-by-name&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A internal change has been made to the way the compiler instantiates units. In
the resulting Verilog code, arguments were previously passed positionally like
this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;verilog&quot; class=&quot;language-verilog &quot;&gt;&lt;code class=&quot;language-verilog&quot; data-lang=&quot;verilog&quot;&gt;subunit unit_0(arg1, arg2, arg3);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In 0.6.0 they are now instead instantiated by name&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;verilog&quot; class=&quot;language-verilog &quot;&gt;&lt;code class=&quot;language-verilog&quot; data-lang=&quot;verilog&quot;&gt;subunit unit_0(.param1(arg1), .param2(arg2), .param3(arg3));
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this makes no difference for Spade code where the compiler knows the
argument order, it did cause problems when instantiating external Verilog like
vendor primitives, or VHDL code where argument order is less well known.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, the following code now works as expected whereas it would behave incorrectly before&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;#[no_mangle]
fn external_verilog_module(first_arg: bool, second_arg: bool, result: &amp;amp;mut bool) __builtin__
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;verilog&quot; class=&quot;language-verilog &quot;&gt;&lt;code class=&quot;language-verilog&quot; data-lang=&quot;verilog&quot;&gt;module external_verilog_module(input second_arg_i, input first_arg_i, output result_o);
  &amp;#x2F;&amp;#x2F; ...
endmodule
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.5.0</title>
        <published>2023-11-17T00:00:00+00:00</published>
        <updated>2023-11-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-5-0/"/>
        <id>/v0-5-0/</id>
        
        <content type="html" xml:base="/v0-5-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.5.0&#x2F;CHANGELOG.md#anchor-050&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.5.0&#x2F;CHANGELOG.md#anchor-050&quot;&gt;Swim changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.5.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.10149647&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Welcome back to a new Spade release! This time we&#x27;re releasing version 0.5.0 of
Spade and Swim. We skipped the previous release window, so this one contains
a bit more stuff than usual.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;language-reference&quot;&gt;Language reference&lt;a class=&quot;zola-anchor&quot; href=&quot;#language-reference&quot; aria-label=&quot;Anchor link for: language-reference&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We have started work on a language reference. The progress is slow but ongoing.
You can check out &lt;a href=&quot;https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;language_reference&#x2F;index.html&quot;&gt;the language reference chapter in the Spade
book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verilator-simulation&quot;&gt;Verilator simulation&lt;a class=&quot;zola-anchor&quot; href=&quot;#verilator-simulation&quot; aria-label=&quot;Anchor link for: verilator-simulation&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Spade has supported cocotb testbenches written in Python for a while now. New in
this version is the ability to write tests with Verilator in C++! Here&#x27;s a short
example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c++&quot; class=&quot;language-c++ &quot;&gt;&lt;code class=&quot;language-c++&quot; data-lang=&quot;c++&quot;&gt;&amp;#x2F;&amp;#x2F; top=cxx::top::add

#include &amp;lt;cassert&amp;gt;
#define TOP add

#include &amp;lt;verilator_util.hpp&amp;gt;

TEST_CASE(it_works, {
    dut-&amp;gt;eval();
    ctx-&amp;gt;timeInc(1);
    dut-&amp;gt;eval();

    s.i-&amp;gt;a = &amp;quot;5&amp;quot;;
    s.i-&amp;gt;b = &amp;quot;10&amp;quot;;

    ctx-&amp;gt;timeInc(1);
    dut-&amp;gt;eval();

    ASSERT_EQ(s.o, &amp;quot;15&amp;quot;)

    return 0;
})

MAIN
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For more details on how to write testbenches, see the newly added &lt;a href=&quot;https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;simulation.html#verilator&quot;&gt;Verilator documentation in the Spade
book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;oss-cad-suite&quot;&gt;&lt;code&gt;oss-cad-suite&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#oss-cad-suite&quot; aria-label=&quot;Anchor link for: oss-cad-suite&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One unfortunate reality with open source FPGAs is the need for multiple
different programs to synthesize, place-and-route and programming that are not
always distributed as distribution packages. To alleviate this, the Yosys
organization releases a packed binary software distribution called
&lt;code&gt;oss-cad-suite&lt;&#x2F;code&gt; containing open source software for doing digital design. Swim
has learned about &lt;code&gt;oss-cad-suite&lt;&#x2F;code&gt;, so now you can run &lt;code&gt;swim install-tools&lt;&#x2F;code&gt; which
will install the latest version and use it when running Swim.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;$ swim synth
...
[INFO] Synthesizing
Error:
   0: Failed to run yosys
   1: No such file or directory (os error 2)

Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
$ swim install-tools
[INFO] Requesting list of releases
[INFO] Downloading oss-cad-suite-linux-x64-20231117.tgz from
https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;YosysHQ&amp;#x2F;oss-cad-suite-build&amp;#x2F;releases&amp;#x2F;download&amp;#x2F;2023-11-17&amp;#x2F;oss-cad-suite-linux-x64-20231117.tgz
$ swim synth
[INFO] Synthesizing
...
[INFO] Synthesized ...&amp;#x2F;build&amp;#x2F;hardware.json
$ :-)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tomldoc&quot;&gt;tomldoc&lt;a class=&quot;zola-anchor&quot; href=&quot;#tomldoc&quot; aria-label=&quot;Anchor link for: tomldoc&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Swim projects are configured using a file called &lt;code&gt;swim.toml&lt;&#x2F;code&gt;, much like how
Cargo projects are configured using a file called &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;. The format of
this file (which fields and sections are available) changes pretty often, and
crucially, often enough to make it difficult to keep external documentation up
to date. After a &lt;del&gt;critical hit&lt;&#x2F;del&gt; double &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;356&#x2F;&quot;&gt;nerd snipe&lt;&#x2F;a&gt;,
Frans wrote &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;TheZoq2&#x2F;tomldoc&quot;&gt;a tool to generate mdbook-documentation for configuration
files&lt;&#x2F;a&gt; from doc-comments in structs. That&#x27;s
a lot of technical words, so it&#x27;s probably best to judy look at &lt;a href=&quot;https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;swim_project_configuration&#x2F;config__Config.html&quot;&gt;the finished
&lt;code&gt;swim.toml&lt;&#x2F;code&gt;-documentation&lt;&#x2F;a&gt;
to understand what it is about. This whole page is generated from the Swim
source code, which means that it should always be up to date with how the
&lt;code&gt;swim.toml&lt;&#x2F;code&gt; is supposed to look.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;various-bug-fixes&quot;&gt;Various bug fixes&lt;a class=&quot;zola-anchor&quot; href=&quot;#various-bug-fixes&quot; aria-label=&quot;Anchor link for: various-bug-fixes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As usual, there are also additional bugfixes. Check out the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;blob&#x2F;v0.5.0&#x2F;CHANGELOG.md&quot;&gt;Swim
changelog&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.5.0&#x2F;CHANGELOG.md&quot;&gt;Spade
changelog&lt;&#x2F;a&gt; for
more information!&lt;&#x2F;p&gt;
&lt;p&gt;This version&#x27;s featured bug-fix is
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;235&quot;&gt;spade!235&lt;&#x2F;a&gt; where it
turned out Vivado parses &lt;code&gt;\new&lt;&#x2F;code&gt; as the keyword &lt;code&gt;new&lt;&#x2F;code&gt;, even though it is written
as an escaped identifier with the leading &lt;code&gt;\&lt;&#x2F;code&gt;. Thanks, Vivado!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.4.0</title>
        <published>2023-08-24T00:00:00+00:00</published>
        <updated>2023-08-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-4-0/"/>
        <id>/v0-4-0/</id>
        
        <content type="html" xml:base="/v0-4-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.4.0&#x2F;CHANGELOG.md#anchor-040&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.4.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.8279534&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;After a small summer break, it&#x27;s time to release Spade 0.4.0. It contains an
important milestone for Spade and several improvements to the surrounding
tooling along with the usual batch of small fixes and changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;write-your-top-module-in-spade-not-verilog&quot;&gt;Write your top module in Spade, not Verilog!&lt;a class=&quot;zola-anchor&quot; href=&quot;#write-your-top-module-in-spade-not-verilog&quot; aria-label=&quot;Anchor link for: write-your-top-module-in-spade-not-verilog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A very exciting milestone is that writing Spade projects no longer requires writing
a Verilog shim! Historically, every Spade project has needed an outermost
Verilog file that takes care of two things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Generating a reset signal.&lt;&#x2F;li&gt;
&lt;li&gt;Naming the signals from the pin file that will be used and passing them to the Spade code.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;From now on, you can do all these things directly in Spade. You can see this in
action in the updated
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim-templates&#x2F;&quot;&gt;swim templates repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;initial-values-for-registers&quot;&gt;Initial values for registers&lt;a class=&quot;zola-anchor&quot; href=&quot;#initial-values-for-registers&quot; aria-label=&quot;Anchor link for: initial-values-for-registers&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One change required for the previously mentioned heading is the possibility to
specify initial values for registers. For example, here is how you would define
a reset signal that is initialized to &lt;code&gt;true&lt;&#x2F;code&gt; and then set to &lt;code&gt;false&lt;&#x2F;code&gt; at the
first clock cycle.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;reg(clk) rst initial (true) = false;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;wal-integration&quot;&gt;WAL integration&lt;a class=&quot;zola-anchor&quot; href=&quot;#wal-integration&quot; aria-label=&quot;Anchor link for: wal-integration&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In the Spring, we did a collaboration with &lt;a href=&quot;https:&#x2F;&#x2F;wal-lang.org&#x2F;&quot;&gt;the WAL
project&lt;&#x2F;a&gt;. WAL is a language for analyzing simulation
waveforms which makes it much easier to get high level information out of your
simulation results.&lt;&#x2F;p&gt;
&lt;p&gt;The result of our joint work is a way to bundle WAL analysis code with Spade
libraries, a set of annotations to effortlessly request the use of the analysis
passes, and integration with Swim to allow running the requested passes in a
single command - &lt;code&gt;swim plugin analysis&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As an example of the capability this adds we can look at a project consisting
of two devices communicating with a shared device via two &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Wishbone_(computer_bus)&quot;&gt;wishbone
buses&lt;&#x2F;a&gt; connected to an
arbiter.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll add the wishbone bus as a dependency to the project, along with the WAL analysis plugin:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;[libraries.wishbone]
git = &amp;quot;https:&amp;#x2F;&amp;#x2F;gitlab.com&amp;#x2F;spade-lang&amp;#x2F;lib&amp;#x2F;fishbone&amp;quot;
branch = &amp;quot;main&amp;quot;

[plugins.wal_analysis]
git = &amp;quot;https:&amp;#x2F;&amp;#x2F;gitlab.com&amp;#x2F;spade-lang&amp;#x2F;wal_analysis&amp;quot;
branch = &amp;quot;main&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we&#x27;ll instantiate two wishbone buses, connect their inputs and outputs to the master and arbiter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity wb_harness(clk: clock, rst: bool)
  -&amp;gt; (int&amp;lt;16&amp;gt;, int&amp;lt;16&amp;gt;)
{
    let (wb1, wb1inv) = port;
    let (wb2, wb2inv) = port;

    #[wal_trace(clk=clk, rst=rst))]
    let wb1 = wb1;
    #[wal_trace(clk=clk, rst=rst))]
    let wb2 = wb2;

    let _ = inst wishbone_arbiter( clk, rst, wb1inv, wb2inv, ...);
    let o1 = inst wishbone_master( clk, rst, wb1, ...);
    let o2 = inst wishbone_master( clk, rst, wb2, ...);

    (o1, o2)
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The two &lt;code&gt;#[wal_trace]&lt;&#x2F;code&gt; attributes are where the magic happens. This tells the
compiler to emit some special signals that the analysis scripts in the
wishbone library should look for.&lt;&#x2F;p&gt;
&lt;p&gt;With this in place, after running &lt;code&gt;swim plugin analysis&lt;&#x2F;code&gt; you will get a whole bunch of high level
information about the two buses:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[ANALYSIS] # wb_harness.wb1
[ANALYSIS]    Nr. transactions : 697
[ANALYSIS]    Nr. reads        : 16
[ANALYSIS]    Avg read latency : 6 clock cycles
[ANALYSIS]    Nr. writes       : 681
[ANALYSIS]    Avg write latency: 9 clock cycles
[ANALYSIS]    Inactive cycles  : 6%
[ANALYSIS] # wb_harness.wb2
[ANALYSIS]    Nr. transactions : 421
[ANALYSIS]    Nr. reads        : 0
[ANALYSIS]    Avg read latency : - clock cycles
[ANALYSIS]    Nr. writes       : 421
[ANALYSIS]    Avg write latency: 12 clock cycles
[ANALYSIS]    Inactive cycles  : 22%
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And you&#x27;ll even get a histogram showing the number of transactions over time
which can give a lot of insight into the behaviour of the system.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;wb_histogram.png&quot; alt=&quot;Histogram showing the number of bus transactions over time&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We will present this work at &lt;a href=&quot;https:&#x2F;&#x2F;fdl-conference.com&#x2F;&quot;&gt;FDL 2023&lt;&#x2F;a&gt;. If you want to learn more and see how it is implemented, you can read &lt;a href=&quot;https:&#x2F;&#x2F;spade-lang.org&#x2F;fdl2023.pdf&quot;&gt;our paper&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;swim-simulation-improvements&quot;&gt;Swim Simulation Improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#swim-simulation-improvements&quot; aria-label=&quot;Anchor link for: swim-simulation-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Swim has also gotten some love recently. It now discovers and runs each test
case in parallel instead of the previous fully sequential test running. Along
with that, it has a new UI for the test running which scales with the size of
your terminal, shows which tests are running, waiting and done, and only prints
the stdout of failed tests. All of this is easier to showcase in a video:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video src=&quot;..&#x2F;swim_par_ui.mp4&quot; height=800px controls&gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;open-vcd-files-in-a-single-click&quot;&gt;Open VCD files in a single click&lt;a class=&quot;zola-anchor&quot; href=&quot;#open-vcd-files-in-a-single-click&quot; aria-label=&quot;Anchor link for: open-vcd-files-in-a-single-click&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In addition, if you run &lt;code&gt;swim setup-links&lt;&#x2F;code&gt; and run a terminal that supports
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Alhadis&#x2F;OSC8-Adoption&#x2F;#user-content-fnref-3-8383ec6fb7dbe9534feab376ed3ba053&quot;&gt;OSC8
hyperlinks&lt;&#x2F;a&gt;,
swim will now print links to open the wave file from an individual test in a
waveform viewer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video src=&quot;..&#x2F;swim_clickable_links.mp4&quot; height=800px controls&gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-new-waveform-viewer&quot;&gt;A new waveform viewer&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-new-waveform-viewer&quot; aria-label=&quot;Anchor link for: a-new-waveform-viewer&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p class=&quot;heading-author&quot;&gt;Frans Skarman&lt;&#x2F;p&gt;
&lt;p&gt;Finally, in that last video you may have noticed an unusual waveform viewer. It
is called surfer and is something I&#x27;ve been working on and off for the past few
months. My goals here are a wave viewer with a nice to use interface
and which is easy to integrate with languages like Spade where signal values
are more than just bits. For Spade, that means it can translate Spade types into
their fields or enum variants, but the translation interface is general, so
other projects should also be able to add similar features.&lt;&#x2F;p&gt;
&lt;p&gt;The interface is snappy and thanks to some work by &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@lcsklmmr@fosstodon.org&quot;&gt;Lucas
Klemmer&lt;&#x2F;a&gt; of WAL fame, it also
has a very nice keyboard centric interface as you can see in the next video.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video src=&quot;..&#x2F;surfer_ui.mp4&quot; width=100% controls&gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The project is still in its early stages, but I have been using it for all my wave surfing needs for the past few weeks. You can follow along at &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;surfer-project&#x2F;surfer&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;surfer-project&#x2F;surfer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.3.0</title>
        <published>2023-06-01T00:00:00+00:00</published>
        <updated>2023-06-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-3-0/"/>
        <id>/v0-3-0/</id>
        
        <content type="html" xml:base="/v0-3-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;v0.3.0&#x2F;CHANGELOG.md&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.3.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.7995330&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Today, we release Spade version 0.3.0. It comes with a few small fixes, and some major new features:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dynamic-pipelining&quot;&gt;Dynamic Pipelining&lt;a class=&quot;zola-anchor&quot; href=&quot;#dynamic-pipelining&quot; aria-label=&quot;Anchor link for: dynamic-pipelining&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The biggest new feature is native support for stalling pipelines. Pipelines can be stalled
by adding a condition for stalling to a stage as shown below:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;    reg[should_stall];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If &lt;code&gt;should_stall&lt;&#x2F;code&gt; is true, the registers corresponding to this &lt;code&gt;reg&lt;&#x2F;code&gt;-statement will hold their
current value, instead of getting a new one. Additionally, all stages &lt;em&gt;before&lt;&#x2F;em&gt; it will also stall,
in order to not throw away any data.&lt;&#x2F;p&gt;
&lt;p&gt;When interacting with the outside world, it is of course important to know if a stage is ready to
receive data, and if data in a stage is valid. This can
be done using &lt;code&gt;stage.valid&lt;&#x2F;code&gt; and &lt;code&gt;stage.ready&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For a full description of the feature, see https:&#x2F;&#x2F;docs.spade-lang.org&#x2F;language_reference&#x2F;dynamic_pipelines.html&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inverted-ports&quot;&gt;Inverted Ports&lt;a class=&quot;zola-anchor&quot; href=&quot;#inverted-ports&quot; aria-label=&quot;Anchor link for: inverted-ports&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It is now possible to create inverted versions of port types, i.e. ports where
&lt;code&gt;mut&lt;&#x2F;code&gt; wires non-&lt;code&gt;mut&lt;&#x2F;code&gt; wires are switched.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful when wanting to create a port somewhere in between two units
communicating with ports, and passing each end to one unit. To create such
a port combination, the new &lt;code&gt;port&lt;&#x2F;code&gt; expression can be used.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, here a port pair connecting a producer and a consumer is created:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;entity top() {
    let (p, p_inv) = port;

    let _ = inst consumer(p);
    let _ = inst producer(p_inv)
}

entity consumer(p: P) -&amp;gt; bool {
    &amp;#x2F;&amp;#x2F; ...
}

entity producer(p: ~P) -&amp;gt; bool {
    &amp;#x2F;&amp;#x2F; ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;experimental-word-length-inference&quot;&gt;Experimental Word Length Inference&lt;a class=&quot;zola-anchor&quot; href=&quot;#experimental-word-length-inference&quot; aria-label=&quot;Anchor link for: experimental-word-length-inference&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The past few months, a master student has been working on adding better
handling of word lengths to Spade, and with 0.3.0, an experimental version of
that feature is included.&lt;&#x2F;p&gt;
&lt;p&gt;The new word length inference can be turned on using &lt;code&gt;--infer-method&lt;&#x2F;code&gt; to the
compiler, or by setting the environment variable &lt;code&gt;SPADE_INFER_METHOD&lt;&#x2F;code&gt;. There
are three word length inference methods available: Interval Arithmetic (&lt;code&gt;IA&lt;&#x2F;code&gt;),
Affine Arithmetic (&lt;code&gt;AA&lt;&#x2F;code&gt;), and a mix of the two: (&lt;code&gt;AAIA&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;With one of these flags enabled, the compiler should infer tighter bounds on word
lengths, and will require far &lt;code&gt;trunc&lt;&#x2F;code&gt; and &lt;code&gt;sext&lt;&#x2F;code&gt; calls. For example, it is now
possible to write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;a + b + c
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;without manual intervention.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-predictable-names&quot;&gt;More predictable names&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-predictable-names&quot; aria-label=&quot;Anchor link for: more-predictable-names&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The last major change in this release is improvements to the names used in the output Verilog.&lt;&#x2F;p&gt;
&lt;p&gt;First, you can now use &lt;code&gt;#[no_mangle]&lt;&#x2F;code&gt; on unit arguments in addition to on the
whole unit, allowing interop with more Verilog modules.&lt;&#x2F;p&gt;
&lt;p&gt;The names of signals being generated have also been improved. They are no
longer globally unique, but this means that the names correspond more closely
to the corresponding name in the source code. In fact, variables with no shadowing
have the exact same name in the generated Verilog as they do in the source code.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.2.0</title>
        <published>2023-04-20T00:00:00+00:00</published>
        <updated>2023-04-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-2-0/"/>
        <id>/v0-2-0/</id>
        
        <content type="html" xml:base="/v0-2-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md#020-2023-03-07&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.2.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.7729341&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;6 weeks have passed, so it is time for another Spade release! A lot of my time
has been spent at or preparing for conferences, so there are no huge changes
this time, but quite a few convenience features.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-initial-content&quot;&gt;Memory Initial Content&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-initial-content&quot; aria-label=&quot;Anchor link for: memory-initial-content&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The standard library has been extended with another function:
&lt;code&gt;std::mem::clocked_memory_init&lt;&#x2F;code&gt;. Like its sibling &lt;code&gt;clocked_memory&lt;&#x2F;code&gt;, it defines
a memory which can be read by &lt;code&gt;read_memory&lt;&#x2F;code&gt;, but this one also allows
specifying initial content of the memory.&lt;&#x2F;p&gt;
&lt;p&gt;This can be used to build ROMs if no write ports are specified, or RAMs with
initial content if the available memories support it.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let rom = clocked_memory_init$(
    clk,
    writes: [],
    initial: [1,2,3,4]
);
reg(clk) rom_out = read_mem(rom, addr);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;more-arithmetic-ops&quot;&gt;More arithmetic ops&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-arithmetic-ops&quot; aria-label=&quot;Anchor link for: more-arithmetic-ops&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This release adds &lt;code&gt;min&lt;&#x2F;code&gt;, &lt;code&gt;max&lt;&#x2F;code&gt; and &lt;code&gt;order&lt;&#x2F;code&gt; functions to the standard library
under the &lt;code&gt;std::ops&lt;&#x2F;code&gt; namespace, and the &lt;code&gt;!=&lt;&#x2F;code&gt; operator to the core language.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hacky-literals&quot;&gt;(Hacky) literals&lt;a class=&quot;zola-anchor&quot; href=&quot;#hacky-literals&quot; aria-label=&quot;Anchor link for: hacky-literals&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An issue that has been plaguing the language for a while is a lack of support for large or negative integer literals. For example, the following code failed to compile&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let x: int&amp;lt;8&amp;gt; = -128
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is clearly not intentional, and has been fixed.&lt;&#x2F;p&gt;
&lt;p&gt;In a related issue, the following code also failed to compile&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let x: int&amp;lt;8&amp;gt; = 128
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this &lt;em&gt;is&lt;&#x2F;em&gt; incorrect code since &lt;code&gt;128&lt;&#x2F;code&gt; does not fit in an 8-bit integer, Spade does not currently have an unsigned type and some features such as array indices treat signed integers as unsigned. This means that code like&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let array = [1,2,3,4];
let value = array[3];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;fails to compile. Until Spade gets a proper unsigned type, you can now suffix integer literals with &lt;code&gt;u&lt;&#x2F;code&gt;, making the following code work&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let array = [1,2,3,4];
let value = array[3u];
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is worth pointing out that this is only an integer literal representation change, so using u for anything but index-like operations will fail. For example,&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;spade&quot; class=&quot;language-spade &quot;&gt;&lt;code class=&quot;language-spade&quot; data-lang=&quot;spade&quot;&gt;let x: int&amp;lt;8&amp;gt; = 1;
let y: int&amp;lt;8&amp;gt; = 150u;
x &amp;gt; y
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;will evaluate to &lt;code&gt;false&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;standard-library-in-stand-alone-projects&quot;&gt;Standard Library in Stand-alone Projects&lt;a class=&quot;zola-anchor&quot; href=&quot;#standard-library-in-stand-alone-projects&quot; aria-label=&quot;Anchor link for: standard-library-in-stand-alone-projects&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Previously, the standard library was included by &lt;code&gt;swim&lt;&#x2F;code&gt; when compiling
projects. But this meant that one had to manually include the standard library
when running the spade compiler in stand-alone mode without swim.&lt;&#x2F;p&gt;
&lt;p&gt;As of this version, &lt;code&gt;spade&lt;&#x2F;code&gt; now includes the standard library and prelude
itself, allowing its use without swim.&lt;&#x2F;p&gt;
&lt;p&gt;Note: If you use an old &lt;code&gt;swim&lt;&#x2F;code&gt; with a new &lt;code&gt;spade&lt;&#x2F;code&gt;, or vice versa, you will see
errors when building swim projects. Make sure to update both or neither.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;error-message-improvements&quot;&gt;Error message improvements&lt;a class=&quot;zola-anchor&quot; href=&quot;#error-message-improvements&quot; aria-label=&quot;Anchor link for: error-message-improvements&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After 4 years of resistance, my advisor has finally written some Rust! Among
other things, he made numerous improvements to the grammar and clarity of the
error messages coming out of the compiler.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;publications&quot;&gt;Publications&lt;a class=&quot;zola-anchor&quot; href=&quot;#publications&quot; aria-label=&quot;Anchor link for: publications&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I managed to visit 2 workshops in the last month:
&lt;a href=&quot;https:&#x2F;&#x2F;capra.cs.cornell.edu&#x2F;latte23&#x2F;&quot;&gt;Latte&#x27;23&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;osda.ws&#x2F;&quot;&gt;OSDA&lt;&#x2F;a&gt;.
If you want to see the papers or presentations, check the publication list at
https:&#x2F;&#x2F;spade-lang.org&#x2F;#publications&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spade 0.1.0</title>
        <published>2023-03-09T00:00:00+00:00</published>
        <updated>2023-03-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/v0-1-0/"/>
        <id>/v0-1-0/</id>
        
        <content type="html" xml:base="/v0-1-0/">&lt;div id=&quot;release-links&quot;&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md#010-2023-03-07&quot;&gt;Associated changelog&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;tree&#x2F;v0.1.0&quot;&gt;Git&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.5281&#x2F;zenodo.7713115&quot;&gt;DOI&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Before this point, Spade has only had commit IDs to differentiate versions, but
for various reasons discussed in
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;161&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;161&lt;&#x2F;a&gt; having numbered
releases is useful.&lt;&#x2F;p&gt;
&lt;p&gt;As with so many other aspects of this project, inspiration has been taken from
Rust&#x27;s release and versioning scheme. New Spade versions will be published
every six weeks on a fixed schedule. Features and fixes that are on &lt;code&gt;master&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; are
included, everything else is not. Since the compiler and language are still in
an unstable development stage, all versions will be &lt;code&gt;0.x&lt;&#x2F;code&gt;, and breaking changes
will be the norm for now.&lt;&#x2F;p&gt;
&lt;p&gt;As a user, it will still be advised to always use the &lt;code&gt;master&lt;&#x2F;code&gt; branch. Releases
are more intended to give something to reference, especially on
&lt;a href=&quot;https:&#x2F;&#x2F;zenodo.org&quot;&gt;https:&#x2F;&#x2F;zenodo.org&lt;&#x2F;a&gt;, and to serve as an opportunity to
summarize what has changed in the past few weeks and make some announcements.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all for today! In 6 weeks, when 0.2 is released, the blog post will
hopefully have more interesting content, highlighting some new features.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;We should probably rename it to &lt;code&gt;main&lt;&#x2F;code&gt; at some point 🤔&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ISY Summer of Code 2022</title>
        <published>2022-08-16T00:00:00+00:00</published>
        <updated>2022-08-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/summer-of-code-2022/"/>
        <id>/summer-of-code-2022/</id>
        
        <content type="html" xml:base="/summer-of-code-2022/">&lt;p&gt;This summer I&#x27;ve had the opportunity to work in a Summer of Code organized by
&lt;a href=&quot;https:&#x2F;&#x2F;www.isy.liu.se&quot;&gt;the department of Electrical Engineering (ISY)&lt;&#x2F;a&gt; at
&lt;a href=&quot;https:&#x2F;&#x2F;liu.se&quot;&gt;Linköping University&lt;&#x2F;a&gt;. This post will summarize a few of the
changes I worked on and had particularly fun with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;a class=&quot;zola-anchor&quot; href=&quot;#background&quot; aria-label=&quot;Anchor link for: background&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I was selected to work half-time for two
months on Spade, but I had a lot of freedom in what exactly I did.
A complete listing of all merged merge requests (at least in the &lt;code&gt;spade-lang&lt;&#x2F;code&gt;
Gitlab organization, so not counting e.g. &lt;code&gt;prr&lt;&#x2F;code&gt;) can be found &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;groups&#x2F;spade-lang&#x2F;-&#x2F;merge_requests?author_username=sornas&amp;amp;page=2&amp;amp;scope=all&amp;amp;sort=closed_at&amp;amp;state=all&quot;&gt;on
Gitlab&lt;&#x2F;a&gt;
(from spade!75 and onwards). Apart from that I also helped review some merge
requests (also &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;groups&#x2F;spade-lang&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;state=merged&amp;amp;reviewer_username=sornas&quot;&gt;on
Gitlab&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;You can read more about Spade on the &lt;a href=&quot;https:&#x2F;&#x2F;spade-lang.org&quot;&gt;main Spade
website&lt;&#x2F;a&gt;. Spade, as well as most of the tooling, is
implemented in &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt;, so some of the content here will
also touch on Rust.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;about-me&quot;&gt;About me&lt;a class=&quot;zola-anchor&quot; href=&quot;#about-me&quot; aria-label=&quot;Anchor link for: about-me&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Before I started university, I had not done any hardware programming (or
hardware anything really, apart from building my desktop computer) at all.
University introduced me first to digital electronics using physical wires and
later to VHDL and hardware programming.&lt;&#x2F;p&gt;
&lt;p&gt;I had already been contributing to Spade for a couple of months, and I had used
it twice in game jam projects. (Not really the intended use case but it worked
out alright.) Still, I wouldn&#x27;t call myself a expert in hardware by any means.
What&#x27;s nice about a hardware &lt;em&gt;compiler&lt;&#x2F;em&gt; is that I usually don&#x27;t have to worry
that much about the actual hardware going on since the compiler hides most of
the weirdness behind abstractions. I could for example work on the parser without
worrying at all about Verilog.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tracing-in-the-compiler&quot;&gt;Tracing in the compiler&lt;a class=&quot;zola-anchor&quot; href=&quot;#tracing-in-the-compiler&quot; aria-label=&quot;Anchor link for: tracing-in-the-compiler&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As a first task, I wanted to get a better feel for the Spade compiler structure.
We had specialized tracing (logging) for the parser and typechecker, but I
wanted something more like &lt;a href=&quot;https:&#x2F;&#x2F;rustc-dev-guide.rust-lang.org&#x2F;tracing.html&quot;&gt;the tracing found in the Rust
compiler&lt;&#x2F;a&gt;. It turns out Rust
uses public libraries (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tracing&quot;&gt;&lt;code&gt;tracing&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
&quot;scoped, structured logging and diagnostics&quot;, and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;davidbarsky&#x2F;tracing-tree&quot;&gt;&lt;code&gt;tracing-tree&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for the output) so
we could add them right away.&lt;&#x2F;p&gt;
&lt;p&gt;Adding &lt;code&gt;tracing&lt;&#x2F;code&gt; and &lt;code&gt;tracing-tree&lt;&#x2F;code&gt; was first done in
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;75&quot;&gt;spade!75&lt;&#x2F;a&gt;. We opted to
not add the tracing events themselves all at once since the compiler is too
large for that. Instead, we added them as needed when we worked on fixing other
bugs.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;p&gt;&lt;img src=&quot;tracing-ast-lowering.png&quot; alt=&quot;Example of tracing output for the AST
lowering stage.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example of tracing output for the AST lowering stage.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;We still have two old systems that can annotate functions and show a tree-like
view of the program flow (for parsing and type checking) which are left for now.
At some point they could probably be incorporated into tracing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;multipart-suggestions&quot;&gt;Multipart suggestions&lt;a class=&quot;zola-anchor&quot; href=&quot;#multipart-suggestions&quot; aria-label=&quot;Anchor link for: multipart-suggestions&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One important goal of the Spade compiler is to be friendly to humans. Here&#x27;s an
example error message from a small fix I did in
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;spade&#x2F;-&#x2F;merge_requests&#x2F;94&#x2F;diffs&quot;&gt;spade!94&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;text&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;error: Multiple definitions of b
  ┌─ testinput:1:8
  │
1 │ entity b() -&amp;gt; bool {
  │        ^ Multiple items named b
  ·
5 │ use x::b;
  │     ---- Previous definition here
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;A Spade compiler error example&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;This can be compared with the output for the equivalent error (two entities
with the same name) when compiling some VHDL in one of my university courses,
using a to-be-unnamed proprietary compiler.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;text&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;=========================================================================
*                          HDL Parsing                                  *
=========================================================================
Parsing VHDL file &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; into library work
Parsing entity &amp;lt;lab&amp;gt;.
Parsing entity &amp;lt;lab&amp;gt;.
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 13: &amp;lt;std_logic&amp;gt; is not declared.
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 14: &amp;lt;unsigned&amp;gt; is not declared.
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 15: &amp;lt;unsigned&amp;gt; is not declared.
ERROR:HDLCompiler:854 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 12: Unit &amp;lt;lab&amp;gt; ignored due to previous errors.
Parsing architecture &amp;lt;Behavioral&amp;gt; of entity &amp;lt;lab&amp;gt;.
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 51: &amp;lt;rx&amp;gt; is not declared.
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 47: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 46: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 69: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 68: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 102: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 101: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 130: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 129: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 148: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 147: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 171: &amp;lt;rst&amp;gt; is not declared.
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 170: Type error near clk ; current type unsigned; expected type std_ulogic
ERROR:HDLCompiler:1728 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 192: Type error near clk ; current type unsigned; expected type std_logic
ERROR:HDLCompiler:69 - &amp;quot;&amp;#x2F;home&amp;#x2F;user&amp;#x2F;....&amp;#x2F;lab.vhd&amp;quot; Line 192: &amp;lt;rst&amp;gt; is not declared.
Sorry, too many errors..
--&amp;gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;A VHDL compiler error example. Too many errors indeed.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;We use a library called &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;codespan&quot;&gt;&lt;code&gt;codespan&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which renders
our source code annotated with labels that can point to different spans, as seen
above. Before the Summer of Code we had already implemented support for
suggestions in which we attach suggestions to error messages. These suggestions
consist of a span to remove and a text to replace it with. What&#x27;s nice is that
all combinations of add and remove (only addition, only removal, and
replacement) could be chosen by leaving either the span or the text empty.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;text&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;error: Expected array size
  ┌─ testinput:2:12
  │
2 │     let _: [bool] = [true, false];
  │            ^^^^^^ This array type
  │
  = Array types need a specified size
  = Insert a size here
  │
2 │     let _: [bool; N] = [true, false];
  │                 +++
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;An example of a suggestion with a single replacement. In this
case, the replacement span is the empty span between &lt;code&gt;l&lt;&#x2F;code&gt; and &lt;code&gt;]&lt;&#x2F;code&gt;, and the
replacement text is &lt;code&gt;; N&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;codespan&#x2F;-&#x2F;merge_requests&#x2F;2&quot;&gt;codespan!2&lt;&#x2F;a&gt;, I
then added support for suggestions that consist of multiple parts.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;text&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;error: Unexpected `(`, expected `{`, `,`, or `}`
  ┌─ main.spade:2:6
  │
2 │     B(n: int&amp;lt;4&amp;gt;),
  │      ^ expected `{`, `,`, or `}`
  │
  = Use `{` if you want to add items to this enum variant
  │
2 │     B{n: int&amp;lt;4&amp;gt;},
  │      ~         ~
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;An example of a suggestion with multiple replacements.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;There is still work left to do. For starters, suggestions currently need to be
on the same line to be rendered.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;text&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;error: Unexpected `(`, expected `{`, `,`, or `}`
  ┌─ main.spade:2:6
  │
2 │     B(
  │      ^ expected `{`, `,`, or `}`
  │
  = (Note: skipped showing 1 multi-line suggestion)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;An example of a suggestion over multiple lines that is skipped.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;At some point we also probably want to upstream this into the original codespan
repository.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;board-presets-in-swim-configurations&quot;&gt;Board presets in Swim configurations&lt;a class=&quot;zola-anchor&quot; href=&quot;#board-presets-in-swim-configurations&quot; aria-label=&quot;Anchor link for: board-presets-in-swim-configurations&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In addition to Spade, we also have a build tool called Swim. It handles some of
the work in getting your Spade code programmed onto an FPGA. It does this through
a series of steps.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build&lt;&#x2F;li&gt;
&lt;li&gt;Synthesis&lt;&#x2F;li&gt;
&lt;li&gt;Place and route&lt;&#x2F;li&gt;
&lt;li&gt;Packing&lt;&#x2F;li&gt;
&lt;li&gt;Uploading&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Since FPGA models have unique hardware characteristics, we need to specify
different values and programs for different boards in a Swim configuration file. Here&#x27;s
how it looks for the &lt;a href=&quot;https:&#x2F;&#x2F;nandland.com&#x2F;the-go-board&#x2F;&quot;&gt;Go Board&lt;&#x2F;a&gt; I have at
home.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;compiler_dir = &amp;quot;spade&amp;quot;

[synthesis]
top = &amp;quot;top&amp;quot;
extra_verilog = [&amp;quot;src&amp;#x2F;top.v&amp;quot;]
command = &amp;quot;synth_ice40&amp;quot;

[pnr]
architecture = &amp;quot;ice40&amp;quot;
device = &amp;quot;iCE40HX1K&amp;quot;
pin_file = &amp;quot;go.pcf&amp;quot;
package = &amp;quot;vq100&amp;quot;

[packing]
tool = &amp;quot;icepack&amp;quot;

[upload]
tool = &amp;quot;iceprog&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example Swim.toml for the Go Board FPGA.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Compare this to the configuration required for the ECPIX-5. Notably, &lt;code&gt;[pnr]&lt;&#x2F;code&gt;,
&lt;code&gt;[upload]&lt;&#x2F;code&gt; and &lt;code&gt;[packing]&lt;&#x2F;code&gt; contains completely different values.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;compiler_dir = &amp;quot;spade&amp;quot;

[synthesis]
top = &amp;quot;top&amp;quot;
extra_verilog = [ &amp;quot;src&amp;#x2F;top.v&amp;quot; ]
command = &amp;quot;synth_ecp5&amp;quot;

[pnr]
architecture = &amp;quot;ecp5&amp;quot;
device = &amp;quot;LFE5UM5G-45F&amp;quot;
pin_file = &amp;quot;ecpix5.lpf&amp;quot;
package = &amp;quot;CABGA554&amp;quot;

[upload]
tool = &amp;quot;openocd&amp;quot;
config_file = &amp;quot;openocd-ecpix5.cfg&amp;quot;

[packing]
tool = &amp;quot;ecppack&amp;quot;
idcode = &amp;quot;0x81112043&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example Swim.toml for the ECPIX-5 FPGA.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Now, most of this configuration will be the same for each Go Board, or ECPIX-5,
or &lt;em&gt;insert your FPGA of choice here&lt;&#x2F;em&gt;. So in
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;merge_requests&#x2F;26&quot;&gt;swim!26&lt;&#x2F;a&gt; I added
support for a &lt;code&gt;[board]&lt;&#x2F;code&gt;-directive in the configuration file. You could then instead of the
above configurations write:&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;compiler_dir = &amp;quot;spade&amp;quot;

[synthesis]
top = &amp;quot;top&amp;quot;
extra_verilog = [&amp;quot;src&amp;#x2F;top.v&amp;quot;]
command = &amp;quot;synth_ice40&amp;quot;

[board]
name = &amp;quot;go-board&amp;quot;
pcf = &amp;quot;go.pcf&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example Swim.toml for the Go Board FPGA, with &lt;code&gt;[board]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;compiler_dir = &amp;quot;spade&amp;quot;

[synthesis]
top = &amp;quot;top&amp;quot;
extra_verilog = [ &amp;quot;src&amp;#x2F;top.v&amp;quot; ]
command = &amp;quot;synth_ecp5&amp;quot;

[board]
name = &amp;quot;ecpix-5&amp;quot;
pin_file = &amp;quot;ecpix5.lpf&amp;quot;
config_file = &amp;quot;openocd-ecpix5.cfg&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example Swim.toml for the ECPIX-5 FPGA, with &lt;code&gt;[board]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The fields &lt;code&gt;pin_file&lt;&#x2F;code&gt; and &lt;code&gt;pcf&lt;&#x2F;code&gt; are used to map pins on the board to input and output
signals in the code, which means it is not the same from project to project and
therefore still specified.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lock-file-for-pinning-dependencies-in-swim&quot;&gt;Lock file for &quot;pinning&quot; dependencies in Swim&lt;a class=&quot;zola-anchor&quot; href=&quot;#lock-file-for-pinning-dependencies-in-swim&quot; aria-label=&quot;Anchor link for: lock-file-for-pinning-dependencies-in-swim&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before the Summer of Code, we had already added support for dependencies in Swim.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;compiler_dir = &amp;quot;spade&amp;quot;

[libraries.my-dependency]
git = &amp;quot;https:&amp;#x2F;&amp;#x2F;example.com&amp;#x2F;git&amp;#x2F;repository.git
branch = &amp;quot;main&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Example dependency in a Swim configuration file&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;When you run &lt;code&gt;swim build&lt;&#x2F;code&gt; for the first time, Swim will fetch a copy of the
repository, checkout the specified branch and build it as a separate module.
After the first build, Swim won&#x27;t re-fetch the repository unless you run &lt;code&gt;swim update&lt;&#x2F;code&gt; (so you don&#x27;t have to have an internet connection ever time you build).
But if you later build this project on another computer, what happens if the
branch has been updated in the repository? To ensure the project uses the same
dependencies, we create a file &lt;code&gt;swim.lock&lt;&#x2F;code&gt; containing the hash of the commit
which takes priority over the specified reference in &lt;code&gt;swim.toml&lt;&#x2F;code&gt;. (It&#x27;s a bit
hard to exemplify but you might be aware of lock files from other build tools
like Cargo, npm and Nix (flakes).)&lt;&#x2F;p&gt;
&lt;p&gt;The hardest part about this change wasn&#x27;t the actual change, but testing it.
What good is a complex feature like this if you can&#x27;t trust that it even works
from the start? Most of Swim relied on relative paths and changing the active
directory (like &lt;code&gt;cd&lt;&#x2F;code&gt;) which in combination with tests running in parallel made
the test suite more racy than an F1 GP. The solution was to not have
relative paths and tests that all change the active directory, by instead
making all paths absolute paths instead.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s more, the logging output was
&lt;em&gt;not&lt;&#x2F;em&gt; captured by the test suite, so it all went to the same terminal, making it
borderline impossible to debug where stuff went wrong. (Usually, Cargo collects
output from tests and only prints it per test for failed tests. The solution was
to wrap the log call in a &lt;code&gt;println&lt;&#x2F;code&gt; with &lt;code&gt;fern::Output::call(|record| println!(&quot;{}&quot;, record.args()));&lt;&#x2F;code&gt;.) My misery can
be found in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;swim&#x2F;-&#x2F;merge_requests&#x2F;37&quot;&gt;swim!37&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This also came during the worst of the summer heat, and I got to experience
first-hand the loss of productivity when it&#x27;s 30+°C degrees outside and somewhere
around 25-28 °C inside for an entire week.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gitlab-ci&quot;&gt;Gitlab CI&lt;a class=&quot;zola-anchor&quot; href=&quot;#gitlab-ci&quot; aria-label=&quot;Anchor link for: gitlab-ci&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Speaking of tests, I found myself debugging CI pipelines at multiple points for
different projects. I&#x27;ve created new CI configurations for our mdbook, this
blog and our codespan fork. We also have a tool called &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;trawler&quot;&gt;Trawler&lt;&#x2F;a&gt; that tries to build a list of
projects to ensure we don&#x27;t accidentally break &quot;real&quot; code (and as an incentive
to keep a couple of external projects up-to-date), so for that I wrote a
JUnit-generator since Gitlab understands and renders JUnit-reports.&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;img src=&quot;junit.png&quot; alt=&quot;A JUnit report on Gitlab.&quot; &#x2F;&gt;&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;A Trawler JUnit report on Gitlab.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;this-blog&quot;&gt;This blog&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-blog&quot; aria-label=&quot;Anchor link for: this-blog&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Towards the end of the summer we felt like it would be nice to write a bit about
what I had done and how everything had went. Thus, this blog. I started with a
scrapped personal website and modified the look to be more like the main
&lt;a href=&quot;https:&#x2F;&#x2F;spade-lang.org&quot;&gt;spade-lang.org&lt;&#x2F;a&gt;. You&#x27;re browsing the result right now
:).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been getting used to Zola more and more, but some things are still a bit
difficult to do (and more importantly, not really documented). I have collected
&lt;a href=&quot;&#x2F;summer-of-code-2022&#x2F;#appendix-a-zola-workaround-example&quot;&gt;an example in the appendix&lt;&#x2F;a&gt;. Still, right
when I want to give up and make an ugly hack in the Zola source, a solution
usually presents itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gitlab-support-for-prr-for-offline-code-reviews&quot;&gt;Gitlab support for &lt;code&gt;prr&lt;&#x2F;code&gt; for offline code reviews&lt;a class=&quot;zola-anchor&quot; href=&quot;#gitlab-support-for-prr-for-offline-code-reviews&quot; aria-label=&quot;Anchor link for: gitlab-support-for-prr-for-offline-code-reviews&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;During development I found a tool called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;danobi&#x2F;prr&quot;&gt;&lt;code&gt;prr&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
From the repository:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;prr&lt;&#x2F;code&gt; is a tool that brings mailing list style code reviews to Github PRs.
This means offline reviews and inline comments, more or less.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I had found myself on quite a few train rides without internet access, so this
sounded like something I could use. I had gotten permission to work a bit on
unrelated tooling if it was to help me work on Spade, and since we use
Gitlab instead of Github I got to work on adding Gitlab support. This didn&#x27;t
take too long (a day or two) since I had already used the
&lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;gitlab&quot;&gt;&lt;code&gt;gitlab&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;-crate for doing API calls to Gitlab
before.&lt;&#x2F;p&gt;
&lt;p&gt;The resulting fork can be found &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sornas&#x2F;prr&quot;&gt;on Github&lt;&#x2F;a&gt;. It
doesn&#x27;t support spanned comments due to &lt;a href=&quot;&#x2F;summer-of-code-2022&#x2F;#appendix-b-spanned-comments-using-the-gitlab-api&quot;&gt;some funky API documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appendix-a-zola-workaround-example&quot;&gt;Appendix A: Zola workaround example&lt;a class=&quot;zola-anchor&quot; href=&quot;#appendix-a-zola-workaround-example&quot; aria-label=&quot;Anchor link for: appendix-a-zola-workaround-example&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In Zola, the special variables &lt;code&gt;page&lt;&#x2F;code&gt; and &lt;code&gt;section&lt;&#x2F;code&gt; aren&#x27;t inherited when using
&lt;code&gt;include &quot;something.html&quot;&lt;&#x2F;code&gt; (I think). So here&#x27;s a weird solution to work around
that:&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;md&quot; class=&quot;language-md &quot;&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;We want the header link (top left) to link to

1) If we&amp;#x27;re rendering a post, the containing section.
2) If we&amp;#x27;re rendering a section, this section.
3) If we&amp;#x27;re rendering the homepage, the homepage.

[[ templates&amp;#x2F;base.html ]]

{% if page %}
  {% set this = page %}
  {% set page = page %}
{% elif section %}
  {% set this = section %}
  {% set section = section %}
{% endif %}

[[ templates&amp;#x2F;partials&amp;#x2F;nav.html (included from
   templates&amp;#x2F;base.html) ]]
{% if page %}
  {% set section = get_section(path=page.ancestors | last) %}
  &amp;lt;a href={{ section.permalink }}&amp;gt;
    {{ section.title | default(value=config.title) }}
  &amp;lt;&amp;#x2F;a&amp;gt;
{% elif section and section.title %}
  {{ section.title }}
{% else %}
  {{ config.title }}
{% endif %}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;appendix-b-spanned-comments-using-the-gitlab-api&quot;&gt;Appendix B: Spanned comments using the Gitlab API&lt;a class=&quot;zola-anchor&quot; href=&quot;#appendix-b-spanned-comments-using-the-gitlab-api&quot; aria-label=&quot;Anchor link for: appendix-b-spanned-comments-using-the-gitlab-api&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While working on spanned comments (comments that target a line range instead of
a single line) I had a &quot;&quot;&quot;fun&quot;&quot;&quot; problem with the API documentation. There is a
header in the documentation called &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;15.2&#x2F;ee&#x2F;api&#x2F;discussions.html#create-new-merge-request-thread&quot;&gt;Create a new merge request
thread&lt;&#x2F;a&gt;
which shows us how to create a thread pointing to a single line. Great! Let&#x27;s
use it. We use the already existing code to take a review file and parse it into
a list of &lt;code&gt;InlineComment&lt;&#x2F;code&gt;. Then, we use an iterator and &lt;code&gt;map&lt;&#x2F;code&gt; (transform, sort
of) each inline comment into its own thread.&lt;&#x2F;p&gt;
&lt;p&gt;(This code is simplified to make a point. Check the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sornas&#x2F;prr&#x2F;blob&#x2F;46167d9c7111ad7c3a5da751e2b65acbe7974e39&#x2F;src&#x2F;api&#x2F;gitlab.rs#L150&quot;&gt;original&lt;&#x2F;a&gt;
if you&#x27;re interested.)&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let discussions = inline_comments
  .iter()
  .map(|c| {
    let mut position = Position::new();
    match c.line {
      &amp;#x2F;&amp;#x2F; Since we&amp;#x27;re commenting on a diff, all of these
      &amp;#x2F;&amp;#x2F; contain two values: the line number the comment
      &amp;#x2F;&amp;#x2F; is at before and after the diff is applied.
      LineLocation::Removed(old_line, _) =&amp;gt; {
        position.old_line(old_line);
      }
      LineLocation::Added(_, new_line) =&amp;gt; {
        position.new_line(new_line);
      }
      &amp;#x2F;&amp;#x2F; Fun fact: having both old_line and new_line here
      &amp;#x2F;&amp;#x2F; is mandated by the API.
      LineLocation::Changed(old_line, new_line) =&amp;gt; {
        position.old_line(old_line).new_line(new_line);
      }
    }
    CreateMergeRequestDiscussion::new()
      .body(&amp;amp;c.comment)
      .position(position)
  });
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;Adding comments on single lines on Gitlab (simplified).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;If you&#x27;re not used to builders and&#x2F;or Rust this might look a bit odd but the
point is that each &lt;code&gt;InlineComment&lt;&#x2F;code&gt; is turned into a
&lt;code&gt;CreateMergeRequestDiscussion&lt;&#x2F;code&gt; with a body and position. Both of those are
mapped from the &lt;code&gt;InlineComment&lt;&#x2F;code&gt; without much trouble.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try to apply this to spanned comments. The API (&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;15.2&#x2F;ee&#x2F;api&#x2F;discussions.html#parameters-for-multiline-comments&quot;&gt;Parameters for multiline
comments&lt;&#x2F;a&gt;)
tells us that we need a &lt;em&gt;line code&lt;&#x2F;em&gt; and &lt;em&gt;type&lt;&#x2F;em&gt; for the start and end of each
comment. The line code is documented right below this header and combines the
hash of the file we&#x27;re commenting on, the line number before the change and the
line number after the change. This is information we have, so it should be fine.
The API also wants a &quot;type&quot; &lt;em&gt;and I quote&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Attribute: &lt;code&gt;position[line_range][start][type]&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Type: string&lt;&#x2F;li&gt;
&lt;li&gt;Required: yes&lt;&#x2F;li&gt;
&lt;li&gt;Description: &quot;Use &lt;code&gt;new&lt;&#x2F;code&gt; for lines added by this commit, otherwise &lt;code&gt;old&lt;&#x2F;code&gt;&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Since our chosen API wrapper is well made it mirrors this. Well, I tried
implementing it, but it didn&#x27;t work. It&#x27;s a bit difficult to debug since the
comments still show up as normal single line comments. I did however compare the
request that is sent (top) with the one sent when using Gitlabs own web UI
(bottom):&lt;&#x2F;p&gt;
&lt;figure class=&quot;px-8&quot;&gt;
  &lt;div&gt;&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;line_range: Some(
  LineRange {
    start: LineCode {
      line_code: &amp;quot;1b[...]b7_12_10&amp;quot;,
      type_: Old,
    },
    end: LineCode {
      line_code: &amp;quot;1b[...]b7_15_14&amp;quot;,
      type_: Old,
    },
  }
)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&amp;quot;line_range&amp;quot;:{
  &amp;quot;start&amp;quot;:{
    &amp;quot;line_code&amp;quot;:&amp;quot;1b[...]b7_12_10&amp;quot;,
    &amp;quot;type&amp;quot;:null,
    &amp;quot;old_line&amp;quot;:12,
    &amp;quot;new_line&amp;quot;:10
  },
  &amp;quot;end&amp;quot;:{
    &amp;quot;line_code&amp;quot;:&amp;quot;1b[...]b7_15_14&amp;quot;,
    &amp;quot;type&amp;quot;:null,
    &amp;quot;old_line&amp;quot;:15,
    &amp;quot;new_line&amp;quot;:14
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;-mt-5&quot;&gt;&lt;p&gt;What should be the same comment. Comparison between my
prr-fork (top) and the
Gitlab web-UI (bottom).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Interestingly, we see that Gitlab:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Sets &lt;code&gt;type&lt;&#x2F;code&gt; to &lt;code&gt;null&lt;&#x2F;code&gt; even though it should be a string that is either
&lt;code&gt;&quot;old&quot;&lt;&#x2F;code&gt; or &lt;code&gt;&quot;new&quot;&lt;&#x2F;code&gt; according to the documentation.&lt;&#x2F;li&gt;
&lt;li&gt;Sets &lt;code&gt;old_line&lt;&#x2F;code&gt; and &lt;code&gt;new_line&lt;&#x2F;code&gt; on &lt;code&gt;line_range[start]&lt;&#x2F;code&gt; and &lt;code&gt;line_range[end]&lt;&#x2F;code&gt;,
fields that don&#x27;t exist in the documentation. They&#x27;re also duplicated from
information that is already present in the line code.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Maybe there is a way to &quot;bypass&quot; the type system and modify the API calls with
custom fields? In any case, I&#x27;ve given up on spanned comments for now since
single line comments look almost exactly the same. If you have any ideas, feel
free to drop by the forked repo at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sornas&#x2F;prr&quot;&gt;sornas&#x2F;prr
(github)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hello World</title>
        <published>2022-08-15T00:00:00+00:00</published>
        <updated>2022-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="/hello/"/>
        <id>/hello/</id>
        
        <content type="html" xml:base="/hello/">&lt;p&gt;This is the first post on this blog. We hope you will enjoy the articles to
come.&lt;&#x2F;p&gt;
&lt;p&gt;The blog (at least in its first form) uses the static site generator
&lt;a href=&quot;https:&#x2F;&#x2F;getzola.org&quot;&gt;Zola&lt;&#x2F;a&gt;. The base theme is called
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;not-matthias&#x2F;apollo&quot;&gt;Apollo&lt;&#x2F;a&gt;, but at this point it has been
modified so much that the only parts that can be recognized are the link
highlights and the &lt;code&gt;#&lt;&#x2F;code&gt; header prefix. If you&#x27;re interested, the source is
available on &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;spade-lang&#x2F;blog.spade-lang.org&quot;&gt;Gitlab&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
