diff options
| author | Schuyler Eldridge | 2019-09-16 19:03:37 -0400 |
|---|---|---|
| committer | GitHub | 2019-09-16 19:03:37 -0400 |
| commit | f93e1d240f80848dc12c25906239fe6c8a4d42b5 (patch) | |
| tree | 9b39634fc4bd5044e37939a0bd568ae4ed158826 | |
| parent | 7e39ea8ec948ff1db7ccd0d850923a86d2d8a4e7 (diff) | |
| parent | b3dd7924f27342083681be6dd5932ef95d354029 (diff) | |
Merge pull request #1124 from freechipsproject/gender-to-flow
Gender to Flow
48 files changed, 610 insertions, 518 deletions
diff --git a/spec/spec.pdf b/spec/spec.pdf Binary files differindex 9242011e..db755eef 100644 --- a/spec/spec.pdf +++ b/spec/spec.pdf diff --git a/spec/spec.tex b/spec/spec.tex index 8685de45..12d86e35 100644 --- a/spec/spec.tex +++ b/spec/spec.tex @@ -17,7 +17,7 @@ \title{Specification for the FIRRTL Language} \author{Patrick S. Li \\ \href{mailto:psli@eecs.berkeley.edu}{psli@eecs.berkeley.edu} - \and Adam M. Izraelevitz \\ \href{mailto:adamiz@eecs.berkeley.edu}{adamiz@eecs.berkeley.edu} + \and Adam M. Izraelevitz \\ \href{mailto:adamiz@eecs.berkeley.edu}{adamiz@eecs.berkeley.edu} \and Jonathan Bachrach \\ \href{mailto:jrb@eecs.berkeley.edu}{jrb@eecs.berkeley.edu} } \documentclass[12pt]{article} \usepackage{listings} @@ -29,7 +29,7 @@ \hypersetup{ colorlinks=true, linkcolor=blue, - filecolor=magenta, + filecolor=magenta, urlcolor=cyan, } \usepackage[pdftex]{graphicx} @@ -64,7 +64,7 @@ \subsection{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. +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. \begin{enumerate}[topsep=3pt,itemsep=-0.5ex,partopsep=1ex,parsep=1ex] @@ -76,7 +76,7 @@ Internally, the investment in developing and learning Chisel was rewarded with h \item The output of Chisel (Verilog) is unreadable and slow to simulate. \end{enumerate} -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. +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. \subsection{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. @@ -117,11 +117,11 @@ circuit MyTop : module MyTop : ... module MyModule : - ... -\end{lstlisting} + ... +\end{lstlisting} \subsection{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 \pd{direction}, which may be input or output, a name, and the data type of the port. +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 \pd{direction}, 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 section \ref{connects} for details on the connect statement. @@ -130,7 +130,7 @@ module MyModule : input foo: UInt output bar: UInt bar <= foo -\end{lstlisting} +\end{lstlisting} Note that a module definition does {\em 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 (section \ref{instances}). @@ -142,7 +142,7 @@ extmodule MyExternalModule : input foo: UInt output bar: UInt output baz: SInt -\end{lstlisting} +\end{lstlisting} % The following example is the port declaration of a module that spans two clock domains. @@ -158,7 +158,7 @@ extmodule MyExternalModule : \section{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. +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. \subsection{Ground Types} @@ -171,32 +171,32 @@ Both unsigned and signed integer types may optionally be given a known positive \begin{lstlisting} UInt<10> SInt<32> -\end{lstlisting} +\end{lstlisting} Alternatively, if the bit width is omitted, it will be automatically inferred by FIRRTL's width inferencer, as detailed in section \ref{width_inference}. \begin{lstlisting} UInt SInt -\end{lstlisting} +\end{lstlisting} \subsubsection{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 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: \begin{lstlisting} Clock -\end{lstlisting} +\end{lstlisting} \subsection{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. +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. \begin{lstlisting} UInt<16>[10] -\end{lstlisting} +\end{lstlisting} The next example specifies a ten element vector of unsigned integers of omitted but identical bit widths. \begin{lstlisting} @@ -206,11 +206,11 @@ 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. \begin{lstlisting} UInt<16>[10][20] -\end{lstlisting} +\end{lstlisting} \subsection{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. +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, \verb|real|, and \verb|imag|, both 10-bit signed integers. \begin{lstlisting} @@ -229,7 +229,7 @@ output a: {word:UInt<32>, valid:UInt<1>, flip ready:UInt<1>} \end{lstlisting} In a connection to the \verb|a| port, the data carried by the \verb|word| and \verb|valid| subfields will flow out of the module, while data carried by the \verb|ready| subfield will flow into the module. More details about how the bundle field orientation affects connections are explained in section \ref{connects}. -As in the case of vector types, a bundle field may be declared with any type, including other aggregate types. +As in the case of vector types, a bundle field may be declared with any type, including other aggregate types. \begin{lstlisting} {real: {word:UInt<32>, valid:UInt<1>, flip ready:UInt<1>} imag: {word:UInt<32>, valid:UInt<1>, flip ready:UInt<1>}} @@ -251,7 +251,7 @@ Intuitively, a passive type is a type where all data flows in the same direction The type equivalence relation is used to determine whether a connection between two components is legal. See section \ref{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. +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. Clock types are equivalent to clock types, and are not equivalent to any other type. @@ -273,9 +273,9 @@ An oriented ground type is an orientation coupled with a ground type. An oriente 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. \subsubsection{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 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 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. @@ -308,30 +308,30 @@ In order for a connection to be legal the following conditions must hold: \begin{enumerate} \item The types of the left-hand and right-hand side expressions must be equivalent (see section \ref{type_equivalence} for details). \item 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. -\item The gender of the left-hand side expression must be female or bi-gender (see section \ref{genders} for an explanation of gender). -\item Either the gender of the right-hand side expression is male or bi-gender, or the right-hand side expression has a passive type. +\item The flow of the left-hand side expression must be sink or duplex (see section \ref{flows} for an explanation of flow). +\item Either the flow of the right-hand side expression is source or duplex, or the right-hand side expression has a passive type. \end{enumerate} 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 section \ref{connection_algorithm}. \subsubsection{The Connection Algorithm} \label{connection_algorithm} -Connect statements between ground types cannot be expanded further. +Connect statements between ground types cannot be expanded further. -Connect statements between two vector typed components recursively connects each subelement in the right-hand side expression to the corresponding subelement in the left-hand side expression. +Connect statements between two vector typed components recursively connects each subelement in the right-hand side expression to the corresponding subelement 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. \subsection{Partial Connects}\label{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. +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: \begin{enumerate} \item The types of the left-hand and right-hand side expressions must be weakly equivalent (see section \ref{weak_type_equivalence} for details). -\item The gender of the left-hand side expression must be female or bi-gender (see section \ref{genders} for an explanation of gender). -\item Either the gender of the right-hand side expression is male or bi-gender, or the right-hand side expression has a passive type. +\item The flow of the left-hand side expression must be sink or duplex (see section \ref{flow} for an explanation of flow). +\item Either the flow of the right-hand side expression is source or duplex, or the right-hand side expression has a passive type. \end{enumerate} -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. +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 subelements are ignored. The full algorithm is detailed in section \ref{partial_connection_algorithm}. @@ -356,11 +356,11 @@ For details on the syntax and semantics of the subfield expression, subindex exp \subsubsection{The Partial Connection Algorithm} \label{partial_connection_algorithm} -A partial connect statement between two ground type components connects the right-hand side expression to the left-hand side expression. Conversely, a {\em reverse} partial connect statement between two ground type components connects the left-hand side expression to the right-hand side expression. +A partial connect statement between two ground type components connects the right-hand side expression to the left-hand side expression. Conversely, a {\em reverse} partial connect statement between two ground type components connects the left-hand side expression to the right-hand side expression. -A partial (or reverse partial) connect statement between two vector typed components applies a partial (or reverse partial) connect from the first n subelements in the right-hand side expression to the first n corresponding subelements in the left-hand side expression, where n is the length of the shorter vector. +A partial (or reverse partial) connect statement between two vector typed components applies a partial (or reverse partial) connect from the first n subelements in the right-hand side expression to the first n corresponding subelements 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. +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. \subsection{Statement Groups} \label{statement_groups} @@ -378,7 +378,7 @@ module MyModule : \end{lstlisting} \subsubsection{Last Connect Semantics}\label{last_connect} -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 \verb|b| will be connected to \verb|myport1|, and port \verb|a| will be connected to \verb|myport2|. +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 \verb|b| will be connected to \verb|myport1|, and port \verb|a| will be connected to \verb|myport2|. 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 section \ref{conditional_last_connect}. @@ -451,7 +451,7 @@ wire mywire : UInt \subsection{Registers} A register is a named stateful circuit component. -The following example demonstrates instantiating a register with the given name \verb|myreg|, type \verb|SInt|, and is driven by the clock signal \verb|myclock|. +The following example demonstrates instantiating a register with the given name \verb|myreg|, type \verb|SInt|, and is driven by the clock signal \verb|myclock|. \begin{lstlisting} wire myclock: Clock @@ -507,7 +507,7 @@ module MyModule : 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. \subsubsection{The Invalidate Algorithm}\label{invalidate_algorithm} -Invalidating a component with a ground type indicates that the component's value is indetermined if the component is female or bi-gender (see section \ref{genders}). Otherwise, the component is unaffected. +Invalidating a component with a ground type indicates that the component's value is indetermined if the component has sink or duplex flow (see section \ref{flows}). Otherwise, the component is unaffected. Invalidating a component with a vector type recursively invalidates each subelement in the vector. @@ -529,7 +529,7 @@ node mynode = mux(pred, a, b) \subsection{Conditionals}\label{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 \verb|x| is connected to the input \verb|a| only when the \verb|en| signal is high. Otherwise, the wire \verb|x| is connected to the input \verb|b|. +In the following example, the wire \verb|x| is connected to the input \verb|a| only when the \verb|en| signal is high. Otherwise, the wire \verb|x| is connected to the input \verb|b|. \begin{lstlisting} module MyModule : @@ -540,7 +540,7 @@ module MyModule : when en : x <= a else : - x <= b + x <= b \end{lstlisting} \subsubsection{Syntactic Shorthands} @@ -568,8 +568,8 @@ module MyModule : wire x: UInt when en : x <= a - else : - skip + else : + skip \end{lstlisting} To aid readability of long chains of conditional statements, the colon following the \verb|else| keyword may be omitted if the \verb|else| branch consists of a single conditional statement. @@ -593,9 +593,9 @@ module MyModule : x <= b else : when c3 : - x <= c + x <= c else : - x <= d + x <= d \end{lstlisting} can be equivalently written as: @@ -615,9 +615,9 @@ module MyModule : else when c2 : x <= b else when c3 : - x <= c + x <= c else : - x <= d + x <= d \end{lstlisting} \subsubsection{Nested Declarations} @@ -646,7 +646,7 @@ In the following example, the wire \verb|a| is connected to the wire \verb|w| wh \begin{lstlisting} module MyModule : - input en: UInt<1> + input en: UInt<1> input a: UInt wire w: UInt when en : @@ -670,7 +670,7 @@ wire w: UInt w <= a when c : w <= b -... +... \end{lstlisting} can be rewritten equivalently using a multiplexor as follows: \begin{lstlisting} @@ -690,7 +690,7 @@ wire w: UInt w is invalid when c : w <= a -... +... \end{lstlisting} can be rewritten equivalently as follows: \begin{lstlisting} @@ -712,7 +712,7 @@ wire w: {a:UInt, b:UInt} w <= x when c : w <= y -... +... \end{lstlisting} can be rewritten equivalently as follows: \begin{lstlisting} @@ -736,7 +736,7 @@ wire w: {a:UInt, b:UInt} w <= x when c : w.a <= y -... +... \end{lstlisting} can be rewritten equivalently as follows: \begin{lstlisting} @@ -775,18 +775,18 @@ mem mymem : In the example above, the type of \verb|mymem| is: \begin{lstlisting} -{flip r1: {flip data: {real:SInt<16>, imag:SInt<16>}, - addr: UInt<8>, - en: UInt<1>, +{flip r1: {flip data: {real:SInt<16>, imag:SInt<16>}, + addr: UInt<8>, + en: UInt<1>, clk: Clock} - flip r2: {flip data: {real:SInt<16>, imag:SInt<16>}, - addr: UInt<8>, - en: UInt<1>, + flip r2: {flip data: {real:SInt<16>, imag:SInt<16>}, + addr: UInt<8>, + en: UInt<1>, clk: Clock} - flip w: {data: {real:SInt<16>, imag:SInt<16>}, - mask: {real:UInt<1>, imag:UInt<1>}, - addr: UInt<8>, - en: UInt<1>, + flip w: {data: {real:SInt<16>, imag:SInt<16>}, + mask: {real:UInt<1>, imag:UInt<1>}, + addr: UInt<8>, + en: UInt<1>, clk: Clock}} \end{lstlisting} @@ -812,16 +812,16 @@ If the \verb|en| field is high, then the non-masked portion of the \verb|data| f \subsubsection{Readwrite Ports} Finally, the readwrite ports have type: \begin{lstlisting} -{wmode:UInt<1>, flip rdata:T, wdata:T, wmask:M, +{wmode:UInt<1>, flip rdata:T, wdata:T, wmask:M, addr:UInt<N>, en:UInt<1>, clk:Clock} \end{lstlisting} -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 \verb|wmode| field is low), then the \verb|rdata|, \verb|addr|, \verb|en|, and \verb|clk| fields constitute its read port fields, and should be used accordingly. If the readwrite port is in write mode (the \verb|wmode| field is high), then the \verb|wdata|, \verb|wmask|, \verb|addr|, \verb|en|, and \verb|clk| fields constitute its write port fields, and should be used accordingly. +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 \verb|wmode| field is low), then the \verb|rdata|, \verb|addr|, \verb|en|, and \verb|clk| fields constitute its read port fields, and should be used accordingly. If the readwrite port is in write mode (the \verb|wmode| field is high), then the \verb|wdata|, \verb|wmask|, \verb|addr|, \verb|en|, and \verb|clk| fields constitute its write port fields, and should be used accordingly. \subsubsection{Read Under Write Behaviour} The read-under-write flag indicates the value held on a read port's \verb|data| field if its memory location is written to while it is reading. The flag may take on three settings: \verb|old|, \verb|new|, and \verb|undefined|. -If the read-under-write flag is set to \verb|old|, then a read port always returns the value existing in the memory on the same cycle that the read was requested. +If the read-under-write flag is set to \verb|old|, 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. @@ -834,7 +834,7 @@ If the read-under-write flag is set to \verb|undefined|, then the value held by In all cases, if a memory location is written to by more than one port on the same cycle, the stored value is undefined. \subsection{Instances}\label{instances} -FIRRTL modules are instantiated with the instance statement. The following example demonstrates creating an instance named \verb|myinstance| of the \verb|MyModule| module within the top level module \verb|Top|. +FIRRTL modules are instantiated with the instance statement. The following example demonstrates creating an instance named \verb|myinstance| of the \verb|MyModule| module within the top level module \verb|Top|. \begin{lstlisting} circuit Top : @@ -843,14 +843,14 @@ circuit Top : output b: UInt b <= a module Top : - inst myinstance of MyModule + inst myinstance of MyModule \end{lstlisting} 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 \verb|myinstance| instance in the example above has type \verb|{flip a:UInt, b:UInt}|. Modules have the property that instances can always be {\em 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. +To disallow infinitely recursive hardware, modules cannot contain instances of itself, either directly, or indirectly through instances of other modules it instantiates. \subsection{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. @@ -901,11 +901,11 @@ Format strings support the following escape characters: \section{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 multiplexors and conditionally valid signals, and for performing primitive operations. +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 multiplexors and conditionally valid signals, and for performing primitive operations. \subsection{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. +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. \begin{lstlisting} UInt<10>(42) \end{lstlisting} @@ -917,7 +917,7 @@ UInt(42) \subsection{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. +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: \begin{enumerate} @@ -943,7 +943,7 @@ UInt<7>("hD") \subsection{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. +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. \begin{lstlisting} SInt<10>(-42) \end{lstlisting} @@ -985,7 +985,7 @@ In the rest of the document, for brevity, the names of components will be used t \subsection{Subfields}\label{subfields} The subfield expression refers to a subelement of an expression with a bundle type. -The following example connects the \verb|in| port to the \verb|a| subelement of the \verb|out| port. +The following example connects the \verb|in| port to the \verb|a| subelement of the \verb|out| port. \begin{lstlisting} module MyModule : input in: UInt @@ -996,7 +996,7 @@ module MyModule : \subsection{Subindices}\label{subindices} The subindex expression statically refers, by index, to a subelement 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 \verb|in| port to the fifth subelement of the \verb|out| port. +The following example connects the \verb|in| port to the fifth subelement of the \verb|out| port. \begin{lstlisting} module MyModule : input in: UInt @@ -1027,7 +1027,7 @@ module MyModule : else when eq(n, UInt(1)) : out <= in[1] else when eq(n, UInt(2)) : - out <= in[2] + out <= in[2] else : out is invalid \end{lstlisting} @@ -1049,7 +1049,7 @@ module MyModule : input in: UInt input default: UInt[3] input n: UInt<2> - output out: UInt[3] + output out: UInt[3] out <= default when eq(n, UInt(0)) : out[0] <= in @@ -1087,19 +1087,19 @@ module MyModule : 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 + out[1][1] <= in \end{lstlisting} \subsection{Multiplexors}\label{multiplexors} -A multiplexor outputs one of two input expressions depending on the value of an unsigned single bit selection signal. +A multiplexor outputs one of two input expressions depending on the value of an unsigned single bit selection signal. The following example connects to the \verb|c| port the result of selecting between the \verb|a| and \verb|b| ports. The \verb|a| port is selected when the \verb|sel| signal is high, otherwise the \verb|b| port is selected. \begin{lstlisting} module MyModule : input a: UInt input b: UInt - input sel: UInt<1> + input sel: UInt<1> output c: UInt c <= mux(sel, a, b) \end{lstlisting} @@ -1119,7 +1119,7 @@ The following example connects the \verb|a| port to the \verb|c| port when the \ \begin{lstlisting} module MyModule : input a: UInt - input valid: UInt<1> + input valid: UInt<1> output c: UInt c <= validif(valid, a) \end{lstlisting} @@ -1134,7 +1134,7 @@ Conditional statements can be equivalently expressed as multiplexors and conditi \subsection{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. +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: \begin{lstlisting} @@ -1159,13 +1159,13 @@ Section \ref{primitives} will describe the format and semantics of each primitiv \newcommand{\nf}[1]{\normalfont{\textbf{#1}}} \newcommand{\opheader}{ \hline - \multicolumn{1}{|c|}{\nf{Name}} + \multicolumn{1}{|c|}{\nf{Name}} & \multicolumn{1}{c|}{\nf{Arguments}} & \multicolumn{1}{c|}{\nf{Parameters}} & \multicolumn{1}{c|}{\nf{Arg Types}} & \multicolumn{1}{c|}{\nf{Result Type}} & \multicolumn{1}{c|}{\nf{Result Width}}\\ -\hline +\hline } 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. @@ -1177,8 +1177,8 @@ Notationally, the width of an argument \vv{e} is represented as \vv{w}\ts{e}. \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader add & (e1,e2) & () & (UInt,UInt) & UInt & max(w\ts{e1},w\ts{e2})+1\\ &&& (SInt,SInt) & SInt & max(w\ts{e1},w\ts{e2})+1\\ \hline @@ -1192,8 +1192,8 @@ The add operation result is the sum of \vv{e1} and \vv{e2} without loss of preci \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader sub & (e1,e2) & () & (UInt,UInt) & SInt & max(w\ts{e1},w\ts{e2})+1\\ &&& (SInt,SInt) & SInt & max(w\ts{e1},w\ts{e2})+1\\ \hline @@ -1207,8 +1207,8 @@ The subtract operation result is \vv{e2} subtracted from \vv{e1}, without loss o \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader mul & (e1,e2) & () & (UInt,UInt) & UInt & w\ts{e1}+w\ts{e2}\\ &&& (SInt,SInt) & SInt & w\ts{e1}+w\ts{e2}\\ \hline @@ -1222,8 +1222,8 @@ The multiply operation result is the product of \vv{e1} and \vv{e2}, without los \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader div & (num,den) & () & (UInt,UInt) & UInt & w\ts{num}\\ &&& (SInt,SInt) & SInt & w\ts{num}+1\\ \hline @@ -1237,8 +1237,8 @@ The divide operation divides \vv{num} by \vv{den}, truncating the fractional por \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader rem & (num,den) & () & (UInt,UInt) & UInt & min(w\ts{num},w\ts{den})\\ &&& (SInt,SInt) & SInt & min(w\ts{num},w\ts{den})\\ \hline @@ -1255,8 +1255,8 @@ num = add(mul(den,div(num,den)),rem(num,den))} \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader lt,leq,gt, & (e1,e2) & () & (UInt,UInt) & UInt & 1\\ geq,eq,neq &&& (SInt,SInt) & UInt & 1\\ \hline @@ -1270,8 +1270,8 @@ The comparison operations return an unsigned 1 bit signal with value one if \vv{ \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader pad & (e) & (n) & (UInt) & UInt & max(w\ts{e},n)\\ &&& (SInt) & SInt & max(w\ts{e},n)\\ \hline @@ -1286,8 +1286,8 @@ If \vv{e}'s bit width is smaller than \vv{n}, then the pad operation zero-extend \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader asUInt & (e) & () & (UInt) & UInt & w\ts{e}\\ &&& (SInt) & UInt & w\ts{e}\\ &&& (Clock) & UInt & 1\\ @@ -1303,8 +1303,8 @@ The interpret as UInt operation reinterprets \vv{e}'s bits as an unsigned intege \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader asSInt & (e) & () & (UInt) & SInt & w\ts{e}\\ &&& (SInt) & SInt & w\ts{e}\\ &&& (Clock) & SInt & 1\\ @@ -1320,25 +1320,25 @@ The interpret as SInt operation reinterprets \vv{e}'s bits as a signed integer a \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader asClock & (e) & () & (UInt) & Clock & n/a\\ &&& (SInt) & Clock & n/a\\ - &&& (Clock) & Clock & n/a\\ + &&& (Clock) & Clock & n/a\\ \hline \end{tabular} }} \end{figure} -The result of the interpret as clock operation is the Clock typed signal obtained from interpreting a single bit integer as a clock signal. +The result of the interpret as clock operation is the Clock typed signal obtained from interpreting a single bit integer as a clock signal. \subsection{Shift Left Operation} \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader shl & (e) & (n) & (UInt) & UInt & w\ts{e}+n\\ &&& (SInt) & SInt & w\ts{e}+n\\ \hline @@ -1371,8 +1371,8 @@ If \vv{n} is greater than or equal to the bit-width of \vv{e}, the resulting val \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader dshl & (e, n) & () & (UInt, UInt) & UInt & w\ts{e} + 2\verb|^|w\ts{n} - 1\\ &&& (SInt, UInt) & SInt & w\ts{e} + 2\verb|^|w\ts{n} - 1\\ \hline @@ -1387,8 +1387,8 @@ The dynamic shift left operation shifts the bits in \vv{e} \vv{n} places towards \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader dshr & (e, n) & () & (UInt, UInt) & UInt & w\ts{e}\\ &&& (SInt, UInt) & SInt & w\ts{e}\\ \hline @@ -1403,8 +1403,8 @@ The dynamic shift right operation shifts the bits in \vv{e} \vv{n} places toward \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader cvt & (e) & () & (UInt) & SInt & w\ts{e}+1\\ &&& (SInt) & SInt & w\ts{e}\\ \hline @@ -1419,8 +1419,8 @@ The result of the arithmetic convert to signed operation is a signed integer rep \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader neg & (e) & () & (UInt) & SInt & w\ts{e}+1\\ &&& (SInt) & SInt & w\ts{e}+1\\ \hline @@ -1435,24 +1435,24 @@ The result of the negate operation is a signed integer representing the negated \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader not & (e) & () & (UInt) & UInt & w\ts{e}\\ - &&& (SInt) & UInt & w\ts{e}\\ + &&& (SInt) & UInt & w\ts{e}\\ \hline \end{tabular} }} \end{figure} -The bitwise complement operation performs a logical not on each bit in \vv{e}. +The bitwise complement operation performs a logical not on each bit in \vv{e}. \subsection{Binary Bitwise Operations} \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader and,or,xor & (e1, e2) & () & (UInt,UInt) & UInt & max(w\ts{e1},w\ts{e2})\\ &&& (SInt,SInt) & UInt & max(w\ts{e1},w\ts{e2})\\ \hline @@ -1467,10 +1467,10 @@ The above bitwise operations perform a bitwise and, or, or exclusive or on \vv{e \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader andr,orr,xorr & (e) & () & (UInt) & UInt & 1\\ - &&& (SInt) & UInt & 1\\ + &&& (SInt) & UInt & 1\\ \hline \end{tabular} }} @@ -1483,8 +1483,8 @@ The bitwise reduction operations correspond to a bitwise and, or, and exclusive \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader cat & (e1,e2) & () & (UInt, UInt) & UInt & w\ts{e1}+w\ts{e2}\\ &&& (SInt, SInt) & UInt & w\ts{e1}+w\ts{e2}\\ \hline @@ -1492,15 +1492,15 @@ cat & (e1,e2) & () & (UInt, UInt) & UInt & w\ts{e1}+w\ts{e2}\\ }} \end{figure} -The result of the concatenate operation is the bits of \vv{e1} concatenated to the most significant end of the bits of \vv{e2}. +The result of the concatenate operation is the bits of \vv{e1} concatenated to the most significant end of the bits of \vv{e2}. \subsection{Bit Extraction Operation} \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader bits & (e) & (hi,lo) & (UInt) & UInt & hi-lo+1\\ &&& (SInt) & UInt & hi-lo+1\\ \hline @@ -1515,8 +1515,8 @@ The result of the bit extraction operation are the bits of \vv{e} between \vv{lo \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader head & (e) & (n) & (UInt) & UInt & n\\ &&& (SInt) & UInt & n\\ \hline @@ -1531,8 +1531,8 @@ The result of the head operation are the \vv{n} most significant bits of \vv{e}. \begin{figure}[H] { \fontsize{10pt}{1.10em}\selectfont {\ttfamily -\begin{tabular}{ |c|c|c|c|c|c| } - \opheader +\begin{tabular}{ |c|c|c|c|c|c| } + \opheader tail & (e) & (n) & (UInt) & UInt & w\ts{e}-n\\ &&& (SInt) & UInt & w\ts{e}-n\\ \hline @@ -1542,21 +1542,21 @@ tail & (e) & (n) & (UInt) & UInt & w\ts{e}-n\\ The tail operation truncates the \vv{n} most significant bits from \vv{e}. \vv{n} must be non-negative and strictly less than the bit width of \vv{e}. -\section{Genders}\label{genders} +\section{Flows}\label{flows} -An expression's gender partially determines the legality of connecting to and from the expression. Every expression is classified as either {\em male}, {\em female}, or {\em bi-gender}. For details on connection rules refer back to sections \ref{connects} and \ref{partial_connects}. +An expression's flow partially determines the legality of connecting to and from the expression. Every expression is classified as either {\em source}, {\em sink}, or {\em duplex}. For details on connection rules refer back to sections \ref{connects} and \ref{partial_connects}. -The gender 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 male. A reference to an output port is female. A reference to a wire or register is bi-gender. +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 gender of a subindex or subaccess expression is the gender of the vector-typed expression it indexes or accesses. +The flow of a subindex or subaccess expression is the flow of the vector-typed expression it indexes or accesses. -The gender of a subfield expression depends upon the orientation of the field. If the field is not flipped, its gender is the same gender as the bundle-typed expression it selects its field from. If the field is flipped, then its gender is the reverse of the gender of the bundle-typed expression it selects its field from. The reverse of male is female, and vice-versa. The reverse of bi-gender remains bi-gender. +The flow of a subfield 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 gender of all other expressions are male. +The flow of all other expressions are source. \section{Width Inference}\label{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 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. @@ -1640,7 +1640,7 @@ module MyModule : r <= in.b when c : r[1] <= in.a - out <= r[0] + out <= r[0] \end{lstlisting} is rewritten as the following equivalent LoFIRRTL circuit by the lowering transform. \begin{lstlisting} @@ -1655,7 +1655,7 @@ module MyModule : c <= in$a reg r$0: UInt<2>, clk reg r$1: UInt<2>, clk - reg r$2: 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 @@ -1666,12 +1666,12 @@ module MyModule : 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 \verb|_|. Identifiers cannot begin with a digit. +The following characters are allowed in identifiers: upper and lower case letters, digits, and \verb|_|. 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. +An integer literal in FIRRTL begins with one of the following, where `\#' represents a digit between 0 and 9. \begin{itemize} -\item `0x' : For indicating a hexadecimal number. The rest of the literal must consist of either digits or a letter between `A' and `F', or the separator `\_'. -\item `0o' : For indicating an octal number. The rest of the literal must consist of digits between 0 and 7, or the separator `\_'. +\item `0x' : For indicating a hexadecimal number. The rest of the literal must consist of either digits or a letter between `A' and `F', or the separator `\_'. +\item `0o' : For indicating an octal number. The rest of the literal must consist of digits between 0 and 7, or the separator `\_'. \item `0b' : For indicating a binary number. The rest of the literal must consist of either 0 or 1, or the separator `\_'. \item `-\#' : For indicating a negative decimal number. The rest of the literal must consist of digits between 0 and 9. \item `\#' : For indicating a positive decimal number. The rest of the literal must consist of digits between 0 and 9. @@ -1699,7 +1699,7 @@ All circuits, modules, ports and statements can optionally be followed with the The following example shows the info tokens included: \begin{lstlisting} -circuit Top : @["myfile.txt: 14, 8"] +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"] @@ -1740,12 +1740,12 @@ The concrete syntax of FIRRTL is defined in section \ref{syntax_tree}. Productio &\pipe &\vv{reg} \pd{id} \vv{:} \pd{type} \pd{exp} \opt{\vv{(with:} \vv{\{reset => (}\pd{exp}, \pd{exp}\vv{)\})}} \opt{\pd{info}} &\text{Register}\\ &\pipe &\vv{mem} \pd{id} \vv{:} \opt{\pd{info}} \vv{(} &\text{Memory}\\ && \verb| |\vv{data-type =>} \pd{type}\\ - && \verb| |\vv{depth =>} \pd{int}\\ - && \verb| |\vv{read-latency =>} \pd{int}\\ - && \verb| |\vv{write-latency =>} \pd{int}\\ - && \verb| |\vv{read-under-write =>} \pd{ruw}\\ - && \verb| |\rpt{\vv{reader =>} \pd{id}}\\ - && \verb| |\rpt{\vv{writer =>} \pd{id}}\\ + && \verb| |\vv{depth =>} \pd{int}\\ + && \verb| |\vv{read-latency =>} \pd{int}\\ + && \verb| |\vv{write-latency =>} \pd{int}\\ + && \verb| |\vv{read-under-write =>} \pd{ruw}\\ + && \verb| |\rpt{\vv{reader =>} \pd{id}}\\ + && \verb| |\rpt{\vv{writer =>} \pd{id}}\\ && \verb| |\rpt{\vv{readwriter =>} \pd{id}}\vv{)} \\ &\pipe &\vv{inst} \pd{id} \vv{of} \pd{id} \opt{\pd{info}} &\text{Instance}\\ &\pipe &\vv{node} \pd{id} \vv{=} \pd{exp} \opt{\pd{info}} &\text{Node}\\ @@ -1814,9 +1814,8 @@ The concrete syntax of FIRRTL is defined in section \ref{syntax_tree}. Productio %\section{TODO} % %- FIRRTL implementation -% - Add partial connect algorithm ; +% - Add partial connect algorithm ; % - Add oriented types to type checker % - Add memory read-under-write flag ; probably overengineering, but could be a wash \end{document} - diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index 854e1876..d7c73e39 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -189,11 +189,11 @@ class VerilogEmitter extends SeqTransform with Emitter { else if (e2 == we(one)) e1.e1 else DoPrim(And, Seq(e1.e1, e2.e1), Nil, UIntType(IntWidth(1))) } - def wref(n: String, t: Type) = WRef(n, t, ExpKind, UNKNOWNGENDER) + def wref(n: String, t: Type) = WRef(n, t, ExpKind, UnknownFlow) def remove_root(ex: Expression): Expression = ex match { case ex: WSubField => ex.expr match { case (e: WSubField) => remove_root(e) - case (_: WRef) => WRef(ex.name, ex.tpe, InstanceKind, UNKNOWNGENDER) + case (_: WRef) => WRef(ex.name, ex.tpe, InstanceKind, UnknownFlow) } case _ => throwInternalError(s"shouldn't be here: remove_root($ex)") } @@ -466,7 +466,7 @@ class VerilogEmitter extends SeqTransform with Emitter { case sx: Connect => netlist(sx.loc) = sx.expr case sx: IsInvalid => error("Should have removed these!") case sx: DefNode => - val e = WRef(sx.name, sx.value.tpe, NodeKind, MALE) + val e = WRef(sx.name, sx.value.tpe, NodeKind, SourceFlow) netlist(e) = sx.value case _ => } @@ -614,7 +614,7 @@ class VerilogEmitter extends SeqTransform with Emitter { val rstring = rand_string(s.dataType) initials += Seq("`ifdef RANDOMIZE_MEM_INIT") initials += Seq("for (initvar = 0; initvar < ", bigIntToVLit(s.depth), "; initvar = initvar+1)") - initials += Seq(tab, WSubAccess(wref(s.name, s.dataType), index, s.dataType, FEMALE), + initials += Seq(tab, WSubAccess(wref(s.name, s.dataType), index, s.dataType, SinkFlow), " = ", rstring, ";") initials += Seq("`endif // RANDOMIZE_MEM_INIT") } @@ -725,7 +725,7 @@ class VerilogEmitter extends SeqTransform with Emitter { initialize(e, sx.reset, sx.init) case sx: DefNode => declare("wire", sx.name, sx.value.tpe, sx.info) - assign(WRef(sx.name, sx.value.tpe, NodeKind, MALE), sx.value, sx.info) + assign(WRef(sx.name, sx.value.tpe, NodeKind, SourceFlow), sx.value, sx.info) case sx: Stop => simulate(sx.clk, sx.en, stop(sx.ret), Some("STOP_COND"), sx.info) case sx: Print => @@ -781,8 +781,8 @@ class VerilogEmitter extends SeqTransform with Emitter { //; Read port assign(addr, netlist(addr), NoInfo) // Info should come from addr connection // assign(en, netlist(en)) //;Connects value to m.r.en - val mem = WRef(sx.name, memType(sx), MemKind, UNKNOWNGENDER) - val memPort = WSubAccess(mem, addr, sx.dataType, UNKNOWNGENDER) + val mem = WRef(sx.name, memType(sx), MemKind, UnknownFlow) + val memPort = WSubAccess(mem, addr, sx.dataType, UnknownFlow) val depthValue = UIntLiteral(sx.depth, IntWidth(sx.depth.bitLength)) val garbageGuard = DoPrim(Geq, Seq(addr, depthValue), Seq(), UnknownType) @@ -812,8 +812,8 @@ class VerilogEmitter extends SeqTransform with Emitter { assign(mask, netlist(mask), NoInfo) assign(en, netlist(en), NoInfo) - val mem = WRef(sx.name, memType(sx), MemKind, UNKNOWNGENDER) - val memPort = WSubAccess(mem, addr, sx.dataType, UNKNOWNGENDER) + val mem = WRef(sx.name, memType(sx), MemKind, UnknownFlow) + val memPort = WSubAccess(mem, addr, sx.dataType, UnknownFlow) update(memPort, data, clk, AND(en, mask), sx.info) } diff --git a/src/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala index 274ccf74..05cdbe96 100644 --- a/src/main/scala/firrtl/LoweringCompilers.scala +++ b/src/main/scala/firrtl/LoweringCompilers.scala @@ -29,7 +29,7 @@ class IRToWorkingIR extends CoreTransform { def transforms = Seq(passes.ToWorkingIR) } -/** Resolves types, kinds, and genders, and checks the circuit legality. +/** Resolves types, kinds, and flows, and checks the circuit legality. * Operates on working IR nodes and high Firrtl. */ class ResolveAndCheck extends CoreTransform { @@ -43,8 +43,8 @@ class ResolveAndCheck extends CoreTransform { passes.Uniquify, passes.ResolveKinds, passes.InferTypes, - passes.ResolveGenders, - passes.CheckGenders, + passes.ResolveFlows, + passes.CheckFlows, new passes.InferWidths, passes.CheckWidths, new firrtl.transforms.InferResets) @@ -70,7 +70,7 @@ class HighFirrtlToMiddleFirrtl extends CoreTransform { passes.InferTypes, passes.CheckTypes, new checks.CheckResets, - passes.ResolveGenders, + passes.ResolveFlows, new passes.InferWidths, passes.CheckWidths, passes.ConvertFixedToSInt, @@ -89,7 +89,7 @@ class MiddleFirrtlToLowFirrtl extends CoreTransform { passes.LowerTypes, passes.ResolveKinds, passes.InferTypes, - passes.ResolveGenders, + passes.ResolveFlows, new passes.InferWidths, passes.Legalize, new firrtl.transforms.RemoveReset, diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index 91da600a..4bf2d14d 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -34,9 +34,9 @@ object toBits { } private def hiercat(e: Expression): Expression = e.tpe match { case t: VectorType => seqCat((0 until t.size).reverse map (i => - hiercat(WSubIndex(e, i, t.tpe, UNKNOWNGENDER)))) + hiercat(WSubIndex(e, i, t.tpe, UnknownFlow)))) case t: BundleType => seqCat(t.fields map (f => - hiercat(WSubField(e, f.name, f.tpe, UNKNOWNGENDER)))) + hiercat(WSubField(e, f.name, f.tpe, UnknownFlow)))) case t: GroundType => DoPrim(AsUInt, Seq(e), Seq.empty, UnknownType) case t => Utils.error(s"Unknown type encountered in toBits: $e") } @@ -63,18 +63,18 @@ object bitWidth { object castRhs { def apply(lhst: Type, rhs: Expression) = { (lhst, rhs.tpe) match { - case (x: GroundType, y: GroundType) if WrappedType(x) == WrappedType(y) => + case (x: GroundType, y: GroundType) if WrappedType(x) == WrappedType(y) => rhs - case (_: SIntType, _) => + case (_: SIntType, _) => DoPrim(AsSInt, Seq(rhs), Seq.empty, lhst) - case (FixedType(_, IntWidth(p)), _) => + case (FixedType(_, IntWidth(p)), _) => DoPrim(AsFixedPoint, Seq(rhs), Seq(p), lhst) - case (ClockType, _) => + case (ClockType, _) => DoPrim(AsClock, Seq(rhs), Seq.empty, lhst) - case (_: UIntType, _) => + case (_: UIntType, _) => DoPrim(AsUInt, Seq(rhs), Seq.empty, lhst) case (_, _) => Utils.error("castRhs lhst, rhs type combination is invalid") - } + } } } @@ -102,13 +102,13 @@ object fromBits { lhst match { case t: VectorType => (0 until t.size foldLeft( (offset, Seq[Statement]()) )) { case ((curOffset, stmts), i) => - val subidx = WSubIndex(lhs, i, t.tpe, UNKNOWNGENDER) + val subidx = WSubIndex(lhs, i, t.tpe, UnknownFlow) val (tmpOffset, substmts) = getPart(subidx, t.tpe, rhs, curOffset) (tmpOffset, stmts ++ substmts) } case t: BundleType => (t.fields foldRight( (offset, Seq[Statement]()) )) { case (f, (curOffset, stmts)) => - val subfield = WSubField(lhs, f.name, f.tpe, UNKNOWNGENDER) + val subfield = WSubField(lhs, f.name, f.tpe, UnknownFlow) val (tmpOffset, substmts) = getPart(subfield, f.tpe, rhs, curOffset) (tmpOffset, stmts ++ substmts) } @@ -228,7 +228,7 @@ object Utils extends LazyLogging { val zero = UIntLiteral(0) def create_exps(n: String, t: Type): Seq[Expression] = - create_exps(WRef(n, t, ExpKind, UNKNOWNGENDER)) + create_exps(WRef(n, t, ExpKind, UnknownFlow)) def create_exps(e: Expression): Seq[Expression] = e match { case ex: Mux => val e1s = create_exps(ex.tval) @@ -240,8 +240,8 @@ object Utils extends LazyLogging { case ex => ex.tpe match { case (_: GroundType) => Seq(ex) case t: BundleType => - t.fields.flatMap(f => create_exps(WSubField(ex, f.name, f.tpe,times(gender(ex), f.flip)))) - case t: VectorType => (0 until t.size).flatMap(i => create_exps(WSubIndex(ex, i, t.tpe,gender(ex)))) + t.fields.flatMap(f => create_exps(WSubField(ex, f.name, f.tpe,times(flow(ex), f.flip)))) + case t: VectorType => (0 until t.size).flatMap(i => create_exps(WSubIndex(ex, i, t.tpe,flow(ex)))) } } @@ -260,9 +260,9 @@ object Utils extends LazyLogging { case ex => ex.tpe match { case (_: GroundType) => Seq(ex) case (t: BundleType) => (t.fields foldLeft Seq[Expression](ex))((exps, f) => - exps ++ create_exps(WSubField(ex, f.name, f.tpe,times(gender(ex), f.flip)))) + exps ++ create_exps(WSubField(ex, f.name, f.tpe,times(flow(ex), f.flip)))) case (t: VectorType) => (0 until t.size foldLeft Seq[Expression](ex))((exps, i) => - exps ++ create_exps(WSubIndex(ex, i, t.tpe,gender(ex)))) + exps ++ create_exps(WSubIndex(ex, i, t.tpe,flow(ex)))) } } def toTarget(main: String, module: String)(expression: Expression): ReferenceTarget = { @@ -283,7 +283,7 @@ object Utils extends LazyLogging { onExp(expression) ReferenceTarget(main, module, Nil, ref, tokens) } - @deprecated("get_flip is fundamentally slow, use to_flip(gender(expr))", "1.2") + @deprecated("get_flip is fundamentally slow, use to_flip(flow(expr))", "1.2") def get_flip(t: Type, i: Int, f: Orientation): Orientation = { if (i >= get_size(t)) throwInternalError(s"get_flip: shouldn't be here - $i >= get_size($t)") t match { @@ -308,7 +308,7 @@ object Utils extends LazyLogging { flip.get } } - + def get_point (e:Expression) : Int = e match { case (e: WRef) => 0 case (e: WSubField) => e.expr.tpe match {case b: BundleType => @@ -418,7 +418,7 @@ object Utils extends LazyLogging { } case vx => UnknownType } - + // ================================= def error(str: String, cause: Throwable = null) = throw new FirrtlInternalException(str, cause) @@ -473,12 +473,12 @@ object Utils extends LazyLogging { } } -// =========== GENDER/FLIP UTILS ============ - def swap(g: Gender) : Gender = g match { - case UNKNOWNGENDER => UNKNOWNGENDER - case MALE => FEMALE - case FEMALE => MALE - case BIGENDER => BIGENDER +// =========== FLOW/FLIP UTILS ============ + def swap(g: Flow) : Flow = g match { + case UnknownFlow => UnknownFlow + case SourceFlow => SinkFlow + case SinkFlow => SourceFlow + case DuplexFlow => DuplexFlow } def swap(d: Direction) : Direction = d match { case Output => Input @@ -488,21 +488,26 @@ object Utils extends LazyLogging { case Default => Flip case Flip => Default } - def to_dir(g: Gender): Direction = g match { - case MALE => Input - case FEMALE => Output + def to_dir(g: Flow): Direction = g match { + case SourceFlow => Input + case SinkFlow => Output } + @deprecated("Migrate from 'Gender' to 'Flow. This method will be removed in 1.3", "1.2") def to_gender(d: Direction): Gender = d match { case Input => MALE case Output => FEMALE } + def to_flow(d: Direction): Flow = d match { + case Input => SourceFlow + case Output => SinkFlow + } def to_flip(d: Direction): Orientation = d match { case Input => Flip case Output => Default } - def to_flip(g: Gender): Orientation = g match { - case MALE => Flip - case FEMALE => Default + def to_flip(g: Flow): Orientation = g match { + case SourceFlow => Flip + case SinkFlow => Default } def field_flip(v: Type, s: String): Orientation = v match { @@ -524,14 +529,14 @@ object Utils extends LazyLogging { case Default => d case Flip => swap(d) } - def times(g: Gender, d: Direction): Direction = times(d, g) - def times(d: Direction, g: Gender): Direction = g match { - case FEMALE => d - case MALE => swap(d) // MALE == INPUT == REVERSE + def times(g: Flow, d: Direction): Direction = times(d, g) + def times(d: Direction, g: Flow): Direction = g match { + case SinkFlow => d + case SourceFlow => swap(d) // SourceFlow == INPUT == REVERSE } - def times(g: Gender, flip: Orientation): Gender = times(flip, g) - def times(flip: Orientation, g: Gender): Gender = flip match { + def times(g: Flow, flip: Orientation): Flow = times(flip, g) + def times(flip: Orientation, g: Flow): Flow = flip match { case Default => g case Flip => swap(g) } @@ -548,6 +553,7 @@ object Utils extends LazyLogging { case ex: WSubAccess => kind(ex.expr) case ex => ExpKind } + @deprecated("Migrate from 'Gender' to 'Flow'. This method will be removed in 1.3", "1.2") def gender(e: Expression): Gender = e match { case ex: WRef => ex.gender case ex: WSubField => ex.gender @@ -561,6 +567,7 @@ object Utils extends LazyLogging { case WInvalid => MALE case ex => throwInternalError(s"gender: shouldn't be here - $e") } + @deprecated("Migrate from 'Gender' to 'Flow'. This method will be removed in 1.3", "1.2") def get_gender(s: Statement): Gender = s match { case sx: DefWire => BIGENDER case sx: DefRegister => BIGENDER @@ -576,7 +583,37 @@ object Utils extends LazyLogging { case sx: IsInvalid => UNKNOWNGENDER case EmptyStmt => UNKNOWNGENDER } + @deprecated("Migrate from 'Gender' to 'Flow'. This method will be removed in 1.3", "1.2") def get_gender(p: Port): Gender = if (p.direction == Input) MALE else FEMALE + def flow(e: Expression): Flow = e match { + case ex: WRef => ex.flow + case ex: WSubField => ex.flow + case ex: WSubIndex => ex.flow + case ex: WSubAccess => ex.flow + case ex: DoPrim => SourceFlow + case ex: UIntLiteral => SourceFlow + case ex: SIntLiteral => SourceFlow + case ex: Mux => SourceFlow + case ex: ValidIf => SourceFlow + case WInvalid => SourceFlow + case ex => throwInternalError(s"flow: shouldn't be here - $e") + } + def get_flow(s: Statement): Flow = s match { + case sx: DefWire => DuplexFlow + case sx: DefRegister => DuplexFlow + case sx: WDefInstance => SourceFlow + case sx: DefNode => SourceFlow + case sx: DefInstance => SourceFlow + case sx: DefMemory => SourceFlow + case sx: Block => UnknownFlow + case sx: Connect => UnknownFlow + case sx: PartialConnect => UnknownFlow + case sx: Stop => UnknownFlow + case sx: Print => UnknownFlow + case sx: IsInvalid => UnknownFlow + case EmptyStmt => UnknownFlow + } + def get_flow(p: Port): Flow = if (p.direction == Input) SourceFlow else SinkFlow def get_info(s: Statement): Info = s match { case s: HasInfo => s.info case _ => NoInfo @@ -598,23 +635,23 @@ object Utils extends LazyLogging { case e: WRef => (e, EmptyExpression) case e: WSubIndex => val (root, tail) = splitRef(e.expr) - (root, WSubIndex(tail, e.value, e.tpe, e.gender)) + (root, WSubIndex(tail, e.value, e.tpe, e.flow)) case e: WSubField => val (root, tail) = splitRef(e.expr) tail match { - case EmptyExpression => (root, WRef(e.name, e.tpe, root.kind, e.gender)) - case exp => (root, WSubField(tail, e.name, e.tpe, e.gender)) + case EmptyExpression => (root, WRef(e.name, e.tpe, root.kind, e.flow)) + case exp => (root, WSubField(tail, e.name, e.tpe, e.flow)) } } /** Adds a root reference to some SubField/SubIndex chain */ def mergeRef(root: Expression, body: Expression): Expression = body match { case e: WRef => - WSubField(root, e.name, e.tpe, e.gender) + WSubField(root, e.name, e.tpe, e.flow) case e: WSubIndex => - WSubIndex(mergeRef(root, e.expr), e.value, e.tpe, e.gender) + WSubIndex(mergeRef(root, e.expr), e.value, e.tpe, e.flow) case e: WSubField => - WSubField(mergeRef(root, e.expr), e.name, e.tpe, e.gender) + WSubField(mergeRef(root, e.expr), e.name, e.tpe, e.flow) case EmptyExpression => root } diff --git a/src/main/scala/firrtl/WIR.scala b/src/main/scala/firrtl/WIR.scala index c1839a22..73a20d18 100644 --- a/src/main/scala/firrtl/WIR.scala +++ b/src/main/scala/firrtl/WIR.scala @@ -20,13 +20,24 @@ case object MemKind extends Kind case object ExpKind extends Kind case object UnknownKind extends Kind -trait Gender -case object MALE extends Gender -case object FEMALE extends Gender -case object BIGENDER extends Gender -case object UNKNOWNGENDER extends Gender +trait Flow +case object SourceFlow extends Flow +case object SinkFlow extends Flow +case object DuplexFlow extends Flow +case object UnknownFlow extends Flow -case class WRef(name: String, tpe: Type, kind: Kind, gender: Gender) extends Expression { +private[firrtl] trait GenderFromFlow { this: Expression => + val flow: Flow + @deprecated("Migrate from 'Gender' to 'Flow'. This method will be removed in 1.3.", "1.2") + def gender: Gender = flow match { + case SourceFlow => MALE + case SinkFlow => FEMALE + case DuplexFlow => BIGENDER + case UnknownFlow => UNKNOWNGENDER + } +} + +case class WRef(name: String, tpe: Type, kind: Kind, flow: Flow) extends Expression with GenderFromFlow { def serialize: String = name def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) @@ -37,21 +48,21 @@ case class WRef(name: String, tpe: Type, kind: Kind, gender: Gender) extends Exp } object WRef { /** Creates a WRef from a Wire */ - def apply(wire: DefWire): WRef = new WRef(wire.name, wire.tpe, WireKind, UNKNOWNGENDER) + def apply(wire: DefWire): WRef = new WRef(wire.name, wire.tpe, WireKind, UnknownFlow) /** Creates a WRef from a Register */ - def apply(reg: DefRegister): WRef = new WRef(reg.name, reg.tpe, RegKind, UNKNOWNGENDER) + def apply(reg: DefRegister): WRef = new WRef(reg.name, reg.tpe, RegKind, UnknownFlow) /** Creates a WRef from a Node */ - def apply(node: DefNode): WRef = new WRef(node.name, node.value.tpe, NodeKind, MALE) + def apply(node: DefNode): WRef = new WRef(node.name, node.value.tpe, NodeKind, SourceFlow) /** Creates a WRef from a Port */ - def apply(port: Port): WRef = new WRef(port.name, port.tpe, PortKind, UNKNOWNGENDER) + def apply(port: Port): WRef = new WRef(port.name, port.tpe, PortKind, UnknownFlow) /** Creates a WRef from a WDefInstance */ - def apply(wi: WDefInstance): WRef = new WRef(wi.name, wi.tpe, InstanceKind, UNKNOWNGENDER) + def apply(wi: WDefInstance): WRef = new WRef(wi.name, wi.tpe, InstanceKind, UnknownFlow) /** Creates a WRef from a DefMemory */ - def apply(mem: DefMemory): WRef = new WRef(mem.name, passes.MemPortUtils.memType(mem), MemKind, UNKNOWNGENDER) + def apply(mem: DefMemory): WRef = new WRef(mem.name, passes.MemPortUtils.memType(mem), MemKind, UnknownFlow) /** Creates a WRef from an arbitrary string name */ - def apply(n: String, t: Type = UnknownType, k: Kind = ExpKind): WRef = new WRef(n, t, k, UNKNOWNGENDER) + def apply(n: String, t: Type = UnknownType, k: Kind = ExpKind): WRef = new WRef(n, t, k, UnknownFlow) } -case class WSubField(expr: Expression, name: String, tpe: Type, gender: Gender) extends Expression { +case class WSubField(expr: Expression, name: String, tpe: Type, flow: Flow) extends Expression with GenderFromFlow { def serialize: String = s"${expr.serialize}.$name" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) @@ -61,10 +72,10 @@ case class WSubField(expr: Expression, name: String, tpe: Type, gender: Gender) def foreachWidth(f: Width => Unit): Unit = Unit } object WSubField { - def apply(expr: Expression, n: String): WSubField = new WSubField(expr, n, field_type(expr.tpe, n), UNKNOWNGENDER) - def apply(expr: Expression, name: String, tpe: Type): WSubField = new WSubField(expr, name, tpe, UNKNOWNGENDER) + def apply(expr: Expression, n: String): WSubField = new WSubField(expr, n, field_type(expr.tpe, n), UnknownFlow) + def apply(expr: Expression, name: String, tpe: Type): WSubField = new WSubField(expr, name, tpe, UnknownFlow) } -case class WSubIndex(expr: Expression, value: Int, tpe: Type, gender: Gender) extends Expression { +case class WSubIndex(expr: Expression, value: Int, tpe: Type, flow: Flow) extends Expression with GenderFromFlow { def serialize: String = s"${expr.serialize}[$value]" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) @@ -73,7 +84,7 @@ case class WSubIndex(expr: Expression, value: Int, tpe: Type, gender: Gender) ex def foreachType(f: Type => Unit): Unit = f(tpe) def foreachWidth(f: Width => Unit): Unit = Unit } -case class WSubAccess(expr: Expression, index: Expression, tpe: Type, gender: Gender) extends Expression { +case class WSubAccess(expr: Expression, index: Expression, tpe: Type, flow: Flow) extends Expression with GenderFromFlow { def serialize: String = s"${expr.serialize}[${index.serialize}]" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr), index = f(index)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) @@ -264,7 +275,7 @@ class WrappedType(val t: Type) { object WrappedWidth { def eqw(w1: Width, w2: Width): Boolean = new WrappedWidth(w1) == new WrappedWidth(w2) } - + class WrappedWidth (val w: Width) { def ww(w: Width): WrappedWidth = new WrappedWidth(w) override def toString = w match { @@ -285,10 +296,10 @@ class WrappedWidth (val w: Width) { case (w1: MinWidth, w2: MinWidth) => w1.args.size == w2.args.size && (w1.args forall (a1 => w2.args exists (a2 => eqw(a1, a2)))) case (w1: IntWidth, w2: IntWidth) => w1.width == w2.width - case (w1: PlusWidth, w2: PlusWidth) => + case (w1: PlusWidth, w2: PlusWidth) => (ww(w1.arg1) == ww(w2.arg1) && ww(w1.arg2) == ww(w2.arg2)) || (ww(w1.arg1) == ww(w2.arg2) && ww(w1.arg2) == ww(w2.arg1)) - case (w1: MinusWidth,w2: MinusWidth) => + case (w1: MinusWidth,w2: MinusWidth) => (ww(w1.arg1) == ww(w2.arg1) && ww(w1.arg2) == ww(w2.arg2)) || (ww(w1.arg1) == ww(w2.arg2) && ww(w1.arg2) == ww(w2.arg1)) case (w1: ExpWidth, w2: ExpWidth) => ww(w1.arg1) == ww(w2.arg1) @@ -365,4 +376,3 @@ case class CDefMPort(info: Info, def foreachString(f: String => Unit): Unit = f(name) def foreachInfo(f: Info => Unit): Unit = f(info) } - diff --git a/src/main/scala/firrtl/package.scala b/src/main/scala/firrtl/package.scala index eb68aef4..1e871c46 100644 --- a/src/main/scala/firrtl/package.scala +++ b/src/main/scala/firrtl/package.scala @@ -12,4 +12,27 @@ package object firrtl { @deprecated("Use firrtl.stage.TargetDirAnnotation", "1.2") val TargetDirAnnotation = firrtl.options.TargetDirAnnotation + + @deprecated("Use Flow instead of Gender. This trait will be removed in 1.3", "1.2") + trait Gender + + @deprecated("Use SourceFlow instead of MALE. This case object will be removed in 1.3", "1.2") + case object MALE extends Gender + + @deprecated("Use SinkFlow instead of FEMALE. This case object will be removed in 1.3", "1.2") + case object FEMALE extends Gender + + @deprecated("Use DuplexFlow instead of BIGENDER. This case object will be removed in 1.3", "1.2") + case object BIGENDER extends Gender + + @deprecated("Use UnknownFlow instead of UNKNOWNGENDER. This case object will be removed in 1.3", "1.2") + case object UNKNOWNGENDER extends Gender + + @deprecated("Please migrate from 'Gender' to 'Flow'. This implicit conversion will be removed in 1.3", "1.2") + implicit def genderToFlow(gender: Gender): Flow = gender match { + case MALE => SourceFlow + case FEMALE => SinkFlow + case BIGENDER => DuplexFlow + case UNKNOWNGENDER => UnknownFlow + } } diff --git a/src/main/scala/firrtl/passes/CheckInitialization.scala b/src/main/scala/firrtl/passes/CheckInitialization.scala index d1b6a03f..9fbf3eeb 100644 --- a/src/main/scala/firrtl/passes/CheckInitialization.scala +++ b/src/main/scala/firrtl/passes/CheckInitialization.scala @@ -18,14 +18,14 @@ object CheckInitialization extends Pass { private case class VoidExpr(stmt: Statement, voidDeps: Seq[Expression]) class RefNotInitializedException(info: Info, mname: String, name: String, trace: Seq[Statement]) extends PassException( - s"$info : [module $mname] Reference $name is not fully initialized.\n" + + s"$info : [module $mname] Reference $name is not fully initialized.\n" + trace.map(s => s" ${get_info(s)} : ${s.serialize}").mkString("\n") ) private def getTrace(expr: WrappedExpression, voidExprs: Map[WrappedExpression, VoidExpr]): Seq[Statement] = { @tailrec def rec(e: WrappedExpression, map: Map[WrappedExpression, VoidExpr], trace: Seq[Statement]): Seq[Statement] = { - val voidExpr = map(e) + val voidExpr = map(e) val newTrace = voidExpr.stmt +: trace if (voidExpr.voidDeps.nonEmpty) rec(voidExpr.voidDeps.head, map, newTrace) else newTrace } @@ -62,7 +62,7 @@ object CheckInitialization extends Pass { case node: DefNode => val (hasVoid, voidDeps) = hasVoidExpr(node.value) if (hasVoid) { - val nodeRef = WRef(node.name, node.value.tpe, NodeKind, MALE) + val nodeRef = WRef(node.name, node.value.tpe, NodeKind, SourceFlow) voidExprs(nodeRef) = VoidExpr(node, voidDeps) } case sx => sx.foreach(checkInitS) diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala index a17a5a2e..85ed7de0 100644 --- a/src/main/scala/firrtl/passes/Checks.scala +++ b/src/main/scala/firrtl/passes/Checks.scala @@ -221,12 +221,12 @@ trait CheckHighFormLike { // Search for ResetType Ports of direction def findBadResetTypePorts(m: DefModule, dir: Direction): Seq[(Port, Expression)] = { - val bad = to_gender(dir) + val bad = to_flow(dir) for { port <- m.ports - ref = WRef(port).copy(gender = to_gender(port.direction)) + ref = WRef(port).copy(flow = to_flow(port.direction)) expr <- create_exps(ref) - if ((expr.tpe == ResetType) && (gender(expr) == bad)) + if ((expr.tpe == ResetType) && (flow(expr) == bad)) } yield (port, expr) } @@ -544,31 +544,31 @@ object CheckTypes extends Pass { } } -object CheckGenders extends Pass { - type GenderMap = collection.mutable.HashMap[String, Gender] +object CheckFlows extends Pass { + type FlowMap = collection.mutable.HashMap[String, Flow] - implicit def toStr(g: Gender): String = g match { - case MALE => "source" - case FEMALE => "sink" - case UNKNOWNGENDER => "unknown" - case BIGENDER => "sourceOrSink" + implicit def toStr(g: Flow): String = g match { + case SourceFlow => "source" + case SinkFlow => "sink" + case UnknownFlow => "unknown" + case DuplexFlow => "duplex" } - class WrongGender(info:Info, mname: String, expr: String, wrong: Gender, right: Gender) extends PassException( + class WrongFlow(info:Info, mname: String, expr: String, wrong: Flow, right: Flow) extends PassException( s"$info: [module $mname] Expression $expr is used as a $wrong but can only be used as a $right.") def run (c:Circuit): Circuit = { val errors = new Errors() - def get_gender(e: Expression, genders: GenderMap): Gender = e match { - case (e: WRef) => genders(e.name) - case (e: WSubIndex) => get_gender(e.expr, genders) - case (e: WSubAccess) => get_gender(e.expr, genders) + def get_flow(e: Expression, flows: FlowMap): Flow = e match { + case (e: WRef) => flows(e.name) + case (e: WSubIndex) => get_flow(e.expr, flows) + case (e: WSubAccess) => get_flow(e.expr, flows) case (e: WSubField) => e.expr.tpe match {case t: BundleType => val f = (t.fields find (_.name == e.name)).get - times(get_gender(e.expr, genders), f.flip) + times(get_flow(e.expr, flows), f.flip) } - case _ => MALE + case _ => SourceFlow } def flip_q(t: Type): Boolean = { @@ -582,66 +582,83 @@ object CheckGenders extends Pass { flip_rec(t, Default) } - def check_gender(info:Info, mname: String, genders: GenderMap, desired: Gender)(e:Expression): Unit = { - val gender = get_gender(e,genders) - (gender, desired) match { - case (MALE, FEMALE) => - errors.append(new WrongGender(info, mname, e.serialize, desired, gender)) - case (FEMALE, MALE) => kind(e) match { + def check_flow(info:Info, mname: String, flows: FlowMap, desired: Flow)(e:Expression): Unit = { + val flow = get_flow(e,flows) + (flow, desired) match { + case (SourceFlow, SinkFlow) => + errors.append(new WrongFlow(info, mname, e.serialize, desired, flow)) + case (SinkFlow, SourceFlow) => kind(e) match { case PortKind | InstanceKind if !flip_q(e.tpe) => // OK! case _ => - errors.append(new WrongGender(info, mname, e.serialize, desired, gender)) + errors.append(new WrongFlow(info, mname, e.serialize, desired, flow)) } case _ => } } - def check_genders_e (info:Info, mname: String, genders: GenderMap)(e:Expression): Unit = { + def check_flows_e (info:Info, mname: String, flows: FlowMap)(e:Expression): Unit = { e match { - case e: Mux => e foreach check_gender(info, mname, genders, MALE) - case e: DoPrim => e.args foreach check_gender(info, mname, genders, MALE) + case e: Mux => e foreach check_flow(info, mname, flows, SourceFlow) + case e: DoPrim => e.args foreach check_flow(info, mname, flows, SourceFlow) case _ => } - e foreach check_genders_e(info, mname, genders) + e foreach check_flows_e(info, mname, flows) } - def check_genders_s(minfo: Info, mname: String, genders: GenderMap)(s: Statement): Unit = { + def check_flows_s(minfo: Info, mname: String, flows: FlowMap)(s: Statement): Unit = { val info = get_info(s) match { case NoInfo => minfo case x => x } s match { - case (s: DefWire) => genders(s.name) = BIGENDER - case (s: DefRegister) => genders(s.name) = BIGENDER - case (s: DefMemory) => genders(s.name) = MALE - case (s: WDefInstance) => genders(s.name) = MALE + case (s: DefWire) => flows(s.name) = DuplexFlow + case (s: DefRegister) => flows(s.name) = DuplexFlow + case (s: DefMemory) => flows(s.name) = SourceFlow + case (s: WDefInstance) => flows(s.name) = SourceFlow case (s: DefNode) => - check_gender(info, mname, genders, MALE)(s.value) - genders(s.name) = MALE + check_flow(info, mname, flows, SourceFlow)(s.value) + flows(s.name) = SourceFlow case (s: Connect) => - check_gender(info, mname, genders, FEMALE)(s.loc) - check_gender(info, mname, genders, MALE)(s.expr) + check_flow(info, mname, flows, SinkFlow)(s.loc) + check_flow(info, mname, flows, SourceFlow)(s.expr) case (s: Print) => - s.args foreach check_gender(info, mname, genders, MALE) - check_gender(info, mname, genders, MALE)(s.en) - check_gender(info, mname, genders, MALE)(s.clk) + s.args foreach check_flow(info, mname, flows, SourceFlow) + check_flow(info, mname, flows, SourceFlow)(s.en) + check_flow(info, mname, flows, SourceFlow)(s.clk) case (s: PartialConnect) => - check_gender(info, mname, genders, FEMALE)(s.loc) - check_gender(info, mname, genders, MALE)(s.expr) + check_flow(info, mname, flows, SinkFlow)(s.loc) + check_flow(info, mname, flows, SourceFlow)(s.expr) case (s: Conditionally) => - check_gender(info, mname, genders, MALE)(s.pred) + check_flow(info, mname, flows, SourceFlow)(s.pred) case (s: Stop) => - check_gender(info, mname, genders, MALE)(s.en) - check_gender(info, mname, genders, MALE)(s.clk) + check_flow(info, mname, flows, SourceFlow)(s.en) + check_flow(info, mname, flows, SourceFlow)(s.clk) case _ => } - s foreach check_genders_e(info, mname, genders) - s foreach check_genders_s(minfo, mname, genders) + s foreach check_flows_e(info, mname, flows) + s foreach check_flows_s(minfo, mname, flows) } for (m <- c.modules) { - val genders = new GenderMap - genders ++= (m.ports map (p => p.name -> to_gender(p.direction))) - m foreach check_genders_s(m.info, m.name, genders) + val flows = new FlowMap + flows ++= (m.ports map (p => p.name -> to_flow(p.direction))) + m foreach check_flows_s(m.info, m.name, flows) } errors.trigger() c } } + +@deprecated("Use 'CheckFlows'. This object will be removed in 1.3", "1.2") +object CheckGenders { + + implicit def toStr(g: Gender): String = g match { + case MALE => "source" + case FEMALE => "sink" + case UNKNOWNGENDER => "unknown" + case BIGENDER => "sourceOrSink" + } + + def run(c: Circuit): Circuit = CheckFlows.run(c) + + @deprecated("Use 'CheckFlows.WrongFlow'. This class will be removed in 1.3", "1.2") + class WrongGender(info:Info, mname: String, expr: String, wrong: Flow, right: Flow) extends PassException( + s"$info: [module $mname] Expression $expr is used as a $wrong but can only be used as a $right.") +} diff --git a/src/main/scala/firrtl/passes/CommonSubexpressionElimination.scala b/src/main/scala/firrtl/passes/CommonSubexpressionElimination.scala index f5b9d00c..3ba12b2d 100644 --- a/src/main/scala/firrtl/passes/CommonSubexpressionElimination.scala +++ b/src/main/scala/firrtl/passes/CommonSubexpressionElimination.scala @@ -13,10 +13,10 @@ object CommonSubexpressionElimination extends Pass { val nodes = collection.mutable.HashMap[String, Expression]() def eliminateNodeRef(e: Expression): Expression = e match { - case WRef(name, tpe, kind, gender) => nodes get name match { + case WRef(name, tpe, kind, flow) => nodes get name match { case Some(expression) => expressions get expression match { case Some(cseName) if cseName != name => - WRef(cseName, tpe, kind, gender) + WRef(cseName, tpe, kind, flow) case _ => e } case _ => e diff --git a/src/main/scala/firrtl/passes/ExpandWhens.scala b/src/main/scala/firrtl/passes/ExpandWhens.scala index a8e2f2ac..12aa9690 100644 --- a/src/main/scala/firrtl/passes/ExpandWhens.scala +++ b/src/main/scala/firrtl/passes/ExpandWhens.scala @@ -108,18 +108,18 @@ object ExpandWhens extends Pass { // Return self, unchanged case stmt @ (_: DefNode | EmptyStmt) => stmt case w: DefWire => - netlist ++= (getFemaleRefs(w.name, w.tpe, BIGENDER) map (ref => we(ref) -> WVoid)) + netlist ++= (getFemaleRefs(w.name, w.tpe, DuplexFlow) map (ref => we(ref) -> WVoid)) w case w: DefMemory => - netlist ++= (getFemaleRefs(w.name, MemPortUtils.memType(w), MALE) map (ref => we(ref) -> WVoid)) + netlist ++= (getFemaleRefs(w.name, MemPortUtils.memType(w), SourceFlow) map (ref => we(ref) -> WVoid)) w case w: WDefInstance => - netlist ++= (getFemaleRefs(w.name, w.tpe, MALE).map(ref => we(ref) -> WVoid)) + netlist ++= (getFemaleRefs(w.name, w.tpe, SourceFlow).map(ref => we(ref) -> WVoid)) w // Update netlist with self reference for each female reference // Return self, unchanged case r: DefRegister => - netlist ++= (getFemaleRefs(r.name, r.tpe, BIGENDER) map (ref => we(ref) -> ref)) + netlist ++= (getFemaleRefs(r.name, r.tpe, DuplexFlow) map (ref => we(ref) -> ref)) r // For value assignments, update netlist/attaches and return EmptyStmt case c: Connect => @@ -193,12 +193,12 @@ object ExpandWhens extends Pass { EmptyStmt case _: ValidIf | _: Mux | _: DoPrim => nodes get res match { case Some(name) => - netlist(lvalue) = WRef(name, res.tpe, NodeKind, MALE) + netlist(lvalue) = WRef(name, res.tpe, NodeKind, SourceFlow) EmptyStmt case None => val name = namespace.newTemp nodes(res) = name - netlist(lvalue) = WRef(name, res.tpe, NodeKind, MALE) + netlist(lvalue) = WRef(name, res.tpe, NodeKind, SourceFlow) DefNode(sx.info, name, res) } case _ => @@ -213,7 +213,7 @@ object ExpandWhens extends Pass { val netlist = new Netlist // Add ports to netlist netlist ++= (m.ports flatMap { case Port(_, name, dir, tpe) => - getFemaleRefs(name, tpe, to_gender(dir)) map (ref => we(ref) -> WVoid) + getFemaleRefs(name, tpe, to_flow(dir)) map (ref => we(ref) -> WVoid) }) val bodyx = expandWhens(netlist, Seq(netlist), one)(m.body) (netlist, simlist, attaches, bodyx, infoMap) @@ -221,13 +221,13 @@ object ExpandWhens extends Pass { /** Returns all references to all Female leaf subcomponents of a reference */ - private def getFemaleRefs(n: String, t: Type, g: Gender): Seq[Expression] = { + private def getFemaleRefs(n: String, t: Type, g: Flow): Seq[Expression] = { val exps = create_exps(WRef(n, t, ExpKind, g)) exps.flatMap { case exp => exp.tpe match { case AnalogType(w) => None - case _ => gender(exp) match { - case (BIGENDER | FEMALE) => Some(exp) + case _ => flow(exp) match { + case (DuplexFlow | SinkFlow) => Some(exp) case _ => None } } diff --git a/src/main/scala/firrtl/passes/InferWidths.scala b/src/main/scala/firrtl/passes/InferWidths.scala index 8f663afd..9c58da2c 100644 --- a/src/main/scala/firrtl/passes/InferWidths.scala +++ b/src/main/scala/firrtl/passes/InferWidths.scala @@ -182,18 +182,18 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { rec(w) has } - + //; Forward solve //; Returns a solved list where each constraint undergoes: //; 1) Continuous Solving (using triangular solving) //; 2) Remove Cycles //; 3) Move to solved if not self-recursive val u = make_unique(l) - + //println("======== UNIQUE CONSTRAINTS ========") //for (x <- u) { println(x) } //println("====================================") - + val f = new ConstraintMap val o = ArrayBuffer[String]() for ((n, e) <- u) { @@ -219,10 +219,10 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { o += n } } - + //println("Forward Solved Constraints") //for (x <- f) println(x) - + //; Backwards Solve val b = new ConstraintMap for (i <- (o.size - 1) to 0 by -1) { @@ -281,7 +281,7 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { } def get_constraints_declared_type (t: Type): Type = t match { - case FixedType(_, p) => + case FixedType(_, p) => v += WGeq(p,IntWidth(0)) t case _ => t map get_constraints_declared_type @@ -293,7 +293,7 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { val locs = create_exps(s.loc) val exps = create_exps(s.expr) v ++= locs.zip(exps).flatMap { case (locx, expx) => - to_flip(gender(locx)) match { + to_flip(flow(locx)) match { case Default => get_constraints_t(locx.tpe, expx.tpe)//WGeq(getWidth(locx), getWidth(expx)) case Flip => get_constraints_t(expx.tpe, locx.tpe)//WGeq(getWidth(expx), getWidth(locx)) } @@ -305,7 +305,7 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { v ++= (ls flatMap {case (x, y) => val locx = locs(x) val expx = exps(y) - to_flip(gender(locx)) match { + to_flip(flow(locx)) match { case Default => get_constraints_t(locx.tpe, expx.tpe)//WGeq(getWidth(locx), getWidth(expx)) case Flip => get_constraints_t(expx.tpe, locx.tpe)//WGeq(getWidth(expx), getWidth(locx)) } @@ -317,7 +317,7 @@ class InferWidths extends Transform with ResolvedAnnotationPaths { get_constraints_t(UIntType(IntWidth(1)), s.reset.tpe)) } v ++= get_constraints_t(s.tpe, s.init.tpe) - case (s:Conditionally) => v ++= + case (s:Conditionally) => v ++= get_constraints_t(s.pred.tpe, UIntType(IntWidth(1))) ++ get_constraints_t(UIntType(IntWidth(1)), s.pred.tpe) case Attach(_, exprs) => diff --git a/src/main/scala/firrtl/passes/LowerTypes.scala b/src/main/scala/firrtl/passes/LowerTypes.scala index 8035c1ce..f52e1e6b 100644 --- a/src/main/scala/firrtl/passes/LowerTypes.scala +++ b/src/main/scala/firrtl/passes/LowerTypes.scala @@ -39,21 +39,21 @@ object LowerTypes extends Transform { } def loweredName(s: Seq[String]): String = s mkString delim def renameExps(renames: RenameMap, n: String, t: Type, root: String): Seq[String] = - renameExps(renames, WRef(n, t, ExpKind, UNKNOWNGENDER), root) + renameExps(renames, WRef(n, t, ExpKind, UnknownFlow), root) def renameExps(renames: RenameMap, n: String, t: Type): Seq[String] = - renameExps(renames, WRef(n, t, ExpKind, UNKNOWNGENDER), "") + renameExps(renames, WRef(n, t, ExpKind, UnknownFlow), "") def renameExps(renames: RenameMap, e: Expression, root: String): Seq[String] = e.tpe match { case (_: GroundType) => val name = root + loweredName(e) renames.rename(root + e.serialize, name) Seq(name) case (t: BundleType) => t.fields.flatMap { f => - val subNames = renameExps(renames, WSubField(e, f.name, f.tpe, times(gender(e), f.flip)), root) + val subNames = renameExps(renames, WSubField(e, f.name, f.tpe, times(flow(e), f.flip)), root) renames.rename(root + e.serialize, subNames) subNames } case (t: VectorType) => (0 until t.size).flatMap { i => - val subNames = renameExps(renames, WSubIndex(e, i, t.tpe,gender(e)), root) + val subNames = renameExps(renames, WSubIndex(e, i, t.tpe,flow(e)), root) renames.rename(root + e.serialize, subNames) subNames } @@ -67,14 +67,14 @@ object LowerTypes extends Transform { renames.rename(hiRef.serialize, loRef.serialize) Seq(loRef.serialize) case (t: BundleType) => t.fields.foldLeft(Seq[String]()){(names, f) => - val subNames = renameMemExps(renames, WSubField(e, f.name, f.tpe, times(gender(e), f.flip)), portAndField) + val subNames = renameMemExps(renames, WSubField(e, f.name, f.tpe, times(flow(e), f.flip)), portAndField) val (mem, tail) = splitRef(e) val hiRef = mergeRef(mem, mergeRef(portAndField, tail)) renames.rename(hiRef.serialize, subNames) names ++ subNames } case (t: VectorType) => (0 until t.size).foldLeft(Seq[String]()){(names, i) => - val subNames = renameMemExps(renames, WSubIndex(e, i, t.tpe,gender(e)), portAndField) + val subNames = renameMemExps(renames, WSubIndex(e, i, t.tpe,flow(e)), portAndField) val (mem, tail) = splitRef(e) val hiRef = mergeRef(mem, mergeRef(portAndField, tail)) renames.rename(hiRef.serialize, subNames) @@ -116,7 +116,7 @@ object LowerTypes extends Transform { case _: GroundType => Seq(e) case memType => create_exps(mem.name, memType) map { e => val loMemName = loweredName(e) - val loMem = WRef(loMemName, UnknownType, kind(mem), UNKNOWNGENDER) + val loMem = WRef(loMemName, UnknownType, kind(mem), UnknownFlow) mergeRef(loMem, mergeRef(port, field)) } } @@ -128,7 +128,7 @@ object LowerTypes extends Transform { case Some(ex) => val loMemExp = mergeRef(mem, ex) val loMemName = loweredName(loMemExp) - WRef(loMemName, UnknownType, kind(mem), UNKNOWNGENDER) + WRef(loMemName, UnknownType, kind(mem), UnknownFlow) case None => mem } Seq(mergeRef(loMem, mergeRef(port, field))) @@ -143,15 +143,15 @@ object LowerTypes extends Transform { case InstanceKind => val (root, tail) = splitRef(e) val name = loweredName(tail) - WSubField(root, name, e.tpe, gender(e)) + WSubField(root, name, e.tpe, flow(e)) case MemKind => val exps = lowerTypesMemExp(memDataTypeMap, info, mname)(e) exps.size match { case 1 => exps.head - case _ => error("Error! lowerTypesExp called on MemKind " + + case _ => error("Error! lowerTypesExp called on MemKind " + "SubField that needs to be expanded!")(info, mname) } - case _ => WRef(loweredName(e), e.tpe, kind(e), gender(e)) + case _ => WRef(loweredName(e), e.tpe, kind(e), flow(e)) } case e: Mux => e map lowerTypesExp(memDataTypeMap, info, mname) case e: ValidIf => e map lowerTypesExp(memDataTypeMap, info, mname) @@ -164,11 +164,11 @@ object LowerTypes extends Transform { s map lowerTypesStmt(memDataTypeMap, info, mname, renames) match { case s: DefWire => s.tpe match { case _: GroundType => s - case _ => + case _ => val exps = create_exps(s.name, s.tpe) val names = exps map loweredName renameExps(renames, s.name, s.tpe) - Block((exps zip names) map { case (e, n) => + Block((exps zip names) map { case (e, n) => DefWire(s.info, n, e.tpe) }) } @@ -190,9 +190,9 @@ object LowerTypes extends Transform { case t: BundleType => val fieldsx = t.fields flatMap { f => renameExps(renames, f.name, f.tpe, s"${sx.name}.") - create_exps(WRef(f.name, f.tpe, ExpKind, times(f.flip, MALE))) map { e => - // Flip because inst genders are reversed from Module type - Field(loweredName(e), swap(to_flip(gender(e))), e.tpe) + create_exps(WRef(f.name, f.tpe, ExpKind, times(f.flip, SourceFlow))) map { e => + // Flip because inst flows are reversed from Module type + Field(loweredName(e), swap(to_flip(flow(e))), e.tpe) } } WDefInstance(sx.info, sx.name, sx.module, BundleType(fieldsx)) @@ -262,11 +262,11 @@ object LowerTypes extends Transform { renames.setModule(m.name) // Lower Ports val portsx = m.ports flatMap { p => - val exps = create_exps(WRef(p.name, p.tpe, PortKind, to_gender(p.direction))) + val exps = create_exps(WRef(p.name, p.tpe, PortKind, to_flow(p.direction))) val names = exps map loweredName renameExps(renames, p.name, p.tpe) (exps zip names) map { case (e, n) => - Port(p.info, n, to_dir(gender(e)), e.tpe) + Port(p.info, n, to_dir(flow(e)), e.tpe) } } m match { @@ -285,4 +285,3 @@ object LowerTypes extends Transform { CircuitState(result, outputForm, state.annotations, Some(renames)) } } - diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala index 1428ea5f..9a644dc8 100644 --- a/src/main/scala/firrtl/passes/Passes.scala +++ b/src/main/scala/firrtl/passes/Passes.scala @@ -48,10 +48,10 @@ class Errors { // These should be distributed into separate files object ToWorkingIR extends Pass { def toExp(e: Expression): Expression = e map toExp match { - case ex: Reference => WRef(ex.name, ex.tpe, UnknownKind, UNKNOWNGENDER) - case ex: SubField => WSubField(ex.expr, ex.name, ex.tpe, UNKNOWNGENDER) - case ex: SubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, UNKNOWNGENDER) - case ex: SubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, UNKNOWNGENDER) + case ex: Reference => WRef(ex.name, ex.tpe, UnknownKind, UnknownFlow) + case ex: SubField => WSubField(ex.expr, ex.name, ex.tpe, UnknownFlow) + case ex: SubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, UnknownFlow) + case ex: SubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, UnknownFlow) case ex => ex // This might look like a case to use case _ => e, DO NOT! } @@ -69,26 +69,26 @@ object PullMuxes extends Pass { def pull_muxes_e(e: Expression): Expression = e map pull_muxes_e match { case ex: WSubField => ex.expr match { case exx: Mux => Mux(exx.cond, - WSubField(exx.tval, ex.name, ex.tpe, ex.gender), - WSubField(exx.fval, ex.name, ex.tpe, ex.gender), ex.tpe) + WSubField(exx.tval, ex.name, ex.tpe, ex.flow), + WSubField(exx.fval, ex.name, ex.tpe, ex.flow), ex.tpe) case exx: ValidIf => ValidIf(exx.cond, - WSubField(exx.value, ex.name, ex.tpe, ex.gender), ex.tpe) + WSubField(exx.value, ex.name, ex.tpe, ex.flow), ex.tpe) case _ => ex // case exx => exx causes failed tests } case ex: WSubIndex => ex.expr match { case exx: Mux => Mux(exx.cond, - WSubIndex(exx.tval, ex.value, ex.tpe, ex.gender), - WSubIndex(exx.fval, ex.value, ex.tpe, ex.gender), ex.tpe) + WSubIndex(exx.tval, ex.value, ex.tpe, ex.flow), + WSubIndex(exx.fval, ex.value, ex.tpe, ex.flow), ex.tpe) case exx: ValidIf => ValidIf(exx.cond, - WSubIndex(exx.value, ex.value, ex.tpe, ex.gender), ex.tpe) + WSubIndex(exx.value, ex.value, ex.tpe, ex.flow), ex.tpe) case _ => ex // case exx => exx causes failed tests } case ex: WSubAccess => ex.expr match { case exx: Mux => Mux(exx.cond, - WSubAccess(exx.tval, ex.index, ex.tpe, ex.gender), - WSubAccess(exx.fval, ex.index, ex.tpe, ex.gender), ex.tpe) + WSubAccess(exx.tval, ex.index, ex.tpe, ex.flow), + WSubAccess(exx.fval, ex.index, ex.tpe, ex.flow), ex.tpe) case exx: ValidIf => ValidIf(exx.cond, - WSubAccess(exx.value, ex.index, ex.tpe, ex.gender), ex.tpe) + WSubAccess(exx.value, ex.index, ex.tpe, ex.flow), ex.tpe) case _ => ex // case exx => exx causes failed tests } case ex => ex @@ -105,29 +105,29 @@ object PullMuxes extends Pass { object ExpandConnects extends Pass { def run(c: Circuit): Circuit = { def expand_connects(m: Module): Module = { - val genders = collection.mutable.LinkedHashMap[String,Gender]() + val flows = collection.mutable.LinkedHashMap[String,Flow]() def expand_s(s: Statement): Statement = { - def set_gender(e: Expression): Expression = e map set_gender match { - case ex: WRef => WRef(ex.name, ex.tpe, ex.kind, genders(ex.name)) + def set_flow(e: Expression): Expression = e map set_flow match { + case ex: WRef => WRef(ex.name, ex.tpe, ex.kind, flows(ex.name)) case ex: WSubField => val f = get_field(ex.expr.tpe, ex.name) - val genderx = times(gender(ex.expr), f.flip) - WSubField(ex.expr, ex.name, ex.tpe, genderx) - case ex: WSubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, gender(ex.expr)) - case ex: WSubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, gender(ex.expr)) + val flowx = times(flow(ex.expr), f.flip) + WSubField(ex.expr, ex.name, ex.tpe, flowx) + case ex: WSubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, flow(ex.expr)) + case ex: WSubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, flow(ex.expr)) case ex => ex } s match { - case sx: DefWire => genders(sx.name) = BIGENDER; sx - case sx: DefRegister => genders(sx.name) = BIGENDER; sx - case sx: WDefInstance => genders(sx.name) = MALE; sx - case sx: DefMemory => genders(sx.name) = MALE; sx - case sx: DefNode => genders(sx.name) = MALE; sx + case sx: DefWire => flows(sx.name) = DuplexFlow; sx + case sx: DefRegister => flows(sx.name) = DuplexFlow; sx + case sx: WDefInstance => flows(sx.name) = SourceFlow; sx + case sx: DefMemory => flows(sx.name) = SourceFlow; sx + case sx: DefNode => flows(sx.name) = SourceFlow; sx case sx: IsInvalid => val invalids = create_exps(sx.expr).flatMap { case expx => - gender(set_gender(expx)) match { - case BIGENDER => Some(IsInvalid(sx.info, expx)) - case FEMALE => Some(IsInvalid(sx.info, expx)) + flow(set_flow(expx)) match { + case DuplexFlow => Some(IsInvalid(sx.info, expx)) + case SinkFlow => Some(IsInvalid(sx.info, expx)) case _ => None } } @@ -140,7 +140,7 @@ object ExpandConnects extends Pass { val locs = create_exps(sx.loc) val exps = create_exps(sx.expr) Block(locs.zip(exps).map { case (locx, expx) => - to_flip(gender(locx)) match { + to_flip(flow(locx)) match { case Default => Connect(sx.info, locx, expx) case Flip => Connect(sx.info, expx, locx) } @@ -153,7 +153,7 @@ object ExpandConnects extends Pass { locs(x).tpe match { case AnalogType(_) => Attach(sx.info, Seq(locs(x), exps(y))) case _ => - to_flip(gender(locs(x))) match { + to_flip(flow(locs(x))) match { case Default => Connect(sx.info, locs(x), exps(y)) case Flip => Connect(sx.info, exps(y), locs(x)) } @@ -164,7 +164,7 @@ object ExpandConnects extends Pass { } } - m.ports.foreach { p => genders(p.name) = to_gender(p.direction) } + m.ports.foreach { p => flows(p.name) = to_flow(p.direction) } Module(m.info, m.name, m.ports, expand_s(m.body)) } @@ -302,13 +302,13 @@ object VerilogPrep extends Pass { def run(c: Circuit): Circuit = { def lowerE(e: Expression): Expression = e match { case (_: WRef | _: WSubField) if kind(e) == InstanceKind => - WRef(LowerTypes.loweredName(e), e.tpe, kind(e), gender(e)) + WRef(LowerTypes.loweredName(e), e.tpe, kind(e), flow(e)) case _ => e map lowerE } def lowerS(attachMap: AttachSourceMap)(s: Statement): Statement = s match { case WDefInstance(info, name, module, tpe) => - val portRefs = create_exps(WRef(name, tpe, ExpKind, MALE)) + val portRefs = create_exps(WRef(name, tpe, ExpKind, SourceFlow)) val (portCons, wires) = portRefs.map { p => attachMap.get(p) match { // If it has a source in attachMap use that diff --git a/src/main/scala/firrtl/passes/RemoveAccesses.scala b/src/main/scala/firrtl/passes/RemoveAccesses.scala index 2cad4c36..1c2dc096 100644 --- a/src/main/scala/firrtl/passes/RemoveAccesses.scala +++ b/src/main/scala/firrtl/passes/RemoveAccesses.scala @@ -85,7 +85,7 @@ class RemoveAccesses extends Pass { def onStmt(s: Statement): Statement = { def create_temp(e: Expression): (Statement, Expression) = { val n = namespace.newName(niceName(e)) - (DefWire(get_info(s), n, e.tpe), WRef(n, e.tpe, kind(e), gender(e))) + (DefWire(get_info(s), n, e.tpe), WRef(n, e.tpe, kind(e), flow(e))) } /** Replaces a subaccess in a given male expression @@ -134,7 +134,7 @@ class RemoveAccesses extends Pass { * Otherwise, map to children. */ def fixMale(e: Expression): Expression = e match { - case w: WSubAccess => removeMale(WSubAccess(w.expr, fixMale(w.index), w.tpe, w.gender)) + case w: WSubAccess => removeMale(WSubAccess(w.expr, fixMale(w.index), w.tpe, w.flow)) //case w: WSubIndex => removeMale(w) //case w: WSubField => removeMale(w) case x => x map fixMale @@ -145,7 +145,7 @@ class RemoveAccesses extends Pass { * Otherwise, map to children. */ def fixFemale(e: Expression): Expression = e match { - case w: WSubAccess => WSubAccess(fixFemale(w.expr), fixMale(w.index), w.tpe, w.gender) + case w: WSubAccess => WSubAccess(fixFemale(w.expr), fixMale(w.index), w.tpe, w.flow) case x => x map fixFemale } @@ -159,7 +159,7 @@ class RemoveAccesses extends Pass { } Module(m.info, m.name, m.ports, squashEmpty(onStmt(m.body))) } - + c copy (modules = c.modules map { case m: ExtModule => m case m: Module => remove_m(m) diff --git a/src/main/scala/firrtl/passes/RemoveCHIRRTL.scala b/src/main/scala/firrtl/passes/RemoveCHIRRTL.scala index 0ccb0b34..d0498cf0 100644 --- a/src/main/scala/firrtl/passes/RemoveCHIRRTL.scala +++ b/src/main/scala/firrtl/passes/RemoveCHIRRTL.scala @@ -178,41 +178,41 @@ object RemoveCHIRRTL extends Transform { var has_write_mport = false var has_readwrite_mport: Option[Expression] = None var has_read_mport: Option[Expression] = None - def remove_chirrtl_e(g: Gender)(e: Expression): Expression = e match { + def remove_chirrtl_e(g: Flow)(e: Expression): Expression = e match { case Reference(name, tpe) => refs get name match { case Some(p) => g match { - case FEMALE => + case SinkFlow => has_write_mport = true if (p.rdwrite) has_readwrite_mport = Some(SubField(p.exp, "wmode", BoolType)) SubField(p.exp, p.female, tpe) - case MALE => + case SourceFlow => SubField(p.exp, p.male, tpe) } case None => g match { - case FEMALE => raddrs get name match { + case SinkFlow => raddrs get name match { case Some(en) => has_read_mport = Some(en) ; e case None => e } - case MALE => e + case SourceFlow => e } } case SubAccess(expr, index, tpe) => SubAccess( - remove_chirrtl_e(g)(expr), remove_chirrtl_e(MALE)(index), tpe) + remove_chirrtl_e(g)(expr), remove_chirrtl_e(SourceFlow)(index), tpe) case ex => ex map remove_chirrtl_e(g) } s match { case DefNode(info, name, value) => - val valuex = remove_chirrtl_e(MALE)(value) + val valuex = remove_chirrtl_e(SourceFlow)(value) val sx = DefNode(info, name, valuex) // Check node is used for read port address - remove_chirrtl_e(FEMALE)(Reference(name, value.tpe)) + remove_chirrtl_e(SinkFlow)(Reference(name, value.tpe)) has_read_mport match { case None => sx case Some(en) => Block(Seq(sx, Connect(info, en, one))) } case Connect(info, loc, expr) => - val rocx = remove_chirrtl_e(MALE)(expr) - val locx = remove_chirrtl_e(FEMALE)(loc) + val rocx = remove_chirrtl_e(SourceFlow)(expr) + val locx = remove_chirrtl_e(SinkFlow)(loc) val sx = Connect(info, locx, rocx) val stmts = ArrayBuffer[Statement]() has_read_mport match { @@ -229,8 +229,8 @@ object RemoveCHIRRTL extends Transform { } if (stmts.isEmpty) sx else Block(sx +: stmts) case PartialConnect(info, loc, expr) => - val locx = remove_chirrtl_e(FEMALE)(loc) - val rocx = remove_chirrtl_e(MALE)(expr) + val locx = remove_chirrtl_e(SinkFlow)(loc) + val rocx = remove_chirrtl_e(SourceFlow)(expr) val sx = PartialConnect(info, locx, rocx) val stmts = ArrayBuffer[Statement]() has_read_mport match { @@ -247,7 +247,7 @@ object RemoveCHIRRTL extends Transform { } } if (stmts.isEmpty) sx else Block(sx +: stmts) - case sx => sx map remove_chirrtl_s(refs, raddrs) map remove_chirrtl_e(MALE) + case sx => sx map remove_chirrtl_s(refs, raddrs) map remove_chirrtl_e(SourceFlow) } } diff --git a/src/main/scala/firrtl/passes/Resolves.scala b/src/main/scala/firrtl/passes/Resolves.scala index e4a06525..24dcda4a 100644 --- a/src/main/scala/firrtl/passes/Resolves.scala +++ b/src/main/scala/firrtl/passes/Resolves.scala @@ -22,7 +22,7 @@ object ResolveKinds extends Pass { case sx: WDefInstance => kinds(sx.name) = InstanceKind case sx: DefMemory => kinds(sx.name) = MemKind case _ => - } + } s map find_stmt(kinds) } @@ -40,14 +40,14 @@ object ResolveKinds extends Pass { map find_stmt(kinds) map resolve_stmt(kinds)) } - + def run(c: Circuit): Circuit = c copy (modules = c.modules map resolve_kinds) } -object ResolveGenders extends Pass { - def resolve_e(g: Gender)(e: Expression): Expression = e match { - case ex: WRef => ex copy (gender = g) +object ResolveFlows extends Pass { + def resolve_e(g: Flow)(e: Expression): Expression = e match { + case ex: WRef => ex copy (flow = g) case WSubField(exp, name, tpe, _) => WSubField( Utils.field_flip(exp.tpe, name) match { case Default => resolve_e(g)(exp) @@ -56,25 +56,36 @@ object ResolveGenders extends Pass { case WSubIndex(exp, value, tpe, _) => WSubIndex(resolve_e(g)(exp), value, tpe, g) case WSubAccess(exp, index, tpe, _) => - WSubAccess(resolve_e(g)(exp), resolve_e(MALE)(index), tpe, g) + WSubAccess(resolve_e(g)(exp), resolve_e(SourceFlow)(index), tpe, g) case _ => e map resolve_e(g) } - + def resolve_s(s: Statement): Statement = s match { //TODO(azidar): pretty sure don't need to do anything for Attach, but not positive... case IsInvalid(info, expr) => - IsInvalid(info, resolve_e(FEMALE)(expr)) + IsInvalid(info, resolve_e(SinkFlow)(expr)) case Connect(info, loc, expr) => - Connect(info, resolve_e(FEMALE)(loc), resolve_e(MALE)(expr)) + Connect(info, resolve_e(SinkFlow)(loc), resolve_e(SourceFlow)(expr)) case PartialConnect(info, loc, expr) => - PartialConnect(info, resolve_e(FEMALE)(loc), resolve_e(MALE)(expr)) - case sx => sx map resolve_e(MALE) map resolve_s + PartialConnect(info, resolve_e(SinkFlow)(loc), resolve_e(SourceFlow)(expr)) + case sx => sx map resolve_e(SourceFlow) map resolve_s } - def resolve_gender(m: DefModule): DefModule = m map resolve_s + def resolve_flow(m: DefModule): DefModule = m map resolve_s def run(c: Circuit): Circuit = - c copy (modules = c.modules map resolve_gender) + c copy (modules = c.modules map resolve_flow) +} + +@deprecated("Use 'ResolveFlows'. This will be removed in 1.3", "1.2") +object ResolveGenders { + + def run(c: Circuit): Circuit = ResolveFlows.run(c) + + def resolve_e(g: Gender)(e: Expression): Expression = ResolveFlows.resolve_e(g)(e) + + def resolve_s(s: Statement): Statement = ResolveFlows.resolve_s(s) + } object CInferMDir extends Pass { @@ -111,7 +122,7 @@ object CInferMDir extends Pass { case e => e map infer_mdir_e(mports, dir) } - def infer_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { + def infer_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { case sx: CDefMPort => mports(sx.name) = sx.direction sx map infer_mdir_e(mports, MRead) @@ -125,17 +136,17 @@ object CInferMDir extends Pass { sx case sx => sx map infer_mdir_s(mports) map infer_mdir_e(mports, MRead) } - - def set_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { + + def set_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { case sx: CDefMPort => sx copy (direction = mports(sx.name)) case sx => sx map set_mdir_s(mports) } - + def infer_mdir(m: DefModule): DefModule = { val mports = new MPortDirMap m map infer_mdir_s(mports) map set_mdir_s(mports) } - + def run(c: Circuit): Circuit = c copy (modules = c.modules map infer_mdir) } diff --git a/src/main/scala/firrtl/passes/SplitExpressions.scala b/src/main/scala/firrtl/passes/SplitExpressions.scala index a32f5366..de955c9a 100644 --- a/src/main/scala/firrtl/passes/SplitExpressions.scala +++ b/src/main/scala/firrtl/passes/SplitExpressions.scala @@ -5,7 +5,7 @@ package passes import firrtl.ir._ import firrtl.Mappers._ -import firrtl.Utils.{kind, gender, get_info} +import firrtl.Utils.{kind, flow, get_info} // Datastructures import scala.collection.mutable @@ -23,15 +23,15 @@ object SplitExpressions extends Pass { case e: DoPrim => val name = namespace.newTemp v += DefNode(get_info(s), name, e) - WRef(name, e.tpe, kind(e), gender(e)) + WRef(name, e.tpe, kind(e), flow(e)) case e: Mux => val name = namespace.newTemp v += DefNode(get_info(s), name, e) - WRef(name, e.tpe, kind(e), gender(e)) + WRef(name, e.tpe, kind(e), flow(e)) case e: ValidIf => val name = namespace.newTemp v += DefNode(get_info(s), name, e) - WRef(name, e.tpe, kind(e), gender(e)) + WRef(name, e.tpe, kind(e), flow(e)) case _ => e } diff --git a/src/main/scala/firrtl/passes/Uniquify.scala b/src/main/scala/firrtl/passes/Uniquify.scala index 52a2f95e..978ccc66 100644 --- a/src/main/scala/firrtl/passes/Uniquify.scala +++ b/src/main/scala/firrtl/passes/Uniquify.scala @@ -155,7 +155,7 @@ object Uniquify extends Transform { case e: WRef => if (m.contains(e.name)) { val node = m(e.name) - (WRef(node.name, e.tpe, e.kind, e.gender), node.elts) + (WRef(node.name, e.tpe, e.kind, e.flow), node.elts) } else (e, Map()) case e: WSubField => @@ -167,14 +167,14 @@ object Uniquify extends Transform { } else { (e.name, Map[String, NameMapNode]()) } - (WSubField(subExp, retName, e.tpe, e.gender), retMap) + (WSubField(subExp, retName, e.tpe, e.flow), retMap) case e: WSubIndex => val (subExp, subMap) = rec(e.expr, m) - (WSubIndex(subExp, e.value, e.tpe, e.gender), subMap) + (WSubIndex(subExp, e.value, e.tpe, e.flow), subMap) case e: WSubAccess => val (subExp, subMap) = rec(e.expr, m) val index = uniquifyNamesExp(e.index, map) - (WSubAccess(subExp, index, e.tpe, e.gender), subMap) + (WSubAccess(subExp, index, e.tpe, e.flow), subMap) case (_: UIntLiteral | _: SIntLiteral) => (exp, m) case (_: Mux | _: ValidIf | _: DoPrim) => (exp map ((e: Expression) => uniquifyNamesExp(e, map)), m) @@ -265,7 +265,7 @@ object Uniquify extends Transform { if (nameMap.contains(sx.name)) { val node = nameMap(sx.name) val newType = uniquifyNamesType(sx.tpe, node.elts) - (Utils.create_exps(sx.name, sx.tpe) zip Utils.create_exps(node.name, newType)) foreach { + (Utils.create_exps(sx.name, sx.tpe) zip Utils.create_exps(node.name, newType)) foreach { case (from, to) => renames.rename(from.serialize, to.serialize) } DefWire(sx.info, node.name, newType) @@ -382,4 +382,3 @@ object Uniquify extends Transform { CircuitState(result, outputForm, state.annotations, Some(renames)) } } - diff --git a/src/main/scala/firrtl/passes/VerilogModulusCleanup.scala b/src/main/scala/firrtl/passes/VerilogModulusCleanup.scala index 330ca497..fdc81797 100644 --- a/src/main/scala/firrtl/passes/VerilogModulusCleanup.scala +++ b/src/main/scala/firrtl/passes/VerilogModulusCleanup.scala @@ -47,11 +47,11 @@ object VerilogModulusCleanup extends Pass { def removeRem(e: Expression): Expression = e match { case e: DoPrim => e.op match { - case Rem => + case Rem => val name = namespace.newTemp val newType = e mapType verilogRemWidth(e) v += DefNode(get_info(s), name, e mapType verilogRemWidth(e)) - val remRef = WRef(name, newType.tpe, kind(e), gender(e)) + val remRef = WRef(name, newType.tpe, kind(e), flow(e)) val remWidth = bitWidth(e.tpe) DoPrim(Bits, Seq(remRef), Seq(remWidth - 1, BigInt(0)), e.tpe) case _ => e diff --git a/src/main/scala/firrtl/passes/ZeroWidth.scala b/src/main/scala/firrtl/passes/ZeroWidth.scala index 6a79fe9a..83fc1b6b 100644 --- a/src/main/scala/firrtl/passes/ZeroWidth.scala +++ b/src/main/scala/firrtl/passes/ZeroWidth.scala @@ -63,14 +63,14 @@ object ZeroWidth extends Transform { } case BundleType(fields) => if (fields.isEmpty) List(expr) - else fields.flatMap(f => findRemovable(WSubField(expr, f.name, f.tpe, MALE), f.tpe)) + else fields.flatMap(f => findRemovable(WSubField(expr, f.name, f.tpe, SourceFlow), f.tpe)) case VectorType(vtpe, size) => if (size == 0) List(expr) else { // Only invoke findRemovable multiple times if a zero-width element is found - val es0 = findRemovable(WSubIndex(expr, 0, vtpe, MALE), vtpe) + val es0 = findRemovable(WSubIndex(expr, 0, vtpe, SourceFlow), vtpe) if (es0.isEmpty) es0 else { - es0 ++ (1 until size).flatMap(i => findRemovable(WSubIndex(expr, i, vtpe, MALE), vtpe)) + es0 ++ (1 until size).flatMap(i => findRemovable(WSubIndex(expr, i, vtpe, SourceFlow), vtpe)) } } } diff --git a/src/main/scala/firrtl/passes/clocklist/ClockListUtils.scala b/src/main/scala/firrtl/passes/clocklist/ClockListUtils.scala index f92a878e..b77629fc 100644 --- a/src/main/scala/firrtl/passes/clocklist/ClockListUtils.scala +++ b/src/main/scala/firrtl/passes/clocklist/ClockListUtils.scala @@ -20,8 +20,8 @@ object ClockListUtils { } val sourceList = moduleMap(lin.name) match { case ExtModule(i, n, ports, dn, p) => - val portExps = ports.flatMap{p => create_exps(WRef(p.name, p.tpe, PortKind, to_gender(p.direction)))} - portExps.filter(e => (e.tpe == ClockType) && (gender(e) == FEMALE)).map(_.serialize) + val portExps = ports.flatMap{p => create_exps(WRef(p.name, p.tpe, PortKind, to_flow(p.direction)))} + portExps.filter(e => (e.tpe == ClockType) && (flow(e) == SinkFlow)).map(_.serialize) case _ => Nil } val sx = sourceList ++ s diff --git a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala index 44f45985..1e88a9b0 100644 --- a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala +++ b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala @@ -160,7 +160,7 @@ class InferReadWrite extends Transform with SeqTransformBased with HasShellOptio CheckInitialization, InferTypes, ResolveKinds, - ResolveGenders + ResolveFlows ) def execute(state: CircuitState): CircuitState = { val runTransform = state.annotations.contains(InferReadWriteAnnotation) diff --git a/src/main/scala/firrtl/passes/memlib/MemUtils.scala b/src/main/scala/firrtl/passes/memlib/MemUtils.scala index bf8b9401..b16a7424 100644 --- a/src/main/scala/firrtl/passes/memlib/MemUtils.scala +++ b/src/main/scala/firrtl/passes/memlib/MemUtils.scala @@ -29,11 +29,11 @@ object toBitMask { (mask.tpe, dataType) match { case (mt: VectorType, dt: VectorType) => seqCat((0 until mt.size).reverse map { i => - hiermask(WSubIndex(mask, i, mt.tpe, UNKNOWNGENDER), dt.tpe) + hiermask(WSubIndex(mask, i, mt.tpe, UnknownFlow), dt.tpe) }) case (mt: BundleType, dt: BundleType) => seqCat((mt.fields zip dt.fields) map { case (mf, df) => - hiermask(WSubField(mask, mf.name, mf.tpe, UNKNOWNGENDER), df.tpe) + hiermask(WSubField(mask, mf.name, mf.tpe, UnknownFlow), df.tpe) }) case (UIntType(width), dt: GroundType) if width == IntWidth(BigInt(1)) => seqCat(List.fill(bitWidth(dt).intValue)(mask)) @@ -80,9 +80,9 @@ object MemPortUtils { } def memPortField(s: DefMemory, p: String, f: String): Expression = { - val mem = WRef(s.name, memType(s), MemKind, UNKNOWNGENDER) + val mem = WRef(s.name, memType(s), MemKind, UnknownFlow) val t1 = field_type(mem.tpe, p) val t2 = field_type(t1, f) - WSubField(WSubField(mem, p, t1, UNKNOWNGENDER), f, t2, UNKNOWNGENDER) + WSubField(WSubField(mem, p, t1, UnknownFlow), f, t2, UnknownFlow) } } diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala index 6ccfd601..f3ef917b 100644 --- a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala +++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala @@ -126,7 +126,7 @@ class ReplSeqMem extends Transform with HasShellOptions { new SimpleMidTransform(InferTypes), Uniquify, new SimpleMidTransform(ResolveKinds), - new SimpleMidTransform(ResolveGenders)) + new SimpleMidTransform(ResolveFlows)) def execute(state: CircuitState): CircuitState = { val annos = state.annotations.collect { case a: ReplSeqMemAnnotation => a } diff --git a/src/main/scala/firrtl/passes/memlib/ResolveMaskGranularity.scala b/src/main/scala/firrtl/passes/memlib/ResolveMaskGranularity.scala index b552470d..41c47dce 100644 --- a/src/main/scala/firrtl/passes/memlib/ResolveMaskGranularity.scala +++ b/src/main/scala/firrtl/passes/memlib/ResolveMaskGranularity.scala @@ -38,14 +38,14 @@ object AnalysisUtils { /** Find a connection LHS's origin from a module's list of node-to-node connections * regardless of whether constant propagation has been run. * Will search past trivial primop/mux's which do not affect its origin. - * Limitations: + * Limitations: * - Only works in a module (stops @ module inputs) * - Only does trivial primop/mux's (is not complete) * TODO(shunshou): implement more equivalence cases (i.e. a + 0 = a) */ def getOrigin(connects: Connects, s: String): Expression = - getOrigin(connects)(WRef(s, UnknownType, ExpKind, UNKNOWNGENDER)) - def getOrigin(connects: Connects)(e: Expression): Expression = e match { + getOrigin(connects)(WRef(s, UnknownType, ExpKind, UnknownFlow)) + def getOrigin(connects: Connects)(e: Expression): Expression = e match { case Mux(cond, tv, fv, _) => val fvOrigin = getOrigin(connects)(fv) val tvOrigin = getOrigin(connects)(tv) @@ -58,12 +58,12 @@ object AnalysisUtils { else e case DoPrim(PrimOps.Or, args, consts, tpe) if args exists (weq(_, one)) => one case DoPrim(PrimOps.And, args, consts, tpe) if args exists (weq(_, zero)) => zero - case DoPrim(PrimOps.Bits, args, Seq(msb, lsb), tpe) => + case DoPrim(PrimOps.Bits, args, Seq(msb, lsb), tpe) => val extractionWidth = (msb - lsb) + 1 val nodeWidth = bitWidth(args.head.tpe) // if you're extracting the full bitwidth, then keep searching for origin if (nodeWidth == extractionWidth) getOrigin(connects)(args.head) else e - case DoPrim((PrimOps.AsUInt | PrimOps.AsSInt | PrimOps.AsClock), args, _, _) => + case DoPrim((PrimOps.AsUInt | PrimOps.AsSInt | PrimOps.AsClock), args, _, _) => getOrigin(connects)(args.head) // It is a correct optimization to treat ValidIf as a connection case ValidIf(cond, value, _) => getOrigin(connects)(value) diff --git a/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala b/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala index 10bcadfb..335e1121 100644 --- a/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala +++ b/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala @@ -15,7 +15,7 @@ import collection.mutable /** This pass generates delay reigsters for memories for verilog */ object VerilogMemDelays extends Pass { - val ug = UNKNOWNGENDER + val ug = UnknownFlow type Netlist = collection.mutable.HashMap[String, Expression] implicit def expToString(e: Expression): String = e.serialize private def NOT(e: Expression) = DoPrim(Not, Seq(e), Nil, BoolType) @@ -58,14 +58,14 @@ object VerilogMemDelays extends Pass { // 1) reference to the last pipe register // 2) pipe registers and connects val node = DefNode(NoInfo, namespace.newTemp, netlist(e)) - val wref = WRef(node.name, e.tpe, NodeKind, MALE) + val wref = WRef(node.name, e.tpe, NodeKind, SourceFlow) ((0 until n) foldLeft( (wref, Seq[Statement](node)) )){case ((ex, stmts), i) => val name = namespace newName s"${LowerTypes.loweredName(e)}_pipe_$i" val exx = WRef(name, e.tpe, RegKind, ug) (exx, stmts ++ Seq(DefRegister(NoInfo, name, e.tpe, clk, zero, exx)) ++ (if (i < n - 1 && WrappedExpression.weq(cond, one)) Seq(Connect(NoInfo, exx, ex)) else { val condn = namespace newName s"${LowerTypes.loweredName(e)}_en" - val condx = WRef(condn, BoolType, NodeKind, FEMALE) + val condx = WRef(condn, BoolType, NodeKind, SinkFlow) Seq(DefNode(NoInfo, condn, cond), Connect(NoInfo, exx, Mux(condx, ex, exx, e.tpe))) }) @@ -94,7 +94,7 @@ object VerilogMemDelays extends Pass { Connect(NoInfo, memPortField(mem, writer, "addr"), addr), Connect(NoInfo, memPortField(mem, writer, "data"), data) ) - + stmts ++= ((sx.readers flatMap {reader => // generate latency pipes for read ports (enable & addr) val clk = netlist(memPortField(sx, reader, "clk")) diff --git a/src/main/scala/firrtl/transforms/ConstantPropagation.scala b/src/main/scala/firrtl/transforms/ConstantPropagation.scala index b781f06c..b183e059 100644 --- a/src/main/scala/firrtl/transforms/ConstantPropagation.scala +++ b/src/main/scala/firrtl/transforms/ConstantPropagation.scala @@ -335,9 +335,9 @@ class ConstantPropagation extends Transform with ResolvedAnnotationPaths { val propagated = old match { case p: DoPrim => constPropPrim(p) case m: Mux => constPropMux(m) - case ref @ WRef(rname, _,_, MALE) if nodeMap.contains(rname) => + case ref @ WRef(rname, _,_, SourceFlow) if nodeMap.contains(rname) => constPropNodeRef(ref, nodeMap(rname)) - case ref @ WSubField(WRef(inst, _, InstanceKind, _), pname, _, MALE) => + case ref @ WSubField(WRef(inst, _, InstanceKind, _), pname, _, SourceFlow) => val module = instMap(inst) // Check constSubOutputs to see if the submodule is driving a constant constSubOutputs.get(module).flatMap(_.get(pname)).getOrElse(ref) @@ -407,7 +407,7 @@ class ConstantPropagation extends Transform with ResolvedAnnotationPaths { case ref @ WRef(rname, _,_,_) if swapMap.contains(rname) => ref.copy(name = swapMap(rname)) // Only const prop on the rhs - case ref @ WRef(rname, _,_, MALE) if nodeMap.contains(rname) => + case ref @ WRef(rname, _,_, SourceFlow) if nodeMap.contains(rname) => constPropNodeRef(ref, nodeMap(rname)) case x => x } diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala index a2f15776..308d68df 100644 --- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala +++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala @@ -108,11 +108,11 @@ class DeadCodeElimination extends Transform with ResolvedAnnotationPaths with Re depGraph.addVertex(LogicNode(mod.name, name)) case mem: DefMemory => // Treat DefMems as a node with outputs depending on the node and node depending on inputs - // From perpsective of the module or instance, MALE expressions are inputs, FEMALE are outputs - val memRef = WRef(mem.name, MemPortUtils.memType(mem), ExpKind, FEMALE) - val exprs = Utils.create_exps(memRef).groupBy(Utils.gender(_)) - val sources = exprs.getOrElse(MALE, List.empty).flatMap(getDeps(_)) - val sinks = exprs.getOrElse(FEMALE, List.empty).flatMap(getDeps(_)) + // From perpsective of the module or instance, SourceFlow expressions are inputs, SinkFlow are outputs + val memRef = WRef(mem.name, MemPortUtils.memType(mem), ExpKind, SinkFlow) + val exprs = Utils.create_exps(memRef).groupBy(Utils.flow(_)) + val sources = exprs.getOrElse(SourceFlow, List.empty).flatMap(getDeps(_)) + val sinks = exprs.getOrElse(SinkFlow, List.empty).flatMap(getDeps(_)) val memNode = getDeps(memRef) match { case Seq(node) => node } depGraph.addVertex(memNode) sinks.foreach(sink => depGraph.addPairWithEdge(sink, memNode)) diff --git a/src/main/scala/firrtl/transforms/Dedup.scala b/src/main/scala/firrtl/transforms/Dedup.scala index cd55a9a4..179ccbe4 100644 --- a/src/main/scala/firrtl/transforms/Dedup.scala +++ b/src/main/scala/firrtl/transforms/Dedup.scala @@ -439,7 +439,7 @@ object DedupModules { def rename(name: String): String = name def retype(name: String)(tpe: Type): Type = { - val exps = Utils.expandRef(WRef(name, tpe, ExpKind, UNKNOWNGENDER)) + val exps = Utils.expandRef(WRef(name, tpe, ExpKind, UnknownFlow)) refs ++= exps.map(Utils.toTarget(main, m.name)) tpe } @@ -465,7 +465,7 @@ object DedupModules { expr.tpe match { case _: GroundType => case b: BundleType => b.fields.foreach { f => onExp(WSubField(expr, f.name, f.tpe)) } - case v: VectorType => (0 until v.size).foreach { i => onExp(WSubIndex(expr, i, v.tpe, UNKNOWNGENDER)) } + case v: VectorType => (0 until v.size).foreach { i => onExp(WSubIndex(expr, i, v.tpe, UnknownFlow)) } } all += expr } diff --git a/src/main/scala/firrtl/transforms/GroupComponents.scala b/src/main/scala/firrtl/transforms/GroupComponents.scala index 70ce37aa..c617e685 100644 --- a/src/main/scala/firrtl/transforms/GroupComponents.scala +++ b/src/main/scala/firrtl/transforms/GroupComponents.scala @@ -213,7 +213,7 @@ class GroupComponents extends firrtl.Transform { added += Connect(NoInfo, WSubField(WRef(label2instance(group)), toPort), otherExp) // Return WRef with new kind (its inside the group Module now) - WRef(toPort, otherExp.tpe, PortKind, MALE) + WRef(toPort, otherExp.tpe, PortKind, SourceFlow) // case 3: source in different group case otherGroup => @@ -227,7 +227,7 @@ class GroupComponents extends firrtl.Transform { added += Connect(NoInfo, WSubField(WRef(groupInst), toPort), WSubField(WRef(otherInst), fromPort)) // Return WRef with new kind (its inside the group Module now) - WRef(toPort, otherExp.tpe, PortKind, MALE) + WRef(toPort, otherExp.tpe, PortKind, SourceFlow) } } diff --git a/src/main/scala/firrtl/transforms/TopWiring.scala b/src/main/scala/firrtl/transforms/TopWiring.scala index e884e02b..65281382 100644 --- a/src/main/scala/firrtl/transforms/TopWiring.scala +++ b/src/main/scala/firrtl/transforms/TopWiring.scala @@ -7,7 +7,7 @@ import firrtl.ir._ import firrtl.passes.{Pass, InferTypes, ResolveKinds, - ResolveGenders, + ResolveFlows, ExpandConnects } import firrtl.annotations._ @@ -227,11 +227,11 @@ class TopWiringTransform extends Transform { val passes = Seq( InferTypes, ResolveKinds, - ResolveGenders, + ResolveFlows, ExpandConnects, InferTypes, ResolveKinds, - ResolveGenders + ResolveFlows ) passes.foldLeft(circuit) { case (c: Circuit, p: Pass) => p.run(c) } } diff --git a/src/main/scala/tutorial/lesson2-working-ir/AnalyzeCircuit.scala b/src/main/scala/tutorial/lesson2-working-ir/AnalyzeCircuit.scala index e7a53ec5..87cc3c59 100644 --- a/src/main/scala/tutorial/lesson2-working-ir/AnalyzeCircuit.scala +++ b/src/main/scala/tutorial/lesson2-working-ir/AnalyzeCircuit.scala @@ -82,7 +82,7 @@ class Ledger { * creating new WIR nodes, use the following "unknown" values in the WIR node, and then call [[firrtl.ResolveAndCheck]] * at the end of your transform: * - Kind -> ExpKind - * - Gender -> UNKNOWNGENDER + * - Flow -> UnknownFlow * - Type -> UnknownType * * The following [[firrtl.CircuitForm]]s require WIR instead of IR nodes: diff --git a/src/test/scala/firrtlTests/CheckInitializationSpec.scala b/src/test/scala/firrtlTests/CheckInitializationSpec.scala index 9b1f3a9c..3af63c6e 100644 --- a/src/test/scala/firrtlTests/CheckInitializationSpec.scala +++ b/src/test/scala/firrtlTests/CheckInitializationSpec.scala @@ -16,8 +16,8 @@ class CheckInitializationSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, PullMuxes, diff --git a/src/test/scala/firrtlTests/CheckSpec.scala b/src/test/scala/firrtlTests/CheckSpec.scala index 54dc60ab..96275003 100644 --- a/src/test/scala/firrtlTests/CheckSpec.scala +++ b/src/test/scala/firrtlTests/CheckSpec.scala @@ -5,7 +5,7 @@ package firrtlTests import org.scalatest._ import firrtl.{Parser, CircuitState, UnknownForm, Transform} import firrtl.ir.Circuit -import firrtl.passes.{Pass,ToWorkingIR,CheckHighForm,ResolveKinds,InferTypes,CheckTypes,PassException,InferWidths,CheckWidths,ResolveGenders,CheckGenders} +import firrtl.passes.{Pass,ToWorkingIR,CheckHighForm,ResolveKinds,InferTypes,CheckTypes,PassException,InferWidths,CheckWidths,ResolveFlows,CheckFlows} class CheckSpec extends FlatSpec with Matchers { val defaultPasses = Seq(ToWorkingIR, CheckHighForm) @@ -176,8 +176,8 @@ class CheckSpec extends FlatSpec with Matchers { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = diff --git a/src/test/scala/firrtlTests/ChirrtlSpec.scala b/src/test/scala/firrtlTests/ChirrtlSpec.scala index aeb70c8d..fba81ec7 100644 --- a/src/test/scala/firrtlTests/ChirrtlSpec.scala +++ b/src/test/scala/firrtlTests/ChirrtlSpec.scala @@ -16,8 +16,8 @@ class ChirrtlSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, PullMuxes, diff --git a/src/test/scala/firrtlTests/ClockListTests.scala b/src/test/scala/firrtlTests/ClockListTests.scala index dde719d5..a30416b3 100644 --- a/src/test/scala/firrtlTests/ClockListTests.scala +++ b/src/test/scala/firrtlTests/ClockListTests.scala @@ -24,7 +24,7 @@ class ClockListTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths ) diff --git a/src/test/scala/firrtlTests/ConstantPropagationTests.scala b/src/test/scala/firrtlTests/ConstantPropagationTests.scala index da3e9b41..79e73c80 100644 --- a/src/test/scala/firrtlTests/ConstantPropagationTests.scala +++ b/src/test/scala/firrtlTests/ConstantPropagationTests.scala @@ -13,7 +13,7 @@ class ConstantPropagationSpec extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, new ConstantPropagation) protected def exec(input: String) = { diff --git a/src/test/scala/firrtlTests/ExpandWhensSpec.scala b/src/test/scala/firrtlTests/ExpandWhensSpec.scala index a1ac8a31..af82cc38 100644 --- a/src/test/scala/firrtlTests/ExpandWhensSpec.scala +++ b/src/test/scala/firrtlTests/ExpandWhensSpec.scala @@ -20,8 +20,8 @@ class ExpandWhensSpec extends FirrtlFlatSpec { Uniquify, ResolveKinds, InferTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, PullMuxes, @@ -141,4 +141,3 @@ class ExpandWhensSpec extends FirrtlFlatSpec { } class ExpandWhensExecutionTest extends ExecutionTest("ExpandWhens", "/passes/ExpandWhens") - diff --git a/src/test/scala/firrtlTests/LowerTypesSpec.scala b/src/test/scala/firrtlTests/LowerTypesSpec.scala index 30ef795b..be9d738b 100644 --- a/src/test/scala/firrtlTests/LowerTypesSpec.scala +++ b/src/test/scala/firrtlTests/LowerTypesSpec.scala @@ -18,8 +18,8 @@ class LowerTypesSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, PullMuxes, @@ -31,7 +31,7 @@ class LowerTypesSpec extends FirrtlFlatSpec { new ConstantPropagation, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, LowerTypes) diff --git a/src/test/scala/firrtlTests/ReplaceAccessesSpec.scala b/src/test/scala/firrtlTests/ReplaceAccessesSpec.scala index 64977c7f..e9ef3bcd 100644 --- a/src/test/scala/firrtlTests/ReplaceAccessesSpec.scala +++ b/src/test/scala/firrtlTests/ReplaceAccessesSpec.scala @@ -13,7 +13,7 @@ class ReplaceAccessesSpec extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, ReplaceAccesses) protected def exec(input: String) = { diff --git a/src/test/scala/firrtlTests/UnitTests.scala b/src/test/scala/firrtlTests/UnitTests.scala index 0ef4f709..b7df945f 100644 --- a/src/test/scala/firrtlTests/UnitTests.scala +++ b/src/test/scala/firrtlTests/UnitTests.scala @@ -95,7 +95,7 @@ class UnitTests extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, ExpandConnects) val input = """circuit Unit : @@ -157,7 +157,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, SplitExpressions ) @@ -181,7 +181,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, PadWidths ) @@ -202,7 +202,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, PullMuxes, ExpandConnects, @@ -210,8 +210,8 @@ class UnitTests extends FirrtlFlatSpec { new ConstantPropagation ) val input = - """circuit AssignViaDeref : - | module AssignViaDeref : + """circuit AssignViaDeref : + | module AssignViaDeref : | input clock : Clock | input reset : UInt<1> | output io : {a : UInt<8>, sel : UInt<1>} @@ -242,7 +242,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -261,7 +261,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -280,7 +280,7 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -388,12 +388,12 @@ class UnitTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, PullMuxes, ExpandConnects, RemoveAccesses, - ResolveGenders, + ResolveFlows, new ConstantPropagation ) val input = @@ -412,13 +412,13 @@ class UnitTests extends FirrtlFlatSpec { val ut2 = UIntType(IntWidth(BigInt(2))) val ut1 = UIntType(IntWidth(BigInt(1))) - val mgen = WRef("_array_index", ut16, WireKind, MALE) - val fgen = WRef("_array_index", ut16, WireKind, FEMALE) - val index = WRef("index", ut2, PortKind, MALE) - val out = WRef("out", ut16, PortKind, FEMALE) + val mgen = WRef("_array_index", ut16, WireKind, SourceFlow) + val fgen = WRef("_array_index", ut16, WireKind, SinkFlow) + val index = WRef("index", ut2, PortKind, SourceFlow) + val out = WRef("out", ut16, PortKind, SinkFlow) def eq(e1: Expression, e2: Expression): Expression = DoPrim(PrimOps.Eq, Seq(e1, e2), Nil, ut1) - def array(v: Int): Expression = WSubIndex(WRef("array", VectorType(ut16, 3), WireKind, MALE), v, ut16, MALE) + def array(v: Int): Expression = WSubIndex(WRef("array", VectorType(ut16, 3), WireKind, SourceFlow), v, ut16, SourceFlow) result should containTree { case DefWire(_, "_array_index", `ut16`) => true } result should containTree { case IsInvalid(_, `fgen`) => true } diff --git a/src/test/scala/firrtlTests/WidthSpec.scala b/src/test/scala/firrtlTests/WidthSpec.scala index 96bd249c..4c0e7f70 100644 --- a/src/test/scala/firrtlTests/WidthSpec.scala +++ b/src/test/scala/firrtlTests/WidthSpec.scala @@ -53,7 +53,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -76,7 +76,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -95,7 +95,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = @@ -120,7 +120,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths) val input = """circuit Unit : @@ -142,7 +142,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths) val input = """circuit Unit : @@ -165,7 +165,7 @@ class WidthSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) val input = diff --git a/src/test/scala/firrtlTests/WiringTests.scala b/src/test/scala/firrtlTests/WiringTests.scala index 4fe4a46c..ec69c39f 100644 --- a/src/test/scala/firrtlTests/WiringTests.scala +++ b/src/test/scala/firrtlTests/WiringTests.scala @@ -33,7 +33,7 @@ class WiringTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths ) diff --git a/src/test/scala/firrtlTests/ZeroWidthTests.scala b/src/test/scala/firrtlTests/ZeroWidthTests.scala index eb955f29..eb3d1a96 100644 --- a/src/test/scala/firrtlTests/ZeroWidthTests.scala +++ b/src/test/scala/firrtlTests/ZeroWidthTests.scala @@ -15,7 +15,7 @@ class ZeroWidthTests extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, ZeroWidth) private def exec (input: String) = { @@ -218,12 +218,12 @@ class ZeroWidthVerilog extends FirrtlFlatSpec { "Circuit" should "accept zero width wires" in { val compiler = new VerilogCompiler val input = - """circuit Top : - | module Top : + """circuit Top : + | module Top : | input y: UInt<0> | output x: UInt<3> | x <= y""".stripMargin - val check = + val check = """module Top( | output [2:0] x |); diff --git a/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala index 667db7b0..6bf86479 100644 --- a/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala +++ b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala @@ -28,8 +28,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -58,8 +58,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -84,8 +84,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -110,8 +110,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -136,8 +136,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -162,8 +162,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -188,8 +188,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -228,8 +228,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths) val input = @@ -254,8 +254,8 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -334,4 +334,3 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { executeTest(input("cmem"), check(0, 1, 1).split("\n") map normalized, new LowFirrtlCompiler) } } - diff --git a/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala b/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala index 21a39e83..8686bd0f 100644 --- a/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala +++ b/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala @@ -28,8 +28,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -58,8 +58,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -89,8 +89,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -116,8 +116,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -143,8 +143,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -195,8 +195,8 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, - CheckGenders, + ResolveFlows, + CheckFlows, new InferWidths, CheckWidths, ConvertFixedToSInt) @@ -215,4 +215,3 @@ class RemoveFixedTypeSpec extends FirrtlFlatSpec { executeTest(input, check.split("\n") map normalized, passes) } } - diff --git a/src/test/scala/firrtlTests/transforms/InferWidthsWithAnnosSpec.scala b/src/test/scala/firrtlTests/transforms/InferWidthsWithAnnosSpec.scala index 54a3df40..46fb310a 100644 --- a/src/test/scala/firrtlTests/transforms/InferWidthsWithAnnosSpec.scala +++ b/src/test/scala/firrtlTests/transforms/InferWidthsWithAnnosSpec.scala @@ -35,7 +35,7 @@ class InferWidthsWithAnnosSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) @@ -64,7 +64,7 @@ class InferWidthsWithAnnosSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) @@ -107,7 +107,7 @@ class InferWidthsWithAnnosSpec extends FirrtlFlatSpec { ResolveKinds, InferTypes, CheckTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths) @@ -156,7 +156,7 @@ class InferWidthsWithAnnosSpec extends FirrtlFlatSpec { ToWorkingIR, ResolveKinds, InferTypes, - ResolveGenders, + ResolveFlows, new InferWidths, CheckWidths, new WiringTransform, |
