diff options
| author | Schuyler Eldridge | 2022-03-04 16:07:54 -0500 |
|---|---|---|
| committer | GitHub | 2022-03-04 16:07:54 -0500 |
| commit | a372c20cc1a52881356603274512bd35e7149a55 (patch) | |
| tree | 1681eea0384928afaf27729f515c977d173398bb | |
| parent | 95cae3cd0eb9ac72eb6373207dbf9f09fb1c7086 (diff) | |
[spec] Remove FIRRTL Specification (#2488)
This removes the FIRRTL specification as this now lives in its own
repository:
https://github.com/chipsalliance/firrtl-spec
All git history (excluding binary updates to spec.pdf) have been
migrated to the new repository.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | spec/Makefile | 10 | ||||
| -rw-r--r-- | spec/ebnf.xml | 41 | ||||
| -rw-r--r-- | spec/firrtl.xml | 174 | ||||
| -rw-r--r-- | spec/future-release.txt | 7 | ||||
| -rw-r--r-- | spec/leftovers.txt | 309 | ||||
| -rw-r--r-- | spec/spec-template.tex | 560 | ||||
| -rw-r--r-- | spec/spec.md | 2722 | ||||
| -rw-r--r-- | spec/spec.pdf | bin | 361333 -> 0 bytes |
9 files changed, 1 insertions, 3824 deletions
@@ -16,7 +16,7 @@ A Firrtl compiler is constructed by chaining together these transformations, then writing the final circuit to a file. - For a detailed description of Firrtl's intermediate representation, see the document "Specification of the Firrtl Language" located in [spec/spec.pdf](https://github.com/freechipsproject/firrtl/blob/master/spec/spec.pdf). + For a detailed description of Firrtl's intermediate representation, see [chipsalliance/firrtl-spec/blob/spec.md](https://github.com/chipsalliance/firrtl-spec/blob/main/spec.md). #### Wiki Pages and Tutorials diff --git a/spec/Makefile b/spec/Makefile deleted file mode 100644 index 3c762cd1..00000000 --- a/spec/Makefile +++ /dev/null @@ -1,10 +0,0 @@ - -SPEC = spec.pdf - -all: $(SPEC) - -spec.pdf: spec.md firrtl.xml spec-template.tex firrtl.xml ebnf.xml - pandoc $< --template spec-template.tex --syntax-definition firrtl.xml --syntax-definition ebnf.xml -r markdown+table_captions+inline_code_attributes+gfm_auto_identifiers --filter pandoc-crossref -o $@ - -clean: - rm -f *.aux *.log *.out *.toc *.pdf diff --git a/spec/ebnf.xml b/spec/ebnf.xml deleted file mode 100644 index 772335f0..00000000 --- a/spec/ebnf.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<language name="EBNF" version="1" kateversion="2.4" section="Sources" extensions="*.ebnf"> - <highlighting> - <contexts> - <context name = "lhs" attribute="Keyword" lineEndContext="#stay"> - <DetectChar char="=" attribute="Operator" context="rhs"/> - <Detect2Chars char="(" char1="*" attribute="Comment" context="comment"/> - </context> - <context name = "rhs" attribute="Variable" lineEndContext="#stay"> - <AnyChar String="|" attribute="Operator" context="#stay"/> - <AnyChar String=",()[]{}" attribute="Separator" context="#stay"/> - <DetectChar char=";" attribute="Separator" context="#pop"/> - <DetectChar attribute="String" context="stringdoublequote" char=""" /> - <DetectChar attribute="String" context="stringsinglequote" char="'" /> - <DetectChar char="?" attribute="Operator" context="special"/> - </context> - <context name="stringdoublequote" attribute="String" lineEndContext="#stay"> - <DetectChar attribute="String" context="#pop" char="""/> - </context> - <context name="stringsinglequote" attribute="String" lineEndContext="#stay"> - <DetectChar attribute="String" context="#pop" char="'"/> - </context> - <context name="comment" attribute="Comment" lineEndContext="#stay"> - <Detect2Chars char="*" char1=")" context="#pop"/> - </context> - <context name="special" attribute="Special" lineEndContext="#stay"> - <DetectChar char="?" attribute="Operator" context="#pop"/> - </context> - </contexts> - <itemDatas> - <itemData name="Normal Text" defStyleNum="dsNormal" /> - <itemData name="Keyword" defStyleNum="dsKeyword" /> - <itemData name="Operator" defStyleNum="dsOperator" /> - <itemData name="Separator" defStyleNum="dsOperator" /> - <itemData name="String" defStyleNum="dsString" /> - <itemData name="Variable" defStyleNum="dsVariable" /> - <itemData name="Comment" defStyleNum="dsComment"/> - <itemData name="Special" defStyleNum="dsVerbatimString"/> - </itemDatas> - </highlighting> -</language> diff --git a/spec/firrtl.xml b/spec/firrtl.xml deleted file mode 100644 index a5c5f318..00000000 --- a/spec/firrtl.xml +++ /dev/null @@ -1,174 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<language name="FIRRTL" version="1" kateversion="2.4" section="Sources" extensions="*.firrtl;*.fir"> - <highlighting> - <list name="structure"> - <item>circuit</item> - <item>module</item> - <item>extmodule</item> - </list> - <list name="keywords"> - <item>input</item> - <item>output</item> - <item>defname</item> - <item>parameter</item> - <item>skip</item> - <item>is</item> - <item>invalid</item> - <item>inst</item> - <item>of</item> - <item>wire</item> - <item>node</item> - </list> - <list name="types"> - <item>UInt</item> - <item>SInt</item> - <item>Fixed</item> - <item>Analog</item> - <item>Clock</item> - <item>Reset</item> - <item>AsyncReset</item> - </list> - <list name="conditionals"> - <item>when</item> - <item>else</item> - </list> - <list name="primops"> - <item>attach</item> - <item>add</item> - <item>sub</item> - <item>mul</item> - <item>div</item> - <item>rem</item> - <item>lt</item> - <item>leq</item> - <item>gt</item> - <item>geq</item> - <item>eq</item> - <item>neq</item> - <item>pad</item> - <item>asUInt</item> - <item>asSInt</item> - <item>asClock</item> - <item>shl</item> - <item>shr</item> - <item>dshl</item> - <item>dshr</item> - <item>cvt</item> - <item>neg</item> - <item>not</item> - <item>and</item> - <item>or</item> - <item>xor</item> - <item>andr</item> - <item>orr</item> - <item>xorr</item> - <item>cat</item> - <item>bits</item> - <item>head</item> - <item>tail</item> - <item>asFixedPoint</item> - <item>bpshl</item> - <item>bpshr</item> - <item>bpset</item> - <item>mux</item> - <item>validif</item> - <item>stop</item> - <item>printf</item> - <item>assert</item> - <item>assume</item> - <item>cover</item> - </list> - <contexts> - <context name="Normal Text" attribute="ID" lineEndContext="#pop"> - <keyword attribute="Keyword" context="#stay" String="keywords" /> - <keyword attribute="Keyword" context="type" String="types" /> - <keyword attribute="Structure" context="#stay" String="structure" /> - <keyword attribute="PrimOp" context="#stay" String="primops" /> - <keyword attribute="Conditional" context="#stay" String="conditionals" /> - <Detect2Chars char="(" char1="*" attribute="Info" context="info"/> - <DetectChar char= ";" context="comment" attribute="Comment"/> - <DetectChar char="{" context="field" attribute="Separator"/> - <Detect2Chars char="<" char1="=" attribute="Operator" context="#stay"/> - <Detect2Chars char="<" char1="-" attribute="Operator" context="#stay"/> - <Detect2Chars char="=" char1=">" attribute="Operator" context="#stay"/> - <AnyChar String=":=.,()" attribute="Separator" context="#stay"/> - <DetectChar char="[" attribute="Operator" context="widthOrDepthOrLit"/> - <DetectChar char=""" attribute="String" context="string"/> - <StringDetect String="reg" attribute="Keyword" context="register"/> - <StringDetect String="mem" attribute="Keyword" context="memoryFirst"/> - </context> - <context name="memoryFirst" attribute="ID" lineEndContext="#pop!memory"> - </context> - <context name="memory" attribute="Keyword" lineEndContext="#stay"> - <Detect2Chars char="=" char1=">" attribute="Operator" context="memoryRHS"/> - <StringDetect String="read-under-write" attribute="Keyword" context="#pop!memoryLast"/> - </context> - <context name="memoryRHS" attribute="ID" lineEndContext="#pop"> - <keyword String="types" attribute="Keyword" context="type"/> - </context> - <context name="memoryLast" attribute="Keyword" lineEndContext="#pop"> - <Detect2Chars char="=" char1=">" attribute="Operator" context="#stay"/> - </context> - <context name="register" attribute="ID" lineEndContext="#pop"> - <keyword String="types" attribute="Keyword" context="type"/> - <AnyChar String=":=>.,()" attribute="Separator" context="#stay"/> - <StringDetect String="with" attribute="Keyword" context="#pop!registerinit"/> - </context> - <context name="registerinit" attribute="comment" lineEndContext="#stay"> - <AnyChar String=":=>.,()" attribute="Separator" context="#stay"/> - <StringDetect String="reset" attribute="Keyword" context="#pop"/> - <DetectChar char= ";" context="comment" attribute="Comment"/> - </context> - <context name="comment" attribute="Comment" lineEndContext="#pop"> - </context> - <context name="string" attribute="String" lineEndContext="#stay"> - <DetectChar char=""" attribute="String" context="#pop"/> - </context> - <context name="info" attribute="Info" lineEndContext="#stay"> - <DetectChar char="]" context="#pop"/> - </context> - <context name="type" attribute="String" lineEndContext="#pop"> - <AnyChar String="<[(" attribute="Operator" context="widthOrDepthOrLit"/> - <AnyChar String="," attribute="Separator" context="#pop"/> - <AnyChar String="}" attribute="Separator" context="#pop#pop"/> - <DetectChar char= ";" context="comment" attribute="Comment"/> - </context> - <context name="widthOrDepthOrLit" attribute="String" lineEndContext="#stay"> - <DetectChar char="<" attribute="Operator" context="widthOrDepthOrLit"/> - <AnyChar String=">])" attribute="Operator" context="#pop"/> - </context> - <context name="field" attribute="ID" lineEndContext="#stay"> - <StringDetect String="flip" attribute="Keyword" context="#stay"/> - <keyword String="types" attribute="Keyword" context="type"/> - <DetectChar char="{" attribute="Separator" context="field"/> - <DetectChar char="}" attribute="Separator" context="#pop"/> - <AnyChar String=":," attribute="Separator" context="#stay"/> - <DetectChar char= ";" context="comment" attribute="Comment"/> - </context> - </contexts> - <itemDatas> - <itemData name="Normal Text" defStyleNum="dsNormal" /> - <itemData name="Keyword" defStyleNum="dsKeyword" /> - <itemData name="Structure" defStyleNum="dsKeyword" /> - <itemData name="PrimOp" defStyleNum="dsOperator" /> - <itemData name="Conditional" defStyleNum="dsControlFlow" /> - <itemData name="String" defStyleNum="dsString" /> - <itemData name="Comment" defStyleNum="dsComment" /> - <itemData name="ID" defStyleNum="dsVariable" /> - <itemData name="Operator" defStyleNum="dsOperator" /> - </itemDatas> - </highlighting> - <general> - <comments> - <comment name="singleLine" start=";"/> - </comments> - <keywords casesensitive="1"/> - <folding indentationsensitive="0"/> - <emptyLines> - <emptyLine regexpr="\s+"/> - <emptyLine regexpr="\s*#.*"/> - </emptyLines> - <spellchecking> - </spellchecking> - </general> -</language> diff --git a/spec/future-release.txt b/spec/future-release.txt deleted file mode 100644 index dd9eece5..00000000 --- a/spec/future-release.txt +++ /dev/null @@ -1,7 +0,0 @@ -Proposed Firrtl Spec changes for Next Release - -Change tail -> drop -Add ranges as a 'width' instead of actually declaring width. - proposed syntax: wire x: UInt{0,10} -Add Analog type, and 'attach' statement (see #87) -Add constraints to low firrtl that assignments are same width, etc. diff --git a/spec/leftovers.txt b/spec/leftovers.txt deleted file mode 100644 index 3446487a..00000000 --- a/spec/leftovers.txt +++ /dev/null @@ -1,309 +0,0 @@ - -%\section{User Guide - Misc} -% -%The resulting instance has a bundle type, where the given module's ports are fields %and can be accessed using the subfield expression. -%The orientation of the {\em output} ports are {\em default}, and the orientation of %the {\em input} ports are {\em reverse}. -%An instance may be directly connected to another element, but it must be on the right-%hand side of the connect statement. -% -%The following example illustrates directly connecting an instance to a wire: -% -%{ \fontsize{11pt}{1.15em}\selectfont -%\[ -%\begin{aligned} -%&\kw{extmodule} Queue \ \kws{:} \\ -%&\quad \kw{input} clk \ \kw{:} \kws{Clock} \\ -%&\quad \kw{input} in \ \kw{:} \kws{UInt$<$}16\kws{$>$} \\ -%&\quad \kw{output} out \ \kw{:} \kws{UInt$<$}16\kws{$>$} \\ -%&\kw{module} Top \ \kws{:} \\ -%&\quad \kw{input} clk \ \kw{:} \kws{Clock} \\ -%&\quad \kw{inst} queue \ \kw{:} Queue \\ -%&\quad \kw{wire} connect \ \kw{:} \bundleT{\kw{default} out \ \kw{:} \kws{UInt$<$}16\%kws{$>$},\kw{reverse} in \ \kw{:} \ \kws{UInt$<$}16\kws{$>$},\kw{reverse} clk \ \kw{:} %\ \kws{Clock}} \\ -%&\quad connect \ \kw{$<$=} queue \\ -%\end{aligned} -%\] -%} -% -%The output ports of an instance may only be connected from, e.g., the right-hand side %of a connect statement. -%Conversely, the input ports of an instance may only be connected to, e.g., the left-%hand side of a connect statement. -% -%The following example illustrates a proper use of creating instances with different %clock domains: -% -%{ \fontsize{11pt}{1.15em}\selectfont -%\[ -%\begin{aligned} -%&\kw{extmodule} AsyncQueue \ \kws{:} \\ -%&\quad \kw{input} clk1 \ \kw{:} \kws{Clock} \\ -%&\quad \kw{input} clk2 \ \kw{:} \kws{Clock} \\ -%&\quad \kw{input} in \ \kw{:} \bundleT{\kw{default} data \ \kw{:} \kws{UInt$<$}16\kws{%$>$},\kw{reverse} ready \ \kw{:} \kws{UInt$<$}1\kws{$>$}} \\ -%&\quad \kw{output} out \ \kw{:} \bundleT{\kw{default} data \ \kw{:} \kws{UInt$<$}16\%kws{$>$},\kw{reverse} ready \ \kw{:} \kws{UInt$<$}1\kws{$>$}} \\ -%&\kw{extmodule} Source \ \kws{:} \\ -%&\quad \kw{input} clk \ \kw{:} \kws{Clock} \\ -%&\quad \kw{output} packet \ \kw{:} \bundleT{\kw{default} data \ \kw{:} \kws{UInt$<$}16%\kws{$>$},\kw{reverse} ready \ \kw{:} \kws{UInt$<$}1\kws{$>$}} \\ -%&\kw{extmodule} Sink \ \kws{:} \\ -%&\quad \kw{input} clk \ \kw{:} \kws{Clock} \\ -%&\quad \kw{input} packet \ \kw{:} \bundleT{\kw{default} data \ \kw{:} \kws{UInt$<$}16\%kws{$>$},\kw{reverse} ready \ \kw{:} \kws{UInt$<$}1\kws{$>$}} \\ -%&\kw{module} TwoClock \ \kws{:} \\ -%&\quad \kw{input} clk1 \ \kw{:} \kws{Clock} \\ -%&\quad \kw{input} clk2 \ \kw{:} \kws{Clock} \\ -%&\quad \kw{inst} src \ \kw{:} Source \\ -%&\quad src.clk \ \kw{$<$=} clk1 \\ -%&\quad \kw{inst} snk \ \kw{:} Sink \\ -%&\quad snk.clk \ \kw{$<$=} clk2 \\ -%&\quad \kw{inst} queue \ \kw{:} AsyncQueue \\ -%&\quad queue.clk1 \ \kw{$<$=} clk1 \\ -%&\quad queue.clk2 \ \kw{$<$=} clk2 \\ -%&\quad queue.in \ \kw{$<$=} src.packet \\ -%&\quad snk.packet \ \kw{$<$=} queue.out \\ -%\end{aligned} -%\] -%} -% - -%\section{Annotations - IN PROGRESS} -%Supporting annotations is a critical piece of FIRRTL, yet is a very difficult problem %to solve properly. -%We are in the experimental phase of supporting annotations, and our philosophy is %outlined below. -%It remains to be seen whether our philosophy is correct - if not, we will certainly %devise a new strategy. -% -%\begin{enumerate}[topsep=3pt,itemsep=-0.5ex,partopsep=1ex,parsep=1ex] -%\item Writing a correct circuit is difficult - avoid silent failures at all costs. -%\item If annotations are held in the graph, every pass must properly propagate all %possible annotations. -%\item A pass incorrectly propagating an annotation cannot be easily detected (silent %failure). -%\item If annotations are held in an external data structure mapping names to %annotations, the structure must updated after every pass. -%\item Incorrectly updating the structure will cause a mismatching of names between %circuit components and annotation entries, which is easily detected. -%\item Thus, we feel the ability to detect failure outweighs the additional burden on %annotation writers. -%\end{enumerate} - -%To implement this philosophy, we encourage passes to either preserve names in the %graph, use simple algorithms to transform names, or provide a rename table after a pass%. -%The annotation writer then updates their data structure accordingly. - -%\section{Concrete Syntax}\label{concrete} -%This section describes the text format for FIRRTL that is supported by the provided %readers and writers. -% -%\subsection*{Circuits and Modules} -%A circuit is specified the following way. -%\begin{verbatim} -%circuit name : (modules ...) -%\end{verbatim} -%Or by taking advantage of indentation structuring: -%\begin{verbatim} -%circuit name : -% modules ... -%\end{verbatim} -% -%A module is specified the following way. -%\begin{verbatim} -%module name : (ports ... stmts ...) -%\end{verbatim} -%The module body consists of a sequence of ports followed immediately by a sequence of %statements. -%If there is more than one statement they are grouped into a statement group by the %parser. -%By using indentation structuring: -%\begin{verbatim} -%module name : -% ports ... -% stmts ... -%\end{verbatim} -% -%The following shows an example of a simple module. -%\begin{verbatim} -%module mymodule : -% input a: UInt<1> -% output b: UInt<1> -% clock clk: UInt<1> -% b <= a -%\end{verbatim} -% -%\subsection*{Types} -%The unsigned and signed integer types are specified the following way. -%The following examples demonstrate an unsigned integer with known bit width, signed %integer with known bit width, an unsigned integer with unknown bit width, and signed %integer with unknown bit width. -%\begin{verbatim} -%UInt<42> -%SInt<42> -%UInt<?> -%SInt<?> -%\end{verbatim} -% -%The bundle type consists of a number of fields surrounded with braces. -%The following shows an example of a decoupled bundle type. -%Note that the commas are for clarity only and are not necessary. -%\begin{verbatim} -%{default data: UInt<10>, -% default valid: UInt<1>, -% reverse ready: UInt<1>} -%\end{verbatim} -% -%The vector type is specified by immediately postfixing a type with a bracketed integer %literal. -%The following example demonstrates a ten-element vector of 16-bit unsigned integers. -%\begin{verbatim} -%UInt<16>[10] -%\end{verbatim} -% -%\subsection*{Statements} -%The following examples demonstrate declaring wires, registers, memories, nodes, %instances, poisons, and accessors. -%\begin{verbatim} -%wire mywire : UInt<10> -%reg myreg : UInt<10>, clk, reset -%cmem mycombmem : UInt<10>,16 -%smem myseqmem : UInt<10>,16 -%inst myinst : MyModule -%poison mypoison : UInt<10> -%infer accessor myaccessor = e[i],clk -%\end{verbatim} -% -%The connect statement is specified using the \verb|<=| operator. -%\begin{verbatim} -%x <= y -%\end{verbatim} -% -%The onreset connect statement is specified using the onreset keyword and the \verb|<=| %operator. -%\begin{verbatim} -%onreset x <= y -%\end{verbatim} -% -%The partial connect statement is specified using the \verb|<-| operator. -%\begin{verbatim} -%x <- y -%\end{verbatim} -% -%The assert statement is specified using the assert keyword. -%\begin{verbatim} -%assert x -%\end{verbatim} -% -%The conditional statement is specified with the \verb|when| keyword. -%\begin{verbatim} -%when x : x <= y else : x <= z -%\end{verbatim} -%Or by using indentation structuring: -%\begin{verbatim} -%when x : -% x <= y -%else : -% x <= z -%\end{verbatim} -% -%If there is no alternative branch specified, the parser will automatically insert an %empty statement. -%\begin{verbatim} -%when x : -% x <= y -%\end{verbatim} -% -%For convenience when expressing nested conditional statements, the colon following the %\verb|else| keyword may be elided if the next statement is another conditional %statement. -%\begin{verbatim} -%when x : -% x <= y -%else when y : -% x <= z -%else : -% x <= w -%\end{verbatim} -% -%\subsection*{Expressions} -% -%The UInt and SInt constructors create literal integers from a given value and bit width%. -%The following examples demonstrate creating literal integers of both known and unknown %bit width. -%\begin{verbatim} -%UInt<4>(42) -%SInt<4>(-42) -%UInt<?>(42) -%SInt<?>(-42) -%\end{verbatim} -% -%References are specified with an identifier. -%\begin{verbatim} -%x -%\end{verbatim} -% -%Subfields are expressed using the dot operator. -%\begin{verbatim} -%x.data -%\end{verbatim} -% -%Subindices are expressed using the \verb|[]| operator. -%\begin{verbatim} -%x[10] -%\end{verbatim} -% -%Primitive operations are expressed by following the name of the primitive with a list %containing the operands. -%\begin{verbatim} -%add(x, y) -%add(x, add(x, y)) -%shl(x, 42) -%\end{verbatim} - - -%\section{Future Plans} -%Some choices were made during the design of this specification which were %intentionally conservative, so that future versions could lift the restrictions if %suitable semantics and implementations are determined. -%By restricting this version and potentially lifting these restrictions in future %versions, all existing FIRRTL circuits will remain valid. -% -%The following design decisions could potentially be changed in future spec revisions: -%\begin{enumerate}[topsep=3pt,itemsep=-0.5ex,partopsep=1ex,parsep=1ex] -%\item Disallowing zero-width types -%\item Always expanding memories into smaller memories (if its type is a non-ground-type%) -%\item Not including a \kws{ROM} node -%\item Custom annotations are not held in FIRRTL nodes -%\item Not requiring that all names are unique -%\end{enumerate} -% -%\section{Questions and Answers} -%\begin{enumerate}[topsep=3pt,itemsep=-0.5ex,partopsep=1ex,parsep=1ex] -%\item Why are there three connect operators? -%Each is needed for a particular use case - the better question is why did we chose to %create multiple connect statements instead of other constructs. -%Statements, as opposed to expressions, are very restricted in how they nest. -%Thus, the desired supported behavior (partial connects, full connects, and resets) %will never be used in an arbitrary nested expression where the semantics would be %unintuitive. -%In addition, both the implementation and the user only needs to look at the single %statement to implement it. -% -%\item Aren't there a lot of idiosyncrasies in FIRRTL? -%The FIRRTL specification is an ongoing process, and as we push more code through it, %it is likely to change. -%In our opinion, the idiosyncrasies are necessary for a cohesive design (and all %languages have idiosyncrasies). -%It remains an unknown whether there are too many idiosyncrasies for frontend writers. -%Because the spec is not frozen, we can certainly adapt it if necessary. -%However, at this point, we just need to push more code through. -% -%\item Why have a separate construct for initializing a register? -%The problem is initializing a register with a vector/bundle type, where a subset of %the fields are initialized. -%If the initial value is kept with the declaration, we would need a new construct to %specify a subset of values of ALL (potentially) nested vector/bundle types. -%It makes much more sense to separate initialization from the declaration, and use %something like a <= to initialize the fields/vector sub-components of the register. -%The next question is why not just have users specify the initial value using their own %"when reset :" statement. -%This doesn't work because of last connect semantics - the user could easily clobber %their initialization when statement without knowing. -%Creating an onreset statement does two things: (1) specifies to the USER exactly what %the reset value will be for any sub-component of a register, (2) encapsulates the %reset value in a way that is easy for the implementation to special case it (so it %doesn't get clobbered). -% -%\item Why do operations allow inputs of differing widths? -%We tried restricting widths, but it actually complicated width inference and made %supporting front-ends with more lax width restrictions very difficult. -%Because there is perfectly well defined semantics, we opted to allow differing widths. -%In line with the Linux "funnel" philosophy of being accepting with your inputs and %restrictive with your outputs. -% -%\item Why require all names unique? -%Passes usually need unique names, so there needs to be a renaming pass somewhere. -%Standardizing how names gets mangled requires a lot of thought, and we didn't feel %comfortable putting this into the spec at the moment and potentially regretting it %later. -%For now, names have to be unique, and it is the front-end's responsibility to do this. -% -%\item Why allow declaring components in when statements? -%We want the important property that a module is just a box of components inside - for %any jumble of components, you can always lace them in the box, and it will preserve %the semantics. -%You need to declare wires inside whens - because generators could run within a when in %a front-end. -%You should always be able to pull them into a module if we want. -%Now its inconsistent if you can't declare registers in the scope. -% -%\item Why not just have LoFIRRTL? -%LoFIRRTL leaves out general when usage, vector and bundle types, and requires a single %connect. -%For performance backends, we will need to emit arrays and structs. -%If there is only a lowered circuit, we lose that ability. -%We cannot simply add vector/bundle types to LoFIRRTL as front-ends cannot easily %remove whens without removing the complex types as well. -%Instead, one will need the expressiveness in FIRRTL to write a performant backend %which does not need to operate on LoFIRRTL. -% -%\item Why the stop statement have no arguments? -%Like the enable for write-accessors, the lowering step will preserve the sequence of %when statements under which a simulation will stop. -% -%\item Why disallow zero-width wires? -%Very tricky to get the semantics correct. -%On the todo list. -% -%\item Why not require default value for wires? Isn't this a SAT problem? -%We do the same thing that is done in Java, and is standard programming language %practice. -% -%\item Why did/didn't you include XXX primop? -%Up for debate. -% -%\item How do you support subword assignment? -%We decided to not support subword assignment directly, and instead require the user to %separate the subword assignment into a vector type. Then, the user uses the subindex %expression to assign to an element in the vector. -% -%\end{enumerate} diff --git a/spec/spec-template.tex b/spec/spec-template.tex deleted file mode 100644 index e4631da8..00000000 --- a/spec/spec-template.tex +++ /dev/null @@ -1,560 +0,0 @@ -% Options for packages loaded elsewhere -\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref} -\PassOptionsToPackage{hyphens}{url} -$if(colorlinks)$ -\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor} -$endif$ -$if(dir)$ -$if(latex-dir-rtl)$ -\PassOptionsToPackage{RTLdocument}{bidi} -$endif$ -$endif$ -$if(CJKmainfont)$ -\PassOptionsToPackage{space}{xeCJK} -$endif$ -% -\documentclass[ -$if(fontsize)$ - $fontsize$, -$endif$ -$if(lang)$ - $babel-lang$, -$endif$ -$if(papersize)$ - $papersize$paper, -$endif$ -$if(beamer)$ - ignorenonframetext, -$if(handout)$ - handout, -$endif$ -$if(aspectratio)$ - aspectratio=$aspectratio$, -$endif$ -$endif$ -$for(classoption)$ - $classoption$$sep$, -$endfor$ -]{$documentclass$} -$if(title)$ -\title{$title$$if(thanks)$\thanks{$thanks$}$endif$} -$endif$ -$if(subtitle)$ -$if(beamer)$ -$else$ -\usepackage{etoolbox} -\makeatletter -\providecommand{\subtitle}[1]{% add subtitle to \maketitle - \apptocmd{\@title}{\par {\large #1 \par}}{}{} -} -\makeatother -$endif$ -\subtitle{$subtitle$} -$endif$ -\author{$for(author)$$author$$sep$ \and $endfor$} -\date{$date$} -$if(beamer)$ -$if(institute)$ -\institute{$for(institute)$$institute$$sep$ \and $endfor$} -$endif$ -$if(titlegraphic)$ -\titlegraphic{\includegraphics{$titlegraphic$}} -$endif$ -$if(logo)$ -\logo{\includegraphics{$logo$}} -$endif$ -$endif$ - -$if(beamer)$ -$if(background-image)$ -\usebackgroundtemplate{% - \includegraphics[width=\paperwidth]{$background-image$}% -} -$endif$ -\usepackage{pgfpages} -\setbeamertemplate{caption}[numbered] -\setbeamertemplate{caption label separator}{: } -\setbeamercolor{caption name}{fg=normal text.fg} -\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$ -$for(beameroption)$ -\setbeameroption{$beameroption$} -$endfor$ -% Prevent slide breaks in the middle of a paragraph -\widowpenalties 1 10000 -\raggedbottom -$if(section-titles)$ -\setbeamertemplate{part page}{ - \centering - \begin{beamercolorbox}[sep=16pt,center]{part title} - \usebeamerfont{part title}\insertpart\par - \end{beamercolorbox} -} -\setbeamertemplate{section page}{ - \centering - \begin{beamercolorbox}[sep=12pt,center]{part title} - \usebeamerfont{section title}\insertsection\par - \end{beamercolorbox} -} -\setbeamertemplate{subsection page}{ - \centering - \begin{beamercolorbox}[sep=8pt,center]{part title} - \usebeamerfont{subsection title}\insertsubsection\par - \end{beamercolorbox} -} -\AtBeginPart{ - \frame{\partpage} -} -\AtBeginSection{ - \ifbibliography - \else - \frame{\sectionpage} - \fi -} -\AtBeginSubsection{ - \frame{\subsectionpage} -} -$endif$ -$endif$ -$if(beamerarticle)$ -\usepackage{beamerarticle} % needs to be loaded first -$endif$ -\usepackage{amsmath,amssymb} -$if(fontfamily)$ -\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$} -$else$ -\usepackage{lmodern} -$endif$ -$if(linestretch)$ -\usepackage{setspace} -$endif$ -\usepackage{iftex} -\ifPDFTeX - \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc} - \usepackage[utf8]{inputenc} - \usepackage{textcomp} % provide euro and other symbols -\else % if luatex or xetex -$if(mathspec)$ - \ifXeTeX - \usepackage{mathspec} - \else - \usepackage{unicode-math} - \fi -$else$ - \usepackage{unicode-math} -$endif$ - \defaultfontfeatures{Scale=MatchLowercase} - \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} -$if(mainfont)$ - \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$} -$endif$ -$if(sansfont)$ - \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$]{$sansfont$} -$endif$ -$if(monofont)$ - \setmonofont[$for(monofontoptions)$$monofontoptions$$sep$,$endfor$]{$monofont$} -$endif$ -$for(fontfamilies)$ - \newfontfamily{$fontfamilies.name$}[$for(fontfamilies.options)$$fontfamilies.options$$sep$,$endfor$]{$fontfamilies.font$} -$endfor$ -$if(mathfont)$ -$if(mathspec)$ - \ifXeTeX - \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$} - \else - \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$} - \fi -$else$ - \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$} -$endif$ -$endif$ -$if(CJKmainfont)$ - \ifXeTeX - \usepackage{xeCJK} - \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$} - \fi -$endif$ -$if(luatexjapresetoptions)$ - \ifLuaTeX - \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset} - \fi -$endif$ -$if(CJKmainfont)$ - \ifLuaTeX - \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec} - \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$} - \fi -$endif$ -\fi -$if(zero-width-non-joiner)$ -%% Support for zero-width non-joiner characters. -\makeatletter -\def\zerowidthnonjoiner{% - % Prevent ligatures and adjust kerning, but still support hyphenating. - \texorpdfstring{% - \textormath{\nobreak\discretionary{-}{}{\kern.03em}% - \ifvmode\else\nobreak\hskip\z@skip\fi}{}% - }{}% -} -\makeatother -\ifPDFTeX - \DeclareUnicodeCharacter{200C}{\zerowidthnonjoiner} -\else - \catcode`^^^^200c=\active - \protected\def ^^^^200c{\zerowidthnonjoiner} -\fi -%% End of ZWNJ support -$endif$ -$if(beamer)$ -$if(theme)$ -\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$} -$endif$ -$if(colortheme)$ -\usecolortheme{$colortheme$} -$endif$ -$if(fonttheme)$ -\usefonttheme{$fonttheme$} -$endif$ -$if(mainfont)$ -\usefonttheme{serif} % use mainfont rather than sansfont for slide text -$endif$ -$if(innertheme)$ -\useinnertheme{$innertheme$} -$endif$ -$if(outertheme)$ -\useoutertheme{$outertheme$} -$endif$ -$endif$ -% Use upquote if available, for straight quotes in verbatim environments -\IfFileExists{upquote.sty}{\usepackage{upquote}}{} -\IfFileExists{microtype.sty}{% use microtype if available - \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype} - \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts -}{} -$if(indent)$ -$else$ -\makeatletter -\@ifundefined{KOMAClassName}{% if non-KOMA class - \IfFileExists{parskip.sty}{% - \usepackage{parskip} - }{% else - \setlength{\parindent}{0pt} - \setlength{\parskip}{6pt plus 2pt minus 1pt}} -}{% if KOMA class - \KOMAoptions{parskip=half}} -\makeatother -$endif$ -$if(verbatim-in-note)$ -\usepackage{fancyvrb} -$endif$ -\usepackage{xcolor} -\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available -\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} -\hypersetup{ -$if(title-meta)$ - pdftitle={$title-meta$}, -$endif$ -$if(author-meta)$ - pdfauthor={$author-meta$}, -$endif$ -$if(lang)$ - pdflang={$lang$}, -$endif$ -$if(subject)$ - pdfsubject={$subject$}, -$endif$ -$if(keywords)$ - pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$}, -$endif$ -$if(colorlinks)$ - colorlinks=true, - linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$}, - filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$}, - citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$}, - urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$}, -$else$ - hidelinks, -$endif$ - pdfcreator={LaTeX via pandoc}} -\urlstyle{same} % disable monospaced font for URLs -$if(verbatim-in-note)$ -\VerbatimFootnotes % allow verbatim text in footnotes -$endif$ -$if(geometry)$ -$if(beamer)$ -\geometry{$for(geometry)$$geometry$$sep$,$endfor$} -$else$ -\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} -$endif$ -$endif$ -$if(beamer)$ -\newif\ifbibliography -$endif$ -$if(listings)$ -\usepackage{listings} -\newcommand{\passthrough}[1]{#1} -\lstset{defaultdialect=[5.3]Lua} -\lstset{defaultdialect=[x86masm]Assembler} -$endif$ -$if(lhs)$ -\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} -$endif$ -$if(highlighting-macros)$ -$highlighting-macros$ -$endif$ -$if(tables)$ -\usepackage{longtable,booktabs,array} -$if(multirow)$ -\usepackage{multirow} -$endif$ -\usepackage{calc} % for calculating minipage widths -$if(beamer)$ -\usepackage{caption} -% Make caption package work with longtable -\makeatletter -\def\fnum@table{\tablename~\thetable} -\makeatother -$else$ -% Correct order of tables after \paragraph or \subparagraph -\usepackage{etoolbox} -\makeatletter -\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} -\makeatother -% Allow footnotes in longtable head/foot -\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} -\makesavenoteenv{longtable} -$endif$ -$endif$ -$if(graphics)$ -\usepackage{graphicx} -\makeatletter -\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} -\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} -\makeatother -% Scale images if necessary, so that they will not overflow the page -% margins by default, and it is still possible to overwrite the defaults -% using explicit options in \includegraphics[width, height, ...]{} -\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} -% Set default figure placement to htbp -\makeatletter -\def\fps@figure{htbp} -\makeatother -$endif$ -$if(links-as-notes)$ -% Make links footnotes instead of hotlinks: -\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}} -$endif$ -$if(strikeout)$ -\usepackage[normalem]{ulem} -% Avoid problems with \sout in headers with hyperref -\pdfstringdefDisableCommands{\renewcommand{\sout}{}} -$endif$ -\setlength{\emergencystretch}{3em} % prevent overfull lines -\providecommand{\tightlist}{% - \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} -$if(numbersections)$ -\setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$} -$else$ -\setcounter{secnumdepth}{-\maxdimen} % remove section numbering -$endif$ -$if(beamer)$ -$else$ -$if(block-headings)$ -% Make \paragraph and \subparagraph free-standing -\ifx\paragraph\undefined\else - \let\oldparagraph\paragraph - \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} -\fi -\ifx\subparagraph\undefined\else - \let\oldsubparagraph\subparagraph - \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} -\fi -$endif$ -$endif$ -$if(pagestyle)$ -$if(pagestyle.fancy)$ -\usepackage{fancyhdr} -\pagestyle{fancy} -$if(title)$ -\lhead{$title$} -$endif$ -$if(version)$ -\rhead{Version $version$} -$endif$ -$else$ -\pagestyle{$pagestyle$} -$endif$ -$endif$ -$if(csl-refs)$ -\newlength{\cslhangindent} -\setlength{\cslhangindent}{1.5em} -\newlength{\csllabelwidth} -\setlength{\csllabelwidth}{3em} -\newlength{\cslentryspacingunit} % times entry-spacing -\setlength{\cslentryspacingunit}{\parskip} -\newenvironment{CSLReferences}[2] % #1 hanging-ident, #2 entry spacing - {% don't indent paragraphs - \setlength{\parindent}{0pt} - % turn on hanging indent if param 1 is 1 - \ifodd #1 - \let\oldpar\par - \def\par{\hangindent=\cslhangindent\oldpar} - \fi - % set entry spacing - \setlength{\parskip}{#2\cslentryspacingunit} - }% - {} -\usepackage{calc} -\newcommand{\CSLBlock}[1]{#1\hfill\break} -\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{#1}} -\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{#1}\break} -\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1} -$endif$ -$for(header-includes)$ -$header-includes$ -$endfor$ -$if(lang)$ -\ifXeTeX - % Load polyglossia as late as possible: uses bidi with RTL langages (e.g. Hebrew, Arabic) - \usepackage{polyglossia} - \setmainlanguage[$for(polyglossia-lang.options)$$polyglossia-lang.options$$sep$,$endfor$]{$polyglossia-lang.name$} -$for(polyglossia-otherlangs)$ - \setotherlanguage[$for(polyglossia-otherlangs.options)$$polyglossia-otherlangs.options$$sep$,$endfor$]{$polyglossia-otherlangs.name$} -$endfor$ -\else - \usepackage[$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel} -% get rid of language-specific shorthands (see #6817): -\let\LanguageShortHands\languageshorthands -\def\languageshorthands#1{} -$if(babel-newcommands)$ - $babel-newcommands$ -$endif$ -\fi -$endif$ -\ifLuaTeX - \usepackage{selnolig} % disable illegal ligatures -\fi -$if(dir)$ -\ifXeTeX - % Load bidi as late as possible as it modifies e.g. graphicx - \usepackage{bidi} -\fi -\ifPDFTeX - \TeXXeTstate=1 - \newcommand{\RL}[1]{\beginR #1\endR} - \newcommand{\LR}[1]{\beginL #1\endL} - \newenvironment{RTL}{\beginR}{\endR} - \newenvironment{LTR}{\beginL}{\endL} -\fi -$endif$ -$if(natbib)$ -\usepackage[$natbiboptions$]{natbib} -\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} -$endif$ -$if(biblatex)$ -\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex} -$for(bibliography)$ -\addbibresource{$bibliography$} -$endfor$ -$endif$ -$if(nocite-ids)$ -\nocite{$for(nocite-ids)$$it$$sep$, $endfor$} -$endif$ -$if(csquotes)$ -\usepackage{csquotes} -$endif$ - -\begin{document} -$if(has-frontmatter)$ -\frontmatter -$endif$ -$if(title)$ -$if(beamer)$ -\frame{\titlepage} -$else$ -\maketitle -$endif$ -$if(abstract)$ -\begin{abstract} -$abstract$ -\end{abstract} -$endif$ -$endif$ - -$for(include-before)$ -$include-before$ - -$endfor$ -$if(toc)$ -$if(toc-title)$ -\renewcommand*\contentsname{$toc-title$} -$endif$ -$if(beamer)$ -\begin{frame}[allowframebreaks] -$if(toc-title)$ - \frametitle{$toc-title$} -$endif$ - \tableofcontents[hideallsubsections] -\end{frame} -$else$ -{ -$if(colorlinks)$ -\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$} -$endif$ -\setcounter{tocdepth}{$toc-depth$} -\tableofcontents -} -$endif$ -$endif$ -$if(lof)$ -\listoffigures -$endif$ -$if(lot)$ -\listoftables -$endif$ -$if(linestretch)$ -\setstretch{$linestretch$} -$endif$ -$if(has-frontmatter)$ -\mainmatter -$endif$ -$body$ - -$if(has-frontmatter)$ -\backmatter -$endif$ -$if(natbib)$ -$if(bibliography)$ -$if(biblio-title)$ -$if(has-chapters)$ -\renewcommand\bibname{$biblio-title$} -$else$ -\renewcommand\refname{$biblio-title$} -$endif$ -$endif$ -$if(beamer)$ -\begin{frame}[allowframebreaks]{$biblio-title$} - \bibliographytrue -$endif$ - \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$} -$if(beamer)$ -\end{frame} -$endif$ - -$endif$ -$endif$ -$if(biblatex)$ -$if(beamer)$ -\begin{frame}[allowframebreaks]{$biblio-title$} - \bibliographytrue - \printbibliography[heading=none] -\end{frame} -$else$ -\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ -$endif$ - -$endif$ -$for(include-after)$ -$include-after$ - -$endfor$ -\end{document} diff --git a/spec/spec.md b/spec/spec.md deleted file mode 100644 index 1ab779cb..00000000 --- a/spec/spec.md +++ /dev/null @@ -1,2722 +0,0 @@ ---- -author: -- | - Patrick S. Li\ - <psli@eecs.berkeley.edu> -- | - Adam M. Izraelevitz\ - <adamiz@eecs.berkeley.edu> -- | - Jonathan Bachrach\ - <jrb@eecs.berkeley.edu> -title: Specification for the FIRRTL Language -date: \today -# Custom options added to the customized template -version: 0.2.0 -# Options passed to the document class -classoption: -- 12pt -# Link options -colorlinks: true -linkcolor: blue -filecolor: magenta -urlcolor: cyan -toccolor: blue -# General pandoc configuration -toc: true -numbersections: true -# Header Setup -pagestyle: - fancy: true -# Margins -geometry: margin=1in -# pandoc-crossref -autoSectionLabels: true -figPrefix: - - Figure - - Figures -eqnPrefix: - - Equation - - Equations -tblPrefix: - - Table - - Tables -lstPrefix: - - Listing - - Listings -secPrefix: - - Section - - Sections -# This 'lastDelim' option does not work... -lastDelim: ", and" ---- - -# Introduction - -## Background - -The ideas for FIRRTL (Flexible Intermediate Representation for RTL) originated -from work on Chisel, a hardware description language (HDL) embedded in Scala -used for writing highly-parameterized circuit design generators. Chisel -designers manipulate circuit components using Scala functions, encode their -interfaces in Scala types, and use Scala's object-orientation features to write -their own circuit libraries. This form of meta-programming enables expressive, -reliable and type-safe generators that improve RTL design productivity and -robustness. - -The computer architecture research group at U.C. Berkeley relies critically on -Chisel to allow small teams of graduate students to design sophisticated RTL -circuits. Over a three year period with under twelve graduate students, the -architecture group has taped-out over ten different designs. - -Internally, the investment in developing and learning Chisel was rewarded with -huge gains in productivity. However, Chisel's external rate of adoption was slow -for the following reasons. - -1. Writing custom circuit transformers requires intimate knowledge about the - internals of the Chisel compiler. - -2. Chisel semantics are under-specified and thus impossible to target from - other languages. - -3. Error checking is unprincipled due to under-specified semantics resulting in - incomprehensible error messages. - -4. Learning a functional programming language (Scala) is difficult for RTL - designers with limited programming language experience. - -5. Confounding the previous point, conceptually separating the embedded Chisel - HDL from the host language is difficult for new users. - -6. The output of Chisel (Verilog) is unreadable and slow to simulate. - -As a consequence, Chisel needed to be redesigned from the ground up to -standardize its semantics, modularize its compilation process, and cleanly -separate its front-end, intermediate representation, and backends. A well -defined intermediate representation (IR) allows the system to be targeted by -other HDLs embedded in other host programming languages, making it possible for -RTL designers to work within a language they are already comfortable with. A -clearly defined IR with a concrete syntax also allows for inspection of the -output of circuit generators and transformers thus making clear the distinction -between the host language and the constructed circuit. Clearly defined semantics -allows users without knowledge of the compiler implementation to write circuit -transformers; examples include optimization of circuits for simulation speed, -and automatic insertion of signal activity counters. An additional benefit of a -well defined IR is the structural invariants that can be enforced before and -after each compilation stage, resulting in a more robust compiler and structured -mechanism for error checking. - -## Design Philosophy - -FIRRTL represents the standardized elaborated circuit that the Chisel HDL -produces. FIRRTL represents the circuit immediately after Chisel's elaboration -but before any circuit simplification. It is designed to resemble the Chisel HDL -after all meta-programming has executed. Thus, a user program that makes little -use of meta-programming facilities should look almost identical to the generated -FIRRTL. - -For this reason, FIRRTL has first-class support for high-level constructs such -as vector types, bundle types, conditional statements, partial connects, and -modules. These high-level constructs are then gradually removed by a sequence of -*lowering* transformations. During each lowering transformation, the circuit is -rewritten into an equivalent circuit using simpler, lower-level -constructs. Eventually the circuit is simplified to its most restricted form, -resembling a structured netlist, which allows for easy translation to an output -language (e.g. Verilog). This form is given the name *lowered FIRRTL* (LoFIRRTL) -and is a strict subset of the full FIRRTL language. - -Because the host language is now used solely for its meta-programming -facilities, the frontend can be very light-weight, and additional HDLs written -in other languages can target FIRRTL and reuse the majority of the compiler -toolchain. - -# Acknowledgments - -The FIRRTL language could not have been developed without the help of many of -the faculty and students in the ASPIRE lab, and the University of California, -Berkeley. - -This project originated from discussions with the authors' advisor, Jonathan -Bachrach, who indicated the need for a structural redesign of the Chisel system -around a well-defined intermediate representation. Patrick Li designed and -implemented the first prototype of the FIRRTL language, wrote the initial -specification for the language, and presented it to the Chisel group consisting -of Adam Izraelevitz, Scott Beamer, David Biancolin, Christopher Celio, Henry -Cook, Palmer Dabbelt, Donggyu Kim, Jack Koenig, Martin Maas, Albert Magyar, -Colin Schmidt, Andrew Waterman, Yunsup Lee, Richard Lin, Eric Love, Albert Ou, -Stephen Twigg, John Bachan, David Donofrio, Farzad Fatollahi-Fard, Jim Lawson, -Brian Richards, Krste Asanović, and John Wawrzynek. - -Adam Izraelevitz then reworked the design and re-implemented FIRRTL, and after -many discussions with Patrick Li and the Chisel group, refined the design to its -present version. - -The authors would like to thank the following individuals in particular for -their contributions to the FIRRTL project: - -- Andrew Waterman: for his many contributions to the design of FIRRTL's - constructs, for his work on Chisel 3.0, and for porting architecture - research infrastructure - -- Richard Lin: for improving the Chisel 3.0 code base for release quality - -- Jack Koenig: for implementing the FIRRTL parser in Scala - -- Henry Cook: for porting and cleaning up many aspects of Chisel 3.0, - including the testing infrastructure and the parameterization library - -- Chick Markley: for creating the new testing harness and porting the Chisel - tutorial - -- Stephen Twigg: for his expertise in hardware intermediate representations - and for providing many corner cases to consider - -- Palmer Dabbelt, Eric Love, Martin Maas, Christopher Celio, and Scott Beamer: - for their feedback on previous drafts of the FIRRTL specification - -And finally this project would not have been possible without the continuous -feedback and encouragement of Jonathan Bachrach, and his leadership on and -implementation of Chisel. - -This research was partially funded by DARPA Award Number HR0011-12-2-0016, the -Center for Future Architecture Research, a member of STARnet, a Semiconductor -Research Corporation program sponsored by MARCO and DARPA, and ASPIRE Lab -industrial sponsors and affiliates Intel, Google, Huawei, Nokia, NVIDIA, Oracle, -and Samsung. Any opinions, findings, conclusions, or recommendations in this -paper are solely those of the authors and does not necessarily reflect the -position or the policy of the sponsors. - -# Circuits and Modules - -## Circuits - -All FIRRTL circuits consist of a list of modules, each representing a hardware -block that can be instantiated. The circuit must specify the name of the -top-level module. - -``` firrtl -circuit MyTop : - module MyTop : - ; ... - module MyModule : - ; ... -``` - -## Modules - -Each module has a given name, a list of ports, and a statement representing the -circuit connections within the module. A module port is specified by its , which -may be input or output, a name, and the data type of the port. - -The following example declares a module with one input port, one output port, -and one statement connecting the input port to the output port. See -[@sec:connects] for details on the connect statement. - -``` firrtl -module MyModule : - input foo: UInt - output bar: UInt - bar <= foo -``` - -Note that a module definition does *not* indicate that the module will be -physically present in the final circuit. Refer to the description of the -instance statement for details on how to instantiate a module -([@sec:instances]). - -## Externally Defined Modules - -Externally defined modules are modules whose implementation is not provided in -the current circuit. Only the ports and name of the externally defined module -are specified in the circuit. An externally defined module may include, in -order, an optional _defname_ which sets the name of the external module in the -resulting Verilog and zero or more name--value _parameter_ statements. Each -name--value parameter statement will result in a value being passed to the named -parameter in the resulting Verilog. - -An example of an externally defined module is: - -``` firrtl -extmodule MyExternalModule : - input foo: UInt<2> - output bar: UInt<4> - output baz: SInt<8> - defname = VerilogName - parameter x = "hello" - parameter y = 42 -``` - -The widths of all externally defined module ports must be specified. Width -inference, described in [@sec:width-inference], is not supported for module -ports. - -A common use of an externally defined module is to represent a Verilog module -that will be written separately and provided together with FIRRTL-generated -Verilog to downstream tools. - -# Types - -Types are used to specify the structure of the data held by each circuit -component. All types in FIRRTL are either one of the fundamental ground types or -are built up from aggregating other types. - -## Ground Types - -There are five ground types in FIRRTL: an unsigned integer type, a signed -integer type, a fixed-point number type, a clock type, and an analog type. - -### Integer Types - -Both unsigned and signed integer types may optionally be given a known -non-negative integer bit width. - -``` firrtl -UInt<10> -SInt<32> -``` - -Alternatively, if the bit width is omitted, it will be automatically inferred by -FIRRTL's width inferencer, as detailed in [@sec:width-inference]. - -``` firrtl -UInt -SInt -``` - -### Fixed-Point Number Type - -In general, a fixed-point binary number type represents a range of values -corresponding with the range of some integral type scaled by a fixed power of -two. In the FIRRTL language, the number represented by a signal of fixed-point -type may expressed in terms of a base integer *value* term and a *binary point*, -which represents an inverse power of two. - -The range of the value term is governed by a *width* an a manner analogous to -integral types, with the additional restriction that all fixed-point number -types are inherently signed in FIRRTL. Whenever an operation such as a -`cat`{.firrtl} operates on the "bits" of a fixed-point number, it operates on -the string of bits that is the signed representation of the integer value -term. The *width* of a fixed-point typed signal is the width of this string of -bits. - -$$\begin{aligned} - \text{fixed-point quantity} &= \left( \text{integer value} \right) \times 2^{-\left(\text{binary point}\right)}\\ - \text{integer value} &\in \left[ -2^{(\text{width})-1}, 2^{(\text{width})-1} \right)\\ - \text{binary point} &\in \mathbb{Z}\end{aligned}$$ - -In the above equation, the range of possible fixed-point quantities is governed -by two parameters beyond a the particular "value" assigned to a signal: the -width and the binary point. Note that when the binary point is positive, it is -equivalent to the number of bits that would fall after the binary point. Just as -width is a parameter of integer types in FIRRTL, width and binary point are both -parameters of the fixed-point type. - -When declaring a component with fixed-point number type, it is possible to leave -the width and/or the binary point unspecified. The unspecified parameters will -be inferred to be sufficient to hold the results of all expressions that may -drive the component. Similar to how width inference for integer types depends on -width-propagation rules for each FIRRTL expression and each kind of primitive -operator, fixed-point parameter inference depends on a set of rules outlined -throughout this spec. - -Included below are examples of the syntax for all possible combinations of -specified and inferred fixed-point type parameters. - -``` firrtl -Fixed<3><<2>> ; 3-bit width, 2 bits after binary point -Fixed<10> ; 10-bit width, inferred binary point -Fixed<<-4>> ; Inferred width, binary point of -4 -Fixed ; Inferred width and binary point -``` - -### Clock Type - -The clock type is used to describe wires and ports meant for carrying clock -signals. The usage of components with clock types are restricted. Clock signals -cannot be used in most primitive operations, and clock signals can only be -connected to components that have been declared with the clock type. - -The clock type is specified as follows: - -``` firrtl -Clock -``` - -### Analog Type - -The analog type specifies that a wire or port can be attached to multiple -drivers. `Analog`{.firrtl} cannot be used as the type of a node or register, nor -can it be used as the datatype of a memory. In this respect, it is similar to -how `inout`{.firrtl} ports are used in Verilog, and FIRRTL analog signals are -often used to interface with external Verilog or VHDL IP. - -In contrast with all other ground types, analog signals cannot appear on either -side of a connection statement. Instead, analog signals are attached to each -other with the commutative `attach`{.firrtl} statement. An analog signal may -appear in any number of attach statements, and a legal circuit may also contain -analog signals that are never attached. The only primitive operations that may -be applied to analog signals are casts to other signal types. - -When an analog signal appears as a field of an aggregate type, the aggregate -cannot appear in a standard connection statement; however, the partial -connection statement will `attach`{.firrtl} corresponding analog fields of its -operands according to the partial connection algorithm described in -[@sec:the-partial-connection-algorithm]. - -As with integer types, an analog type can represent a multi-bit signal. When -analog signals are not given a concrete width, their widths are inferred -according to a highly restrictive width inference rule, which requires that the -widths of all arguments to a given attach operation be identical. - -``` firrtl -Analog<1> ; 1-bit analog type -Analog<32> ; 32-bit analog type -Analog ; analog type with inferred width -``` - -## Vector Types - -A vector type is used to express an ordered sequence of elements of a given -type. The length of the sequence must be non-negative and known. - -The following example specifies a ten element vector of 16-bit unsigned -integers. - -``` firrtl -UInt<16>[10] -``` - -The next example specifies a ten element vector of unsigned integers of omitted -but identical bit widths. - -``` firrtl -UInt[10] -``` - -Note that any type, including other aggregate types, may be used as the element -type of the vector. The following example specifies a twenty element vector, -each of which is a ten element vector of 16-bit unsigned integers. - -``` firrtl -UInt<16>[10][20] -``` - -## Bundle Types - -A bundle type is used to express a collection of nested and named types. All -fields in a bundle type must have a given name, and type. - -The following is an example of a possible type for representing a complex -number. It has two fields, `real`{.firrtl}, and `imag`{.firrtl}, both 10-bit -signed integers. - -``` firrtl -{real: SInt<10>, imag: SInt<10>} -``` - -Additionally, a field may optionally be declared with a *flipped* orientation. - -``` firrtl -{word: UInt<32>, valid: UInt<1>, flip ready: UInt<1>} -``` - -In a connection between circuit components with bundle types, the data carried -by the flipped fields flow in the opposite direction as the data carried by the -non-flipped fields. - -As an example, consider a module output port declared with the following type: - -``` firrtl -output a: {word: UInt<32>, valid: UInt<1>, flip ready: UInt<1>} -``` - -In a connection to the `a`{.firrtl} port, the data carried by the -`word`{.firrtl} and `valid`{.firrtl} sub-fields will flow out of the module, -while data carried by the `ready`{.firrtl} sub-field will flow into the -module. More details about how the bundle field orientation affects connections -are explained in [@sec:connects]. - -As in the case of vector types, a bundle field may be declared with any type, -including other aggregate types. - -``` firrtl -{real: {word: UInt<32>, valid: UInt<1>, flip ready: UInt<1>} - imag: {word: UInt<32>, valid: UInt<1>, flip ready: UInt<1>}} - -``` - -When calculating the final direction of data flow, the orientation of a field is -applied recursively to all nested types in the field. As an example, consider -the following module port declared with a bundle type containing a nested bundle -type. - -``` firrtl -output myport: {a: UInt, flip b: {c: UInt, flip d: UInt}} -``` - -In a connection to `myport`{.firrtl}, the `a`{.firrtl} sub-field flows out of -the module. The `c`{.firrtl} sub-field contained in the `b`{.firrtl} sub-field -flows into the module, and the `d`{.firrtl} sub-field contained in the -`b`{.firrtl} sub-field flows out of the module. - -## Passive Types - -It is inappropriate for some circuit components to be declared with a type that -allows for data to flow in both directions. For example, all sub-elements in a -memory should flow in the same direction. These components are restricted to -only have a passive type. - -Intuitively, a passive type is a type where all data flows in the same -direction, and is defined to be a type that recursively contains no fields with -flipped orientations. Thus all ground types are passive types. Vector types are -passive if their element type is passive. And bundle types are passive if no -fields are flipped and if all field types are passive. - -## Type Equivalence - -The type equivalence relation is used to determine whether a connection between -two components is legal. See [@sec:connects] for further details about connect -statements. - -An unsigned integer type is always equivalent to another unsigned integer type -regardless of bit width, and is not equivalent to any other type. Similarly, a -signed integer type is always equivalent to another signed integer type -regardless of bit width, and is not equivalent to any other type. - -A fixed-point number type is always equivalent to another fixed-point number -type, regardless of width or binary point. It is not equivalent to any other -type. - -Clock types are equivalent to clock types, and are not equivalent to any other -type. - -Two vector types are equivalent if they have the same length, and if their -element types are equivalent. - -Two bundle types are equivalent if they have the same number of fields, and both -the bundles' i'th fields have matching names and orientations, as well as -equivalent types. Consequently, `{a:UInt, b:UInt}`{.firrtl} is not equivalent to -`{b:UInt, a:UInt}`{.firrtl}, and `{a: {flip b:UInt}}`{.firrtl} is not equivalent -to `{flip a: {b: UInt}}`{.firrtl}. - -## Weak Type Equivalence - -The weak type equivalence relation is used to determine whether a partial -connection between two components is legal. See [@sec:partial-connects] for -further details about partial connect statements. - -Two types are weakly equivalent if their corresponding oriented types are -equivalent. - -### Oriented Types - -The weak type equivalence relation requires first a definition of *oriented -types*. Intuitively, an oriented type is a type where all orientation -information is collated and coupled with the leaf ground types instead of in -bundle fields. - -An oriented ground type is an orientation coupled with a ground type. An -oriented vector type is an ordered sequence of positive length of elements of a -given oriented type. An oriented bundle type is a collection of oriented fields, -each containing a name and an oriented type, but no orientation. - -Applying a flip orientation to an oriented type recursively reverses the -orientation of every oriented ground type contained within. Applying a non-flip -orientation to an oriented type does nothing. - -### Conversion to Oriented Types - -To convert a ground type to an oriented ground type, attach a non-flip -orientation to the ground type. - -To convert a vector type to an oriented vector type, convert its element type to -an oriented type, and retain its length. - -To convert a bundle field to an oriented field, convert its type to an oriented -type, apply the field orientation, and combine this with the original field's -name to create the oriented field. To convert a bundle type to an oriented -bundle type, convert each field to an oriented field. - -### Oriented Type Equivalence - -Two oriented ground types are equivalent if their orientations match and their -types are equivalent. - -Two oriented vector types are equivalent if their element types are equivalent. - -Two oriented bundle types are not equivalent if there exists two fields, one -from each oriented bundle type, that have identical names but whose oriented -types are not equivalent. Otherwise, the oriented bundle types are equivalent. - -As stated earlier, two types are weakly equivalent if their corresponding -oriented types are equivalent. - -# Statements - -Statements are used to describe the components within a module and how they -interact. - -## Connects - -The connect statement is used to specify a physically wired connection between -two circuit components. - -The following example demonstrates connecting a module's input port to its -output port, where port `myinput`{.firrtl} is connected to port -`myoutput`{.firrtl}. - -``` firrtl -module MyModule : - input myinput: UInt - output myoutput: UInt - myoutput <= myinput -``` - -In order for a connection to be legal the following conditions must hold: - -1. The types of the left-hand and right-hand side expressions must be - equivalent (see [@sec:type-equivalence] for details). - -2. The bit widths of the two expressions must allow for data to always flow - from a smaller bit width to an equal size or larger bit width. - -3. The flow of the left-hand side expression must be sink or duplex (see - [@sec:flows] for an explanation of flow). - -4. Either the flow of the right-hand side expression is source or duplex, or - the right-hand side expression has a passive type. - -Connect statements from a narrower ground type component to a wider ground type -component will have its value automatically sign-extended or zero-extended to -the larger bit width. The behaviour of connect statements between two circuit -components with aggregate types is defined by the connection algorithm in -[@sec:the-connection-algorithm]. - -### The Connection Algorithm - -Connect statements between ground types cannot be expanded further. - -Connect statements between two vector typed components recursively connects each -sub-element in the right-hand side expression to the corresponding sub-element -in the left-hand side expression. - -Connect statements between two bundle typed components connects the i'th field -of the right-hand side expression and the i'th field of the left-hand side -expression. If the i'th field is not flipped, then the right-hand side field is -connected to the left-hand side field. Conversely, if the i'th field is -flipped, then the left-hand side field is connected to the right-hand side -field. - -## Partial Connects - -Like the connect statement, the partial connect statement is also used to -specify a physically wired connection between two circuit components. However, -it enforces fewer restrictions on the types and widths of the circuit components -it connects. - -In order for a partial connect to be legal the following conditions must hold: - -1. The types of the left-hand and right-hand side expressions must be weakly - equivalent (see [@sec:weak-type-equivalence] for details). - -2. The flow of the left-hand side expression must be sink or duplex (see - [@sec:flows] for an explanation of flow). - -3. Either the flow of the right-hand side expression is source or duplex, or - the right-hand side expression has a passive type. - -Partial connect statements from a narrower ground type component to a wider -ground type component will have its value automatically sign-extended to the -larger bit width. Partial connect statements from a wider ground type component -to a narrower ground type component will have its value automatically truncated -to fit the smaller bit width. - -Intuitively, bundle fields with matching names will be connected appropriately, -while bundle fields not present in both types will be ignored. Similarly, -vectors with mismatched lengths will be connected up to the shorter length, and -the remaining sub-elements are ignored. The full algorithm is detailed in -[@sec:the-partial-connection-algorithm]. - -The following example demonstrates partially connecting a module's input port to -its output port, where port `myinput`{.firrtl} is connected to port -`myoutput`{.firrtl}. - -``` firrtl -module MyModule : - input myinput: {flip a: UInt, b: UInt[2]} - output myoutput: {flip a: UInt, b: UInt[3], c: UInt} - myoutput <- myinput -``` - -The above example is equivalent to the following: - -``` firrtl -module MyModule : - input myinput: {flip a: UInt, b: UInt[2]} - output myoutput: {flip a: UInt, b: UInt[3], c: UInt} - myinput.a <- myoutput.a - myoutput.b[0] <- myinput.b[0] - myoutput.b[1] <- myinput.b[1] -``` - -For details on the syntax and semantics of the sub-field expression, sub-index -expression, and statement groups, see [@sec:sub-fields; @sec:sub-indices; -@sec:statement-groups]. - -### The Partial Connection Algorithm - -A partial connect statement between two non-analog ground type components -connects the right-hand side expression to the left-hand side -expression. Conversely, a *reverse* partial connect statement between two -non-analog ground type components connects the left-hand side expression to the -right-hand side expression. A partial connect statement between two analog-typed -components performs an attach between the two signals. - -A partial (or reverse partial) connect statement between two vector typed -components applies a partial (or reverse partial) connect from the first n -sub-elements in the right-hand side expression to the first n corresponding -sub-elements in the left-hand side expression, where n is the length of the -shorter vector. - -A partial (or reverse partial) connect statement between two bundle typed -components considers any pair of fields, one from the first bundle type and one -from the second, with matching names. If the first field in the pair is not -flipped, then we apply a partial (or reverse partial) connect from the -right-hand side field to the left-hand side field. However, if the first field -is flipped, then we apply a reverse partial (or partial) connect from the -right-hand side field to the left-hand side field. - -## Statement Groups - -An ordered sequence of one or more statements can be grouped into a single -statement, called a statement group. The following example demonstrates a -statement group composed of three connect statements. - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - output myport1: UInt - output myport2: UInt - myport1 <= a - myport1 <= b - myport2 <= a -``` - -### Last Connect Semantics - -Ordering of statements is significant in a statement group. Intuitively, during -elaboration, statements execute in order, and the effects of later statements -take precedence over earlier ones. In the previous example, in the resultant -circuit, port `b`{.firrtl} will be connected to `myport1`{.firrtl}, and port -`a`{.firrtl} will be connected to `myport2`{.firrtl}. - -Note that connect and partial connect statements have equal priority, and later -connect or partial connect statements always take priority over earlier connect -or partial connect statements. Conditional statements are also affected by last -connect semantics, and for details see [@sec:conditional-last-connect-semantics]. - -In the case where a connection to a circuit component with an aggregate type is -followed by a connection to a sub-element of that component, only the connection -to the sub-element is overwritten. Connections to the other sub-elements remain -unaffected. In the following example, in the resultant circuit, the `c`{.firrtl} -sub-element of port `portx`{.firrtl} will be connected to the `c`{.firrtl} -sub-element of `myport`{.firrtl}, and port `porty`{.firrtl} will be connected to -the `b`{.firrtl} sub-element of `myport`{.firrtl}. - -``` firrtl -module MyModule : - input portx: {b: UInt, c: UInt} - input porty: UInt - output myport: {b: UInt, c: UInt} - myport <= portx - myport.b <= porty -``` - -The above circuit can be rewritten equivalently as follows. - -``` firrtl -module MyModule : - input portx: {b: UInt, c: UInt} - input porty: UInt - output myport: {b: UInt, c: UInt} - myport.b <= porty - myport.c <= portx.c -``` - -In the case where a connection to a sub-element of an aggregate circuit -component is followed by a connection to the entire circuit component, the later -connection overwrites the earlier connections completely. - -``` firrtl -module MyModule : - input portx: {b: UInt, c: UInt} - input porty: UInt - output myport: {b: UInt, c: UInt} - myport.b <= porty - myport <= portx -``` - -The above circuit can be rewritten equivalently as follows. - -``` firrtl -module MyModule : - input portx: {b: UInt, c: UInt} - input porty: UInt - output myport: {b: UInt, c: UInt} - myport <= portx -``` - -See [@sec:sub-fields] for more details about sub-field expressions. - -## Empty - -The empty statement does nothing and is used simply as a placeholder where a -statement is expected. It is specified using the `skip`{.firrtl} keyword. - -The following example: - -``` firrtl -a <= b -skip -c <= d -``` - -can be equivalently expressed as: - -``` firrtl -a <= b -c <= d -``` - -The empty statement is most often used as the `else`{.firrtl} branch in a -conditional statement, or as a convenient placeholder for removed components -during transformational passes. See [@sec:conditionals] for details on the -conditional statement. - -## Wires - -A wire is a named combinational circuit component that can be connected to and -from using connect and partial connect statements. - -The following example demonstrates instantiating a wire with the given name -`mywire`{.firrtl} and type `UInt`{.firrtl}. - -``` firrtl -wire mywire: UInt -``` - -## Registers - -A register is a named stateful circuit component. - -The following example demonstrates instantiating a register with the given name -`myreg`{.firrtl}, type `SInt`{.firrtl}, and is driven by the clock signal -`myclock`{.firrtl}. - -``` firrtl -wire myclock: Clock -reg myreg: SInt, myclock -; ... -``` - -Optionally, for the purposes of circuit initialization, a register can be -declared with a reset signal and value. In the following example, -`myreg`{.firrtl} is assigned the value `myinit`{.firrtl} when the signal -`myreset`{.firrtl} is high. - -``` firrtl -wire myclock: Clock -wire myreset: UInt<1> -wire myinit: SInt -reg myreg: SInt, myclock with: (reset => (myreset, myinit)) -; ... -``` - -Note that the clock signal for a register must be of type `clock`{.firrtl}, the -reset signal must be a single bit `UInt`{.firrtl}, and the type of -initialization value must match the declared type of the register. - -## Invalidates - -An invalidate statement is used to indicate that a circuit component contains -indeterminate values. It is specified as follows: - -``` firrtl -wire w: UInt -w is invalid -``` - -Invalidate statements can be applied to any circuit component of any -type. However, if the circuit component cannot be connected to, then the -statement has no effect on the component. This allows the invalidate statement -to be applied to any component, to explicitly ignore initialization coverage -errors. - -The following example demonstrates the effect of invalidating a variety of -circuit components with aggregate types. See [@sec:the-invalidate-algorithm] for -details on the algorithm for determining what is invalidated. - -``` firrtl -module MyModule : - input in: {flip a: UInt, b: UInt} - output out: {flip a: UInt, b: UInt} - wire w: {flip a: UInt, b: UInt} - in is invalid - out is invalid - w is invalid -``` - -is equivalent to the following: - -``` firrtl -module MyModule : - input in: {flip a: UInt, b: UInt} - output out: {flip a: UInt, b: UInt} - wire w: {flip a: UInt, b: UInt} - in.a is invalid - out.b is invalid - w.a is invalid - w.b is invalid -``` - -For the purposes of simulation, invalidated components are initialized to random -values, and operations involving indeterminate values produce undefined -behaviour. This is useful for early detection of errors in simulation. - -### The Invalidate Algorithm - -Invalidating a component with a ground type indicates that the component's value -is undetermined if the component has sink or duplex flow (see [@sec:flows]). -Otherwise, the component is unaffected. - -Invalidating a component with a vector type recursively invalidates each -sub-element in the vector. - -Invalidating a component with a bundle type recursively invalidates each -sub-element in the bundle. - -## Attaches - -The `attach`{.firrtl} statement is used to attach two or more analog signals, -defining that their values be the same in a commutative fashion that lacks the -directionality of a regular connection. It can only be applied to signals with -analog type, and each analog signal may be attached zero or more times. - -``` firrtl -wire x: Analog<2> -wire y: Analog<2> -wire z: Analog<2> -attach(x, y) ; binary attach -attach(z, y, x) ; attach all three signals -``` - -When signals of aggregate types that contain analog-typed fields are used as -operators of a partial connection, corresponding fields of analog type are -attached, rather than connected. - -## Nodes - -A node is simply a named intermediate value in a circuit. The node must be -initialized to a value with a passive type and cannot be connected to. Nodes are -often used to split a complicated compound expression into named -sub-expressions. - -The following example demonstrates instantiating a node with the given name -`mynode`{.firrtl} initialized with the output of a multiplexer (see -[@sec:multiplexers]). - -``` firrtl -wire pred: UInt<1> -wire a: SInt -wire b: SInt -node mynode = mux(pred, a, b) -``` - -## Conditionals - -Connections within a conditional statement that connect to previously declared -components hold only when the given condition is high. The condition must have a -1-bit unsigned integer type. - -In the following example, the wire `x`{.firrtl} is connected to the input -`a`{.firrtl} only when the `en`{.firrtl} signal is high. Otherwise, the wire -`x`{.firrtl} is connected to the input `b`{.firrtl}. - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input en: UInt<1> - wire x: UInt - when en : - x <= a - else : - x <= b -``` - -### Syntactic Shorthands - -The `else`{.firrtl} branch of a conditional statement may be omitted, in which -case a default `else`{.firrtl} branch is supplied consisting of the empty -statement. - -Thus the following example: - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input en: UInt<1> - wire x: UInt - when en : - x <= a -``` - -can be equivalently expressed as: - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input en: UInt<1> - wire x: UInt - when en : - x <= a - else : - skip -``` - -To aid readability of long chains of conditional statements, the colon following -the `else`{.firrtl} keyword may be omitted if the `else`{.firrtl} branch -consists of a single conditional statement. - -Thus the following example: - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input c: UInt - input d: UInt - input c1: UInt<1> - input c2: UInt<1> - input c3: UInt<1> - wire x: UInt - when c1 : - x <= a - else : - when c2 : - x <= b - else : - when c3 : - x <= c - else : - x <= d -``` - -can be equivalently written as: - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input c: UInt - input d: UInt - input c1: UInt<1> - input c2: UInt<1> - input c3: UInt<1> - wire x: UInt - when c1 : - x <= a - else when c2 : - x <= b - else when c3 : - x <= c - else : - x <= d -``` - -To additionally aid readability, a conditional statement where the contents of -the `when`{.firrtl} branch consist of a single line may be combined into a -single line. If an `else`{.firrtl} branch exists, then the `else`{.firrtl} -keyword must be included on the same line. - -The following statement: - -``` firrtl -when c : - a <= b -else : - e <= f -``` - -can have the `when`{.firrtl} keyword, the `when`{.firrtl} branch, and the -`else`{.firrtl} keyword expressed as a single line: - -``` firrtl -when c : a <= b else : - e <= f -``` - -The `else`{.firrtl} branch may also be added to the single line: - -``` firrtl -when c : a <= b else : e <= f -``` - -### Nested Declarations - -If a component is declared within a conditional statement, connections to the -component are unaffected by the condition. In the following example, register -`myreg1`{.firrtl} is always connected to `a`{.firrtl}, and register -`myreg2`{.firrtl} is always connected to `b`{.firrtl}. - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input en: UInt<1> - input clk : Clock - when en : - reg myreg1 : UInt, clk - myreg1 <= a - else : - reg myreg2 : UInt, clk - myreg2 <= b -``` - -Intuitively, a line can be drawn between a connection (or partial connection) to -a component and that component's declaration. All conditional statements that -are crossed by the line apply to that connection (or partial connection). - -### Initialization Coverage - -Because of the conditional statement, it is possible to syntactically express -circuits containing wires that have not been connected to under all conditions. - -In the following example, the wire `a`{.firrtl} is connected to the wire -`w`{.firrtl} when `en`{.firrtl} is high, but it is not specified what is -connected to `w`{.firrtl} when `en`{.firrtl} is low. - -``` firrtl -module MyModule : - input en: UInt<1> - input a: UInt - wire w: UInt - when en : - w <= a -``` - -This is an illegal FIRRTL circuit and an error will be thrown during -compilation. All wires, memory ports, instance ports, and module ports that can -be connected to must be connected to under all conditions. Registers do not -need to be connected to under all conditions, as it will keep its previous value -if unconnected. - -### Scoping - -The conditional statement creates a new *scope* within each of its -`when`{.firrtl} and `else`{.firrtl} branches. It is an error to refer to any -component declared within a branch after the branch has ended. As mention in -[@sec:namespaces], circuit component declarations in a module must be unique -within the module's flat namespace; this means that shadowing a component in an -enclosing scope with a component of the same name inside a conditional statement -is not allowed. - -### Conditional Last Connect Semantics - -In the case where a connection to a circuit component is followed by a -conditional statement containing a connection to the same component, the -connection is overwritten only when the condition holds. Intuitively, a -multiplexer is generated such that when the condition is low, the multiplexer -returns the old value, and otherwise returns the new value. For details about -the multiplexer, see [@sec:multiplexers]. - -The following example: - -``` firrtl -wire a: UInt -wire b: UInt -wire c: UInt<1> -wire w: UInt -w <= a -when c : - w <= b -``` - -can be rewritten equivalently using a multiplexer as follows: - -``` firrtl -wire a: UInt -wire b: UInt -wire c: UInt<1> -wire w: UInt -w <= mux(c, b, a) -``` - -In the case where an invalid statement is followed by a conditional statement -containing a connect to the invalidated component, the resulting connection to -the component can be expressed using a conditionally valid expression. See -[@sec:conditionally-valids] for more details about the conditionally valid -expression. - -``` firrtl -wire a: UInt -wire c: UInt<1> -wire w: UInt -w is invalid -when c : - w <= a -``` - -can be rewritten equivalently as follows: - -``` firrtl -wire a: UInt -wire c: UInt<1> -wire w: UInt -w <= validif(c, a) -``` - -The behaviour of conditional connections to circuit components with aggregate -types can be modeled by first expanding each connect into individual connect -statements on its ground elements (see [@sec:the-connection-algorithm; -@sec:the-partial-connection-algorithm] for the connection and partial connection -algorithms) and then applying the conditional last connect semantics. - -For example, the following snippet: - -``` firrtl -wire x: {a: UInt, b: UInt} -wire y: {a: UInt, b: UInt} -wire c: UInt<1> -wire w: {a: UInt, b: UInt} -w <= x -when c : - w <= y -``` - -can be rewritten equivalently as follows: - -``` firrtl -wire x: {a:UInt, b:UInt} -wire y: {a:UInt, b:UInt} -wire c: UInt<1> -wire w: {a:UInt, b:UInt} -w.a <= mux(c, y.a, x.a) -w.b <= mux(c, y.b, x.b) -``` - -Similar to the behavior of aggregate types under last connect semantics (see -[@sec:last-connect-semantics]), the conditional connects to a sub-element of an -aggregate component only generates a multiplexer for the sub-element that is -overwritten. - -For example, the following snippet: - -``` firrtl -wire x: {a: UInt, b: UInt} -wire y: UInt -wire c: UInt<1> -wire w: {a: UInt, b: UInt} -w <= x -when c : - w.a <= y -``` - -can be rewritten equivalently as follows: - -``` firrtl -wire x: {a: UInt, b: UInt} -wire y: UInt -wire c: UInt<1> -wire w: {a: UInt, b: UInt} -w.a <= mux(c, y, x.a) -w.b <= x.b -``` - -## Memories - -A memory is an abstract representation of a hardware memory. It is characterized -by the following parameters. - -1. A passive type representing the type of each element in the memory. - -2. A positive integer representing the number of elements in the memory. - -3. A variable number of named ports, each being a read port, a write port, or - readwrite port. - -4. A non-negative integer indicating the read latency, which is the number of - cycles after setting the port's read address before the corresponding - element's value can be read from the port's data field. - -5. A positive integer indicating the write latency, which is the number of - cycles after setting the port's write address and data before the - corresponding element within the memory holds the new value. - -6. A read-under-write flag indicating the behaviour when a memory location is - written to while a read to that location is in progress. - -The following example demonstrates instantiating a memory containing 256 complex -numbers, each with 16-bit signed integer fields for its real and imaginary -components. It has two read ports, `r1`{.firrtl} and `r2`{.firrtl}, and one -write port, `w`{.firrtl}. It is combinationally read (read latency is zero -cycles) and has a write latency of one cycle. Finally, its read-under-write -behavior is undefined. - -``` firrtl -mem mymem : - data-type => {real:SInt<16>, imag:SInt<16>} - depth => 256 - reader => r1 - reader => r2 - writer => w - read-latency => 0 - write-latency => 1 - read-under-write => undefined -``` - -In the example above, the type of `mymem`{.firrtl} is: - -``` firrtl -{flip r1: {addr: UInt<8>, - en: UInt<1>, - clk: Clock, - flip data: {real: SInt<16>, imag: SInt<16>}} - flip r2: {addr: UInt<8>, - en: UInt<1>, - clk: Clock, - flip data: {real: SInt<16>, imag: SInt<16>}} - flip w: {addr: UInt<8>, - en: UInt<1>, - clk: Clock, - data: {real: SInt<16>, imag: SInt<16>}, - mask: {real: UInt<1>, imag: UInt<1>}}} -``` - -The following sections describe how a memory's field types are calculated and -the behavior of each type of memory port. - -### Read Ports - -If a memory is declared with element type `T`{.firrtl}, has a size less than or -equal to $2^N$, then its read ports have type: - -``` firrtl -{addr: UInt<N>, en: UInt<1>, clk: Clock, flip data: T} -``` - -If the `en`{.firrtl} field is high, then the element value associated with the -address in the `addr`{.firrtl} field can be retrieved by reading from the -`data`{.firrtl} field after the appropriate read latency. If the `en`{.firrtl} -field is low, then the value in the `data`{.firrtl} field, after the appropriate -read latency, is undefined. The port is driven by the clock signal in the -`clk`{.firrtl} field. - -### Write Ports - -If a memory is declared with element type `T`{.firrtl}, has a size less than or -equal to $2^N$, then its write ports have type: - -``` firrtl -{addr: UInt<N>, en: UInt<1>, clk: Clock, data: T, mask: M} -``` - -where `M`{.firrtl} is the mask type calculated from the element type -`T`{.firrtl}. Intuitively, the mask type mirrors the aggregate structure of the -element type except with all ground types replaced with a single bit unsigned -integer type. The *non-masked portion* of the data value is defined as the set -of data value leaf sub-elements where the corresponding mask leaf sub-element is -high. - -If the `en`{.firrtl} field is high, then the non-masked portion of the -`data`{.firrtl} field value is written, after the appropriate write latency, to -the location indicated by the `addr`{.firrtl} field. If the `en`{.firrtl} field -is low, then no value is written after the appropriate write latency. The port -is driven by the clock signal in the `clk`{.firrtl} field. - -### Readwrite Ports - -Finally, the readwrite ports have type: - -``` firrtl -{addr: UInt<N>, en: UInt<1>, clk: Clock, flip rdata: T, wmode: UInt<1>, - wdata: T, wmask: M} -``` - -A readwrite port is a single port that, on a given cycle, can be used either as -a read or a write port. If the readwrite port is not in write mode (the -`wmode`{.firrtl} field is low), then the `rdata`{.firrtl}, `addr`{.firrtl}, -`en`{.firrtl}, and `clk`{.firrtl} fields constitute its read port fields, and -should be used accordingly. If the readwrite port is in write mode (the -`wmode`{.firrtl} field is high), then the `wdata`{.firrtl}, `wmask`{.firrtl}, -`addr`{.firrtl}, `en`{.firrtl}, and `clk`{.firrtl} fields constitute its write -port fields, and should be used accordingly. - -### Read Under Write Behaviour - -The read-under-write flag indicates the value held on a read port's -`data`{.firrtl} field if its memory location is written to while it is reading. -The flag may take on three settings: `old`{.firrtl}, `new`{.firrtl}, and -`undefined`{.firrtl}. - -If the read-under-write flag is set to `old`{.firrtl}, then a read port always -returns the value existing in the memory on the same cycle that the read was -requested. - -Assuming that a combinational read always returns the value stored in the memory -(no write forwarding), then intuitively, this is modeled as a combinational read -from the memory that is then delayed by the appropriate read latency. - -If the read-under-write flag is set to `new`{.firrtl}, then a read port always -returns the value existing in the memory on the same cycle that the read was -made available. Intuitively, this is modeled as a combinational read from the -memory after delaying the read address by the appropriate read latency. - -If the read-under-write flag is set to `undefined`{.firrtl}, then the value held -by the read port after the appropriate read latency is undefined. - -For the purpose of defining such collisions, an "active write port" is a write -port or a readwrite port that is used to initiate a write operation on a given -clock edge, where `en`{.firrtl} is set and, for a readwriter, `wmode`{.firrtl} -is set. An "active read port" is a read port or a readwrite port that is used to -initiate a read operation on a given clock edge, where `en`{.firrtl} is set and, -for a readwriter, `wmode`{.firrtl} is not set. Each operation is defined to be -"active" for the number of cycles set by its corresponding latency, starting -from the cycle where its inputs were provided to its associated port. Note that -this excludes combinational reads, which are simply modeled as combinationally -selecting from stored values - -For memories with independently clocked ports, a collision between a read -operation and a write operation with independent clocks is defined to occur when -the address of an active write port and the address of an active read port are -the same for overlapping clock periods, or when any portion of a read operation -overlaps part of a write operation with a matching addresses. In such cases, the -data that is read out of the read port is undefined. - -### Write Under Write Behaviour - -In all cases, if a memory location is written to by more than one port on the -same cycle, the stored value is undefined. - -## Instances - -FIRRTL modules are instantiated with the instance statement. The following -example demonstrates creating an instance named `myinstance`{.firrtl} of the -`MyModule`{.firrtl} module within the top level module `Top`{.firrtl}. - -``` firrtl -circuit Top : - module MyModule : - input a: UInt - output b: UInt - b <= a - module Top : - inst myinstance of MyModule -``` - -The resulting instance has a bundle type. Each port of the instantiated module -is represented by a field in the bundle with the same name and type as the -port. The fields corresponding to input ports are flipped to indicate their data -flows in the opposite direction as the output ports. The `myinstance`{.firrtl} -instance in the example above has type `{flip a:UInt, b:UInt}`. - -Modules have the property that instances can always be *inlined* into the parent -module without affecting the semantics of the circuit. - -To disallow infinitely recursive hardware, modules cannot contain instances of -itself, either directly, or indirectly through instances of other modules it -instantiates. - -## Stops - -The stop statement is used to halt simulations of the circuit. Backends are free -to generate hardware to stop a running circuit for the purpose of debugging, but -this is not required by the FIRRTL specification. - -A stop statement requires a clock signal, a halt condition signal that has a -single bit unsigned integer type, and an integer exit code. - -For clocked statements that have side effects in the environment (stop, print, -and verification statements), the order of execution of any such statements that -are triggered on the same clock edge is determined by their syntactic order in -the enclosing module. The order of execution of clocked, side-effect-having -statements in different modules or with different clocks that trigger -concurrently is undefined. - -The stop statement has an optional name attribute which can be used to attach -metadata to the statement. The name is part of the module level -namespace. However it can never be used in a reference since it is not of any -valid type. - -``` firrtl -wire clk: Clock -wire halt: UInt<1> -stop(clk, halt, 42) : optional_name -``` - -## Formatted Prints - -The formatted print statement is used to print a formatted string during -simulations of the circuit. Backends are free to generate hardware that relays -this information to a hardware test harness, but this is not required by the -FIRRTL specification. - -A printf statement requires a clock signal, a print condition signal, a format -string, and a variable list of argument signals. The condition signal must be a -single bit unsigned integer type, and the argument signals must each have a -ground type. - -For information about execution ordering of clocked statements with observable -environmental side effects, see [@sec:stops]. - -The printf statement has an optional name attribute which can be used to attach -metadata to the statement. The name is part of the module level -namespace. However it can never be used in a reference since it is not of any -valid type. - -``` firrtl -wire clk: Clock -wire cond: UInt<1> -wire a: UInt -wire b: UInt -printf(clk, cond, "a in hex: %x, b in decimal:%d.\n", a, b) : optional_name -``` - -On each positive clock edge, when the condition signal is high, the printf -statement prints out the format string where its argument placeholders are -substituted with the value of the corresponding argument. - -### Format Strings - -Format strings support the following argument placeholders: - -- `%b` : Prints the argument in binary - -- `%d` : Prints the argument in decimal - -- `%x` : Prints the argument in hexadecimal - -- `%%` : Prints a single `%` character - -Format strings support the following escape characters: - -- `\n` : New line - -- `\t` : Tab - -- `\\` : Back slash - -- `\"` : Double quote - -- `\'` : Single quote - -## Verification - -To facilitate simulation, model checking and formal methods, there are three -non-synthesizable verification statements available: assert, assume and -cover. Each type of verification statement requires a clock signal, a predicate -signal, an enable signal and an explanatory message string literal. The -predicate and enable signals must have single bit unsigned integer type. When an -assert is violated the explanatory message may be issued as guidance. The -explanatory message may be phrased as if prefixed by the words "Verifies -that\...". - -Backends are free to generate the corresponding model checking constructs in the -target language, but this is not required by the FIRRTL specification. Backends -that do not generate such constructs should issue a warning. For example, the -SystemVerilog emitter produces SystemVerilog assert, assume and cover -statements, but the Verilog emitter does not and instead warns the user if any -verification statements are encountered. - -For information about execution ordering of clocked statements with observable -environmental side effects, see [@sec:stops]. - -Any verification statement has an optional name attribute which can be used to -attach metadata to the statement. The name is part of the module level -namespace. However it can never be used in a reference since it is not of any -valid type. - -### Assert - -The assert statement verifies that the predicate is true on the rising edge of -any clock cycle when the enable is true. In other words, it verifies that enable -implies predicate. - -``` firrtl -wire clk: Clock -wire pred: UInt<1> -wire en: UInt<1> -pred <= eq(X, Y) -en <= Z_valid -assert(clk, pred, en, "X equals Y when Z is valid") : optional_name -``` - -### Assume - -The assume statement directs the model checker to disregard any states where the -enable is true and the predicate is not true at the rising edge of the clock -cycle. In other words, it reduces the states to be checked to only those where -enable implies predicate is true by definition. In simulation, assume is treated -as an assert. - -``` firrtl -wire clk: Clock -wire pred: UInt<1> -wire en: UInt<1> -pred <= eq(X, Y) -en <= Z_valid -assume(clk, pred, en, "X equals Y when Z is valid") : optional_name -``` - -### Cover - -The cover statement verifies that the predicate is true on the rising edge of -some clock cycle when the enable is true. In other words, it directs the model -checker to find some way to make enable implies predicate true at some time -step. - -``` firrtl -wire clk: Clock -wire pred: UInt<1> -wire en: UInt<1> -pred <= eq(X, Y) -en <= Z_valid -cover(clk, pred, en, "X equals Y when Z is valid") : optional_name -``` - -# Expressions - -FIRRTL expressions are used for creating literal unsigned and signed integers, -for referring to a declared circuit component, for statically and dynamically -accessing a nested element within a component, for creating multiplexers and -conditionally valid signals, and for performing primitive operations. - -## Unsigned Integers - -A literal unsigned integer can be created given a non-negative integer value and -an optional positive bit width. The following example creates a 10-bit unsigned -integer representing the number 42. - -``` firrtl -UInt<10>(42) -``` - -Note that it is an error to supply a bit width that is not large enough to fit -the given value. If the bit width is omitted, then the minimum number of bits -necessary to fit the given value will be inferred. - -``` firrtl -UInt(42) -``` - -## Unsigned Integers from Literal Bits - -A literal unsigned integer can alternatively be created given a string -representing its bit representation and an optional bit width. - -The following radices are supported: - -1.`b`{.firrtl} : For representing binary numbers. - -2.`o`{.firrtl} : For representing octal numbers. - -3.`h`{.firrtl} : For representing hexadecimal numbers. - -If a bit width is not given, the number of bits in the bit representation is -directly represented by the string. The following examples create a 8-bit -integer representing the number 13. - -``` firrtl -UInt("b00001101") -UInt("h0D") -``` - -If the provided bit width is larger than the number of bits required to -represent the string's value, then the resulting value is equivalent to the -string zero-extended up to the provided bit width. If the provided bit width is -smaller than the number of bits represented by the string, then the resulting -value is equivalent to the string truncated down to the provided bit width. All -truncated bits must be zero. - -The following examples create a 7-bit integer representing the number 13. - -``` firrtl -UInt<7>("b00001101") -UInt<7>("o015") -UInt<7>("hD") -``` - -## Signed Integers - -Similar to unsigned integers, a literal signed integer can be created given an -integer value and an optional positive bit width. The following example creates -a 10-bit unsigned integer representing the number -42. - -``` firrtl -SInt<10>(-42) -``` - -Note that it is an error to supply a bit width that is not large enough to fit -the given value using two's complement representation. If the bit width is -omitted, then the minimum number of bits necessary to fit the given value will -be inferred. - -``` firrtl -SInt(-42) -``` - -## Signed Integers from Literal Bits - -Similar to unsigned integers, a literal signed integer can alternatively be -created given a string representing its bit representation and an optional bit -width. - -The bit representation contains a binary, octal or hex indicator, followed by an -optional sign, followed by the value. - -If a bit width is not given, the number of bits in the bit representation is the -minimal bitwidth to represent the value represented by the string. The following -examples create a 8-bit integer representing the number -13. For all bases, a -negative sign acts as if it were a unary negation; in other words, a negative -literal produces the additive inverse of the unsigned interpretation of the -digit pattern. - -``` firrtl -SInt("b-1101") -SInt("h-d") -``` - -If the provided bit width is larger than the number of bits represented by the -string, then the resulting value is unchanged. It is an error to provide a bit -width smaller than the number of bits required to represent the string's value. - -## References - -A reference is simply a name that refers to a previously declared circuit -component. It may refer to a module port, node, wire, register, instance, or -memory. - -The following example connects a reference expression `in`{.firrtl}, referring -to the previously declared port `in`{.firrtl}, to the reference expression -`out`{.firrtl}, referring to the previously declared port `out`{.firrtl}. - -``` firrtl -module MyModule : - input in: UInt - output out: UInt - out <= in -``` - -In the rest of the document, for brevity, the names of components will be used -to refer to a reference expression to that component. Thus, the above example -will be rewritten as "the port `in`{.firrtl} is connected to the port -`out`{.firrtl}". - -## Sub-fields - -The sub-field expression refers to a sub-element of an expression with a bundle -type. - -The following example connects the `in`{.firrtl} port to the `a`{.firrtl} -sub-element of the `out`{.firrtl} port. - -``` firrtl -module MyModule : - input in: UInt - output out: {a: UInt, b: UInt} - out.a <= in -``` - -## Sub-indices - -The sub-index expression statically refers, by index, to a sub-element of an -expression with a vector type. The index must be a non-negative integer and -cannot be equal to or exceed the length of the vector it indexes. - -The following example connects the `in`{.firrtl} port to the fifth sub-element -of the `out`{.firrtl} port. - -``` firrtl -module MyModule : - input in: UInt - output out: UInt[10] - out[4] <= in -``` - -## Sub-accesses - -The sub-access expression dynamically refers to a sub-element of a vector-typed -expression using a calculated index. The index must be an expression with an -unsigned integer type. - -The following example connects the n'th sub-element of the `in`{.firrtl} port to -the `out`{.firrtl} port. - -``` firrtl -module MyModule : - input in: UInt[3] - input n: UInt<2> - output out: UInt - out <= in[n] -``` - -A connection from a sub-access expression can be modeled by conditionally -connecting from every sub-element in the vector, where the condition holds when -the dynamic index is equal to the sub-element's static index. - -``` firrtl -module MyModule : - input in: UInt[3] - input n: UInt<2> - output out: UInt - when eq(n, UInt(0)) : - out <= in[0] - else when eq(n, UInt(1)) : - out <= in[1] - else when eq(n, UInt(2)) : - out <= in[2] - else : - out is invalid -``` - -The following example connects the `in`{.firrtl} port to the n'th sub-element of -the `out`{.firrtl} port. All other sub-elements of the `out`{.firrtl} port are -connected from the corresponding sub-elements of the `default`{.firrtl} port. - -``` firrtl -module MyModule : - input in: UInt - input default: UInt[3] - input n: UInt<2> - output out: UInt[3] - out <= default - out[n] <= in -``` - -A connection to a sub-access expression can be modeled by conditionally -connecting to every sub-element in the vector, where the condition holds when -the dynamic index is equal to the sub-element's static index. - -``` firrtl -module MyModule : - input in: UInt - input default: UInt[3] - input n: UInt<2> - output out: UInt[3] - out <= default - when eq(n, UInt(0)) : - out[0] <= in - else when eq(n, UInt(1)) : - out[1] <= in - else when eq(n, UInt(2)) : - out[2] <= in -``` - -The following example connects the `in`{.firrtl} port to the m'th -`UInt`{.firrtl} sub-element of the n'th vector-typed sub-element of the -`out`{.firrtl} port. All other sub-elements of the `out`{.firrtl} port are -connected from the corresponding sub-elements of the `default`{.firrtl} port. - -``` firrtl -module MyModule : - input in: UInt - input default: UInt[2][2] - input n: UInt<1> - input m: UInt<1> - output out: UInt[2][2] - out <= default - out[n][m] <= in -``` - -A connection to an expression containing multiple nested sub-access expressions -can also be modeled by conditionally connecting to every sub-element in the -expression. However the condition holds only when all dynamic indices are equal -to all of the sub-element's static indices. - -``` firrtl -module MyModule : - input in: UInt - input default: UInt[2][2] - input n: UInt<1> - input m: UInt<1> - output out: UInt[2][2] - out <= default - when and(eq(n, UInt(0)), eq(m, UInt(0))) : - out[0][0] <= in - else when and(eq(n, UInt(0)), eq(m, UInt(1))) : - out[0][1] <= in - else when and(eq(n, UInt(1)), eq(m, UInt(0))) : - out[1][0] <= in - else when and(eq(n, UInt(1)), eq(m, UInt(1))) : - out[1][1] <= in -``` - -## Multiplexers - -A multiplexer outputs one of two input expressions depending on the value of an -unsigned selection signal. - -The following example connects to the `c`{.firrtl} port the result of selecting -between the `a`{.firrtl} and `b`{.firrtl} ports. The `a`{.firrtl} port is -selected when the `sel`{.firrtl} signal is high, otherwise the `b`{.firrtl} port -is selected. - -``` firrtl -module MyModule : - input a: UInt - input b: UInt - input sel: UInt<1> - output c: UInt - c <= mux(sel, a, b) -``` - -A multiplexer expression is legal only if the following holds. - -1. The type of the selection signal is an unsigned integer. - -1. The width of the selection signal is any of: - - 1. One-bit - - 1. Unspecified, but will infer to one-bit - -1. The types of the two input expressions are equivalent. - -1. The types of the two input expressions are passive (see - [@sec:passive-types]). - -## Conditionally Valids - -A conditionally valid expression is expressed as an input expression guarded -with an unsigned single bit valid signal. It outputs the input expression when -the valid signal is high, otherwise the result is undefined. - -The following example connects the `a`{.firrtl} port to the `c`{.firrtl} port -when the `valid`{.firrtl} signal is high. Otherwise, the value of the -`c`{.firrtl} port is undefined. - -``` firrtl -module MyModule : - input a: UInt - input valid: UInt<1> - output c: UInt - c <= validif(valid, a) -``` - -A conditionally valid expression is legal only if the following holds. - -1. The type of the valid signal is a single bit unsigned integer. - -2. The type of the input expression is passive (see [@sec:passive-types]). - -Conditional statements can be equivalently expressed as multiplexers and -conditionally valid expressions. See [@sec:conditionals] for details. - -## Primitive Operations - -All fundamental operations on ground types are expressed as a FIRRTL primitive -operation. In general, each operation takes some number of argument expressions, -along with some number of static integer literal parameters. - -The general form of a primitive operation is expressed as follows: - -``` firrtl -op(arg0, arg1, ..., argn, int0, int1, ..., intm) -``` - -The following examples of primitive operations demonstrate adding two -expressions, `a`{.firrtl} and `b`{.firrtl}, shifting expression `a`{.firrtl} -left by 3 bits, selecting the fourth bit through and including the seventh bit -in the `a`{.firrtl} expression, and interpreting the expression `x`{.firrtl} as -a Clock typed signal. - -``` firrtl -add(a, b) -shl(a, 3) -bits(a, 7, 4) -asClock(x) -``` - -[@sec:primitive-operations] will describe the format and semantics of each -primitive operation. - -# Primitive Operations - -The arguments of all primitive operations must be expressions with ground types, -while their parameters are static integer literals. Each specific operation can -place additional restrictions on the number and types of their arguments and -parameters. - -Notationally, the width of an argument e is represented as w~e~. - -## Add Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|---------------|-------------|-----------------------------| -| add | (e1,e2) | () | (UInt,UInt) | UInt | max(w~e1~,w~e2~)+1 | -| | | | (SInt,SInt) | SInt | max(w~e1~,w~e2~)+1 | -| | | | (Fixed,Fixed) | Fixed | see [@sec:fixed-point-math] | - -The add operation result is the sum of e1 and e2 without loss of precision. - -## Subtract Operation - - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|---------------|-------------|-----------------------------| -| sub | (e1,e2) | () | (UInt,UInt) | UInt | max(w~e1~,w~e2~)+1 | -| | | | (SInt,SInt) | SInt | max(w~e1~,w~e2~)+1 | -| | | | (Fixed,Fixed) | Fixed | see [@sec:fixed-point-math] | - -The subtract operation result is e2 subtracted from e1, without loss of -precision. - -## Multiply Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|---------------|-------------|-----------------------------| -| mul | (e1,e2) | () | (UInt,UInt) | UInt | w~e1~+w~e2~ | -| | | | (SInt,SInt) | SInt | w~e1~+w~e2~ | -| | | | (Fixed,Fixed) | Fixed | see [@sec:fixed-point-math] | - -The multiply operation result is the product of e1 and e2, without loss of -precision. - -## Divide Operation - - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-------------|-------------|--------------| -| div | (num,den) | () | (UInt,UInt) | UInt | w~num~ | -| | | | (SInt,SInt) | SInt | w~num~+1 | - -The divide operation divides num by den, truncating the fractional portion of -the result. This is equivalent to rounding the result towards zero. The result -of a division where den is zero is undefined. - -## Modulus Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-------------|-------------|--------------------| -| rem | (num,den) | () | (UInt,UInt) | UInt | min(w~num~,w~den~) | -| | | | (SInt,SInt) | SInt | min(w~num~,w~den~) | - -The modulus operation yields the remainder from dividing num by den, keeping the -sign of the numerator. Together with the divide operator, the modulus operator -satisfies the relationship below: - - num = add(mul(den,div(num,den)),rem(num,den))} - -## Comparison Operations - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|--------|-----------|------------|---------------|-------------|--------------| -| lt,leq | | | (UInt,UInt) | UInt | 1 | -| gt,geq | (e1,e2) | () | (SInt,SInt) | UInt | 1 | -| eq,neq | | | (Fixed,Fixed) | UInt | 1 | - -The comparison operations return an unsigned 1 bit signal with value one if e1 -is less than (lt), less than or equal to (leq), greater than (gt), greater than -or equal to (geq), equal to (eq), or not equal to (neq) e2. The operation -returns a value of zero otherwise. - -## Padding Operations - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|-----------------------------| -| pad | \(e\) | \(n\) | (UInt) | UInt | max(w~e~,n) | -| | | | (SInt) | SInt | max(w~e~,n) | -| | | | (Fixed) | Fixed | see [@sec:fixed-point-math] | - - -If e's bit width is smaller than n, then the pad operation zero-extends or -sign-extends e up to the given width n. Otherwise, the result is simply e. n -must be non-negative. The binary point of fixed-point values is not affected by -padding. - -## Interpret As UInt - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|--------|-----------|------------|-----------|-------------|--------------| -| asUInt | \(e\) | () | (UInt) | UInt | w~e~ | -| | | | (SInt) | UInt | w~e~ | -| | | | (Fixed) | UInt | w~e~ | -| | | | (Clock) | UInt | 1 | - -The interpret as UInt operation reinterprets e's bits as an unsigned integer. - -## Interpret As SInt - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|--------|-----------|------------|-----------|-------------|--------------| -| asSInt | \(e\) | () | (UInt) | SInt | w~e~ | -| | | | (SInt) | SInt | w~e~ | -| | | | (Fixed) | SInt | w~e~ | -| | | | (Clock) | SInt | 1 | - -The interpret as SInt operation reinterprets e's bits as a signed integer -according to two's complement representation. - -## Interpret As Fixed-Point Number - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | Result Binary Point | -|---------|-----------|------------|-----------|-------------|--------------|---------------------| -| asFixed | \(e\) | \(p\) | (UInt) | Fixed | w~e~ | p | -| | | | (SInt) | Fixed | w~e~ | p | -| | | | (Fixed) | Fixed | w~e~ | p | -| | | | (Clock) | Fixed | 1 | p | - -The interpret as fixed-point operation reinterprets e's bits as a fixed-point -number of identical width. Since all fixed-point number in FIRRTL are signed, -the bits are taken to mean a signed value according to two's complement -representation. They are scaled by the provided binary point p, and the result -type has binary point p. - -## Interpret as Clock - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|---------|-----------|------------|-----------|-------------|--------------| -| asClock | \(e\) | () | (UInt) | Clock | n/a | -| | | | (SInt) | Clock | n/a | -| | | | (Fixed) | Clock | n/a | -| | | | (Clock) | Clock | n/a | - -The result of the interpret as clock operation is the Clock typed signal -obtained from interpreting a single bit integer as a clock signal. - -## Shift Left Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|-----------------------------| -| shl | \(e\) | \(n\) | (UInt) | UInt | w~e~+n | -| | | | (SInt) | SInt | w~e~+n | -| | | | (Fixed) | Fixed | see [@sec:fixed-point-math] | - -The shift left operation concatenates n zero bits to the least significant end -of e. n must be non-negative. - -## Shift Right Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|-----------------------------| -| shr | \(e\) | \(n\) | (UInt) | UInt | max(w~e~-n, 1) | -| | | | (SInt) | SInt | max(w~e~-n, 1) | -| | | | (Fixed) | Fixed | see [@sec:fixed-point-math] | - -The shift right operation truncates the least significant n bits from e. If n -is greater than or equal to the bit-width of e, the resulting value will be zero -for unsigned types and the sign bit for signed types. n must be non-negative. - -## Dynamic Shift Left Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|---------------|-------------|-----------------------------| -| dshl | (e1, e2) | () | (UInt, UInt) | UInt | w~e1~ + 2`^`w~e2~ - 1 | -| | | | (SInt, UInt) | SInt | w~e1~ + 2`^`w~e2~ - 1 | -| | | | (Fixed, UInt) | Fixed | see [@sec:fixed-point-math] | - -The dynamic shift left operation shifts the bits in e1 e2 places towards the -most significant bit. e2 zeroes are shifted in to the least significant bits. - -## Dynamic Shift Right Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|---------------|-------------|-----------------------------| -| dshr | (e1, e2) | () | (UInt, UInt) | UInt | w~e1~ | -| | | | (SInt, UInt) | SInt | w~e1~ | -| | | | (Fixed, UInt) | Fixed | see [@sec:fixed-point-math] | - -The dynamic shift right operation shifts the bits in e1 e2 places towards the -least significant bit. e2 signed or zeroed bits are shifted in to the most -significant bits, and the e2 least significant bits are truncated. - -## Arithmetic Convert to Signed Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| cvt | \(e\) | () | (UInt) | SInt | w~e~+1 | -| | | | (SInt) | SInt | w~e~ | - -The result of the arithmetic convert to signed operation is a signed integer -representing the same numerical value as e. - -## Negate Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| neg | \(e\) | () | (UInt) | SInt | w~e~+1 | -| | | | (SInt) | SInt | w~e~+1 | - -The result of the negate operation is a signed integer representing the negated -numerical value of e. - -## Bitwise Complement Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| not | \(e\) | () | (UInt) | UInt | w~e~ | -| | | | (SInt) | UInt | w~e~ | - -The bitwise complement operation performs a logical not on each bit in e. - -## Binary Bitwise Operations - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------------|-----------|------------|-------------|-------------|------------------| -| and,or,xor | (e1, e2) | () | (UInt,UInt) | UInt | max(w~e1~,w~e2~) | -| | | | (SInt,SInt) | UInt | max(w~e1~,w~e2~) | - -The above bitwise operations perform a bitwise and, or, or exclusive or on e1 -and e2. The result has the same width as its widest argument, and any narrower -arguments are automatically zero-extended or sign-extended to match the width of -the result before performing the operation. - -## Bitwise Reduction Operations - - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|---------------|-----------|------------|-----------|-------------|--------------| -| andr,orr,xorr | \(e\) | () | (UInt) | UInt | 1 | -| | | | (SInt) | UInt | 1 | - -The bitwise reduction operations correspond to a bitwise and, or, and exclusive -or operation, reduced over every bit in e. - -In all cases, the reduction incorporates as an inductive base case the "identity -value" associated with each operator. This is defined as the value that -preserves the value of the other argument: one for and (as $x \wedge 1 = x$), -zero for or (as $x \vee 0 = x$), and zero for xor (as $x \oplus 0 = x$). Note -that the logical consequence is that the and-reduction of a zero-width -expression returns a one, while the or- and xor-reductions of a zero-width -expression both return zero. - -## Concatenate Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|----------------|-------------|--------------| -| cat | (e1,e2) | () | (UInt, UInt) | UInt | w~e1~+w~e2~ | -| | | | (SInt, SInt) | UInt | w~e1~+w~e2~ | -| | | | (Fixed, Fixed) | UInt | w~e1~+w~e2~ | - -The result of the concatenate operation is the bits of e1 concatenated to the -most significant end of the bits of e2. - -## Bit Extraction Operation - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| bits | \(e\) | (hi,lo) | (UInt) | UInt | hi-lo+1 | -| | | | (SInt) | UInt | hi-lo+1 | -| | | | (Fixed) | UInt | hi-lo+1 | - -The result of the bit extraction operation are the bits of e between lo -(inclusive) and hi (inclusive). hi must be greater than or equal to lo. Both hi -and lo must be non-negative and strictly less than the bit width of e. - -## Head - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| head | \(e\) | \(n\) | (UInt) | UInt | n | -| | | | (SInt) | UInt | n | -| | | | (Fixed) | UInt | n | - -The result of the head operation are the n most significant bits of e. n must be -non-negative and less than or equal to the bit width of e. - -## Tail - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------|-----------|------------|-----------|-------------|--------------| -| tail | \(e\) | \(n\) | (UInt) | UInt | w~e~-n | -| | | | (SInt) | UInt | w~e~-n | -| | | | (Fixed) | UInt | w~e~-n | - -The tail operation truncates the n most significant bits from e. n must be -non-negative and less than or equal to the bit width of e. - -## Fixed-Point Precision Modification Operations - -| Name | Arguments | Parmaeters | Arg Types | Result Type | Result Width | -|------------------|-----------|------------|-----------|-------------|--------------| -| incp, decp, setp | \(e\) | \(n\) | (Fixed) | Fixed | | - -The increase precision, decrease precision, and set precision operations are -used to alter the number of bits that appear after the binary point in a -fixed-point number. This will cause the binary point and consequently the total -width of the fixed-point result type to differ from those of the fixed-point -argument type. See [@sec:fixed-point-math] for more detail. - -# Flows - -An expression's flow partially determines the legality of connecting to and from -the expression. Every expression is classified as either *source*, *sink*, or -*duplex*. For details on connection rules refer back to [@sec:connects; -@sec:partial-connects]. - -The flow of a reference to a declared circuit component depends on the kind of -circuit component. A reference to an input port, an instance, a memory, and a -node, is a source. A reference to an output port is a sink. A reference to a -wire or register is duplex. - -The flow of a sub-index or sub-access expression is the flow of the vector-typed -expression it indexes or accesses. - -The flow of a sub-field expression depends upon the orientation of the field. If -the field is not flipped, its flow is the same flow as the bundle-typed -expression it selects its field from. If the field is flipped, then its flow is -the reverse of the flow of the bundle-typed expression it selects its field -from. The reverse of source is sink, and vice-versa. The reverse of duplex -remains duplex. - -The flow of all other expressions are source. - -# Width Inference - -For all circuit components declared with unspecified widths, the FIRRTL compiler -will infer the minimum possible width that maintains the legality of all its -incoming connections. If a component has no incoming connections, and the width -is unspecified, then an error is thrown to indicate that the width could not be -inferred. - -For module input ports with unspecified widths, the inferred width is the -minimum possible width that maintains the legality of all incoming connections -to all instantiations of the module. - -The width of a ground-typed multiplexer expression is the maximum of its two -corresponding input widths. For multiplexing aggregate-typed expressions, the -resulting widths of each leaf sub-element is the maximum of its corresponding -two input leaf sub-element widths. - -The width of a conditionally valid expression is the width of its input -expression. - -The width of each primitive operation is detailed in [@sec:primitive-operations]. - -The width of the integer literal expressions is detailed in their respective -sections. - -# Fixed-Point Math - -| Operator | Result Width | Result Binary Point | -|-------------|-------------------------------------------------------|---------------------| -| add(e1, e2) | max(w~e1~-p~e1~, w~e2~-p~e2~) + max(p~e1~, p~e2~) + 1 | max(p~e1~, p~e2~) | -| mul(e1, e2) | w~1~ + w~2~ | p~1~ + p~2~ | - -: Propagation rules for binary primitive operators that operate on two - fixed-point numbers. Here, w~e1~ and p~e1~ are used to indicate the width and - binary point of the first operand, while w~e2~ and p~e2~ are used to indicate - the width and binary point of the second operand. - - -| Operator | Result Width | Result Binary Point | -|------------|-----------------------------|---------------------| -| pad(e, n) | max(w~e~, n) | p~e~ | -| shl(e, n) | w~e~ + n | p~e~ | -| shr(e, n) | max(w~e~ - n, max(1, p~e~)) | p~e~ | -| incp(e, n) | w~e~ + n | p~e~ + n | -| decp(e, n) | w~e~ - n | p~e~ - n | -| setp(e, n) | w~e~ - p~e~ + n | n | - -: Propagation rules for binary primitive operators that modify the width and/or - precision of a single fixed-point number using a constant integer literal - parameter. Here, w~e~ and p~e~ are used to indicate the width and binary point - of the fixed-point operand, while `n` is used to represent the value of the - constant parameter. - -| Operator | Result Width | Result Binary Point | -|--------------|-----------------------|---------------------| -| dshl(e1, e1) | w~e1~ + 2`^`w~e2~ - 1 | p~e~ | -| dshr(e1, e2) | w~e1~ | p~e~ | - -: Propagation rules for dynamic shifts on fixed-point numbers. These take a - fixed-point argument and an UInt argument. Here, w~e1~ and p~e1~ are used to - indicate the width and binary point of the fixed-point operand, while w~e1~ is - used to represent the width of the unsigned integer operand. Note that the - actual shift amount will be the dynamic value of the `e2` argument. - -# Namespaces - -All modules in a circuit exist in the same module namespace, and thus must all -have a unique name. - -Each module has an identifier namespace containing the names of all port and -circuit component declarations. Thus, all declarations within a module must have -unique names. Furthermore, the set of component declarations within a module -must be *prefix unique*. Please see [@sec:prefix-uniqueness] for the definition -of prefix uniqueness. - -Within a bundle type declaration, all field names must be unique. - -Within a memory declaration, all port names must be unique. - -During the lowering transformation, all circuit component declarations with -aggregate types are rewritten as a group of component declarations, each with a -ground type. The name expansion algorithm in [@sec:name-expansion-algorithm] -calculates the names of all replacement components derived from the original -aggregate-typed component. - -After the lowering transformation, the names of the lowered circuit components -are guaranteed by the name expansion algorithm and thus can be reliably -referenced by users to pair meta-data or other annotations with named circuit -components. - -## Name Expansion Algorithm - -Given a component with a ground type, the name of the component is returned. - -Given a component with a vector type, the suffix `$`*i* is appended to the -expanded names of each sub-element, where *i* is the index of each sub-element. - -Given a component with a bundle type, the suffix `$`*f* is appended to the -expanded names of each sub-element, where *f* is the field name of each -sub-element. - -## Prefix Uniqueness - -The *symbol sequence* of a name is the ordered list of strings that results from -splitting the name at each occurrence of the '\$' character. - -A symbol sequence $a$ is a *prefix* of another symbol sequence $b$ if the -strings in $a$ occur in the beginning of $b$. - -A set of names are defined to be *prefix unique* if there exists no two names -such that the symbol sequence of one is a prefix of the symbol sequence of the -other. - -As an example `firetruck$y$z`{.firrtl} shares a prefix with -`firetruck$y`{.firrtl} and `firetruck`{.firrtl}, but does not share a prefix -with `fire`{.firrtl}. - -# The Lowered FIRRTL Forms - -The lowered FIRRTL forms, MidFIRRTL and LoFIRRTL, are increasingly restrictive -subsets of the FIRRTL language that omit many of the higher level -constructs. All conforming FIRRTL compilers must provide a *lowering -transformation* that transforms arbitrary FIRRTL circuits into equivalent -LoFIRRTL circuits. However, there are no additional requirements related to -accepting or producing MidFIRRTL, as the LoFIRRTL output of the lowering -transformation will already be a legal subset of MidFIRRTL. - -## MidFIRRTL - -A FIRRTL circuit is defined to be a valid MidFIRRTL circuit if it obeys the -following restrictions: - -- All widths must be explicitly defined. - -- The conditional statement is not used. - -- The dynamic sub-access expression is not used. - -- All components are connected to exactly once. - -## LoFIRRTL - -A FIRRTL circuit is defined to be a valid LoFIRRTL circuit if it obeys the -following restrictions: - -- All widths must be explicitly defined. - -- The conditional statement is not used. - -- All components are connected to exactly once. - -- All components must be declared with a ground type. - -- The partial connect statement is not used. - -The first three restrictions follow from the fact that any LoFIRRTL circuit is -also a legal MidFIRRTL circuit. The additional restrictions give LoFIRRTL a -direct correspondence to a circuit netlist. - -Low level circuit transformations can be conveniently written by first lowering -a circuit to its LoFIRRTL form, then operating on the restricted (and thus -simpler) subset of constructs. Note that circuit transformations are still free -to generate high level constructs as they can simply be lowered again. - -The following module: - -``` firrtl -module MyModule : - input in: {a: UInt<1>, b: UInt<2>[3]} - input clk: Clock - output out: UInt - wire c: UInt - c <= in.a - reg r: UInt[3], clk - r <= in.b - when c : - r[1] <= in.a - out <= r[0] -``` - -is rewritten as the following equivalent LoFIRRTL circuit by the lowering -transform. - -``` firrtl -module MyModule : - input in$a: UInt<1> - input in$b$0: UInt<2> - input in$b$1: UInt<2> - input in$b$2: UInt<2> - input clk: Clock - output out: UInt<2> - wire c: UInt<1> - c <= in$a - reg r$0: UInt<2>, clk - reg r$1: UInt<2>, clk - reg r$2: UInt<2>, clk - r$0 <= in$b$0 - r$1 <= mux(c, in$a, in$b$1) - r$2 <= in$b$2 - out <= r$0 -``` - -# Details about Syntax - -FIRRTL's syntax is designed to be human-readable but easily algorithmically -parsed. - -The following characters are allowed in identifiers: upper and lower case -letters, digits, and `_`{.firrtl}. Identifiers cannot begin with a digit. - -An integer literal in FIRRTL begins with one of the following, where '\#' -represents a digit between 0 and 9. - -- 'h' : For indicating a hexadecimal number, followed by an optional sign. The - rest of the literal must consist of either digits or a letter between 'A' and - 'F'. - -- 'o' : For indicating an octal number, followed by an optional sign. The rest - of the literal must consist of digits between 0 and 7. - -- 'b' : For indicating a binary number, followed by an optional sign. The rest - of the literal must consist of digits that are either 0 or 1. - -- '-\#' : For indicating a negative decimal number. The rest of the literal must - consist of digits between 0 and 9. - -- '\#' : For indicating a positive decimal number. The rest of the literal must - consist of digits between 0 and 9. - -Comments begin with a semicolon and extend until the end of the line. Commas -are treated as whitespace, and may be used by the user for clarity if desired. - -In FIRRTL, indentation is significant. Indentation must consist of spaces -only---tabs are illegal characters. The number of spaces appearing before a -FIRRTL IR statement is used to establish its *indent level*. Statements with the -same indent level have the same context. The indent level of the -`circuit`{.firrtl} declaration must be zero. - -Certain constructs (`circuit`{.firrtl}, `module`{.firrtl}, `when`{.firrtl}, and -`else`{.firrtl}) create a new sub-context. The indent used on the first line of -the sub-context establishes the indent level. The indent level of a sub-context -is one higher than the parent. All statements in the sub-context must be -indented by the same number of spaces. To end the sub-context, a line must -return to the indent level of the parent. - -Since conditional statements (`when`{.firrtl} and `else`{.firrtl}) may be -nested, it is possible to create a hierarchy of indent levels, each with its own -number of preceding spaces that must be larger than its parent's and consistent -among all direct child statements (those that are not children of an even deeper -conditional statement). - -As a concrete guide, a few consequences of these rules are summarized below: - -- The `circuit`{.firrtl} keyword must not be indented. - -- All `module`{.firrtl} keywords must be indented by the same number of spaces. - -- In a module, all port declarations and all statements (that are not children - of other statements) must be indented by the same number of spaces. - -- The number of spaces comprising the indent level of a module is specific to - each module. - -- The statements comprising a conditional statement's branch must be indented by - the same number of spaces. - -- The statements of nested conditional statements establish their own, deeper - indent level. - -- Each `when`{.firrtl} and each `else`{.firrtl} context may have a different - number of non-zero spaces in its indent level. - -As an example illustrating some of these points, the following is a legal FIRRTL -circuit: - -``` firrtl -circuit Foo : - module Foo : - skip - module Bar : - input a: UInt<1> - output b: UInt<1> - when a: - b <= a - else: - b <= not(a) -``` - -All circuits, modules, ports and statements can optionally be followed with the -info token `@[fileinfo]` where fileinfo is a string containing the source file -information from where it was generated. The following characters need to be -escaped with a leading '`\`': '`\n`' (new line), '`\t`' (tab), '`]`' and '`\`' -itself. - -The following example shows the info tokens included: - -``` firrtl -circuit Top : @[myfile.txt 14:8] - module Top : @[myfile.txt 15:2] - output out: UInt @[myfile.txt 16:3] - input b: UInt<32> @[myfile.txt 17:3] - input c: UInt<1> @[myfile.txt 18:3] - input d: UInt<16> @[myfile.txt 19:3] - wire a: UInt @[myfile.txt 21:8] - when c : @[myfile.txt 24:8] - a <= b @[myfile.txt 27:16] - else : - a <= d @[myfile.txt 29:17] - out <= add(a,a) @[myfile.txt 34:4] -``` - -\pagebreak - -# FIRRTL Language Definition - -``` ebnf -(* Whitespace definitions *) -indent = " " , { " " } ; -dedent = ? remove one level of indentation ? ; -newline = ? a newline character ? ; - -(* Integer literal definitions *) -digit_bin = "0" | "1" ; -digit_oct = digit_bin | "2" | "3" | "4" | "5" | "6" | "7" ; -digit_dec = digit_oct | "8" | "9" ; -digit_hex = digit_dec - | "A" | "B" | "C" | "D" | "E" | "F" - | "a" | "b" | "c" | "d" | "e" | "f" ; -(* An integer *) -int = '"' , "b" , [ "-" ] , { digit_bin } , '"' - | '"' , "o" , [ "-" ] , { digit_oct } , '"' - | '"' , "h" , [ "-" ] , { digit_hex } , '"' - | [ "-" ] , { digit_bin } ; - -(* Identifiers define legal FIRRTL or Verilog names *) -letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" - | "H" | "I" | "J" | "K" | "L" | "M" | "N" - | "O" | "P" | "Q" | "R" | "S" | "T" | "U" - | "V" | "W" | "X" | "Y" | "Z" - | "a" | "b" | "c" | "d" | "e" | "f" | "g" - | "h" | "i" | "j" | "k" | "l" | "m" | "n" - | "o" | "p" | "q" | "r" | "s" | "t" | "u" - | "v" | "w" | "x" | "y" | "z" ; -id = ( "_" | letter ) , { "_" | letter | digit_dec } ; - -(* Fileinfo communicates Chisel source file and line/column info *) -linecol = digit_dec , { digit_dec } , ":" , digit_dec , { digit_dec } ; -info = "@" , "[" , { string , " " , linecol } , "]" ; - -(* Type definitions *) -width = "<" , int , ">" ; -binarypoint = "<<" , int , ">>" ; -type_ground = "Clock" - | ( "UInt" | "SInt" | "Analog" ) , [ width ] - | "Fixed" , [ width ] , [ binarypoint ] ; -type_aggregate = "{" , field , { field } , "}" - | type , "[" , int , "]" ; -field = [ "flip" ] , id , ":" , type ; -type = type_ground | type_aggregate ; - -(* Primitive operations *) -primop_2expr_keyword = - "add" | "sub" | "mul" | "div" | "mod" - | "lt" | "leq" | "gt" | "geq" | "eq" | "neq" - | "dshl" | "dshr" - | "and" | "or" | "xor" | "cat" ; -primop_2expr = - primop_2expr_keyword , "(" , expr , "," , expr ")" ; -primop_1expr_keyword = - "asUInt" | "asSInt" | "asClock" | "cvt" - | "neg" | "not" - | "andr" | "orr" | "xorr" - | "head" | "tail" ; -primop_1expr = - primop_1expr_keyword , "(" , expr , ")" ; -primop_1expr1int_keyword = - "pad" | "shl" | "shr" ; -primop_1expr1int = - primop_1exrp1int_keywork , "(", expr , "," , int , ")" ; -primop_1expr2int_keyword = - "bits" ; -primop_1expr2int = - primop_1expr2int_keywork , "(" , expr , "," , int , "," , int , ")" ; -primop = primop_2expr | primop_1expr | primop_1expr1int | primop_1expr2int ; - -(* Expression definitions *) -expr = - ( "UInt" | "SInt" ) , [ width ] , "(" , ( int ) , ")" - | reference - | "mux" , "(" , expr , "," , expr , "," , expr , ")" - | "validif" , "(" , expr , "," , expr , ")" - | primop ; -reference = id - | reference , "." , id - | reference , "[" , int , "]" - | reference , "[" , expr , "]" ; - -(* Memory *) -ruw = ( "old" | "new" | "undefined" ) ; -memory = "mem" , id , ":" , [ info ] , newline , indent , - "data-type" , "=>" , type , newline , - "depth" , "=>" , int , newline , - "read-latency" , "=>" , int , newline , - "write-latency" , "=>" , int , newline , - "read-under-write" , "=>" , ruw , newline , - { "reader" , "=>" , id , newline } , - { "writer" , "=>" , id , newline } , - { "readwriter" , "=>" , id , newline } , - dedent ; - -(* Statements *) -statement = "wire" , id , ":" , type , [ info ] - | "reg" , id , ":" , type , expr , - [ "(with: {reset => (" , expr , "," , expr ")})" ] , [ info ] - | memory - | "inst" , id , "of" , id , [ info ] - | "node" , id , "=" , expr , [ info ] - | reference , "<=" , expr , [ info ] - | reference , "<-" , expr , [ info ] - | reference , "is invalid" , [ info ] - | "attach(" , { reference } , ")" , [ info ] - | "when" , expr , ":" [ info ] , newline , indent , - { statement } , - dedent , [ "else" , ":" , indent , { statement } , dedent ] - | "stop(" , expr , "," , expr , "," , int , ")" , [ info ] - | "printf(" , expr , "," , expr , "," , string , - { expr } , ")" , [ ":" , id ] , [ info ] - | "skip" , [ info ] ; - -(* Module definitions *) -port = ( "input" | "output" ) , id , ":": , type , [ info ] ; -module = "module" , id , ":" , [ info ] , newline , indent , - { port , newline } , - { statement , newline } , - dedent ; -extmodule = "extmodule" , id , ":" , [ info ] , newline , indent , - { port , newline } , - [ "defname" , "=" , id , newline ] , - { "parameter" , "=" , ( string | int ) , newline } , - dedent ; - -(* Circuit definition *) -circuit = "circuit" , id , ":" , [ info ] , newline , indent , - { module | extmodule } , - dedent ; -``` diff --git a/spec/spec.pdf b/spec/spec.pdf Binary files differdeleted file mode 100644 index c3485b63..00000000 --- a/spec/spec.pdf +++ /dev/null |
