mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Tidy/reflow some things
This commit is contained in:
		
							parent
							
								
									2c75b103d6
								
							
						
					
					
						commit
						4b40372446
					
				
					 10 changed files with 433 additions and 443 deletions
				
			
		|  | @ -189,13 +189,13 @@ values for the global asynchronous reset in an FPGA implementation. This design | |||
| can not be expressed in BLIF as it is. Instead we need to use a synthesis script | ||||
| that transforms this form to synchronous resets that can be expressed in BLIF. | ||||
| 
 | ||||
| (Note that there is no problem if this coding techniques are used to | ||||
| model ROM, where the register is initialized using this syntax but is | ||||
| never updated otherwise.) | ||||
| (Note that there is no problem if this coding techniques are used to model ROM, | ||||
| where the register is initialized using this syntax but is never updated | ||||
| otherwise.) | ||||
| 
 | ||||
| :numref:`amber23.ys` shows the synthesis script for the Amber23 core. In line 17 | ||||
| the add command is used to add a 1-bit wide global input signal with the name | ||||
| globrst. That means that an input with that name is added to each module in the | ||||
| ``globrst``. That means that an input with that name is added to each module in the | ||||
| design hierarchy and then all module instantiations are altered so that this new | ||||
| signal is connected throughout the whole design hierarchy. | ||||
| 
 | ||||
|  | @ -235,18 +235,18 @@ signal is connected throughout the whole design hierarchy. | |||
| 
 | ||||
|    endmodule | ||||
| 
 | ||||
| In line 18 the proc command is called. But in this script the signal | ||||
| name globrst is passed to the command as a global reset signal for | ||||
| resetting the registers to their assigned initial values. | ||||
| In line 18 the ``proc`` command is called. But in this script the signal name | ||||
| globrst is passed to the command as a global reset signal for resetting the | ||||
| registers to their assigned initial values. | ||||
| 
 | ||||
| Finally in line 19 the techmap command is used to replace all instances of | ||||
| flip-flops with asynchronous resets with flip-flops with synchronous resets. The | ||||
| map file used for this is shown in :numref:`adff2dff.v`. Note how the | ||||
| techmap_celltype attribute is used in line 1 to tell the techmap command which | ||||
| cells to replace in the design, how the \_TECHMAP_FAIL\_ wire in lines 15 and 16 | ||||
| (which evaluates to a constant value) determines if the parameter set is | ||||
| compatible with this replacement circuit, and how the \_TECHMAP_DO\_ wire in | ||||
| line 13 provides a mini synthesis-script to be used to process this cell. | ||||
| ``techmap_celltype`` attribute is used in line 1 to tell the techmap command | ||||
| which cells to replace in the design, how the ``_TECHMAP_FAIL_`` wire in lines | ||||
| 15 and 16 (which evaluates to a constant value) determines if the parameter set | ||||
| is compatible with this replacement circuit, and how the ``_TECHMAP_DO_`` wire | ||||
| in line 13 provides a mini synthesis-script to be used to process this cell. | ||||
| 
 | ||||
| .. code-block:: c | ||||
|    :caption: Test program for the Amber23 CPU (Sieve of Eratosthenes). Compiled  | ||||
|  | @ -298,39 +298,36 @@ format as well. | |||
| 
 | ||||
| .. _ABC: https://github.com/berkeley-abc/abc | ||||
| 
 | ||||
| The only thing left to write about the simulation itself is that it | ||||
| probably was one of the most energy inefficient and time consuming ways | ||||
| of successfully calculating the first 31 primes the author has ever | ||||
| conducted. | ||||
| The only thing left to write about the simulation itself is that it probably was | ||||
| one of the most energy inefficient and time consuming ways of successfully | ||||
| calculating the first 31 primes the author has ever conducted. | ||||
| 
 | ||||
| Limitations | ||||
| =========== | ||||
| 
 | ||||
| At the time of this writing Yosys does not support multi-dimensional | ||||
| memories, does not support writing to individual bits of array elements, | ||||
| does not support initialization of arrays with $readmemb and $readmemh, | ||||
| and has only limited support for tristate logic, to name just a few | ||||
| limitations. | ||||
| At the time of this writing Yosys does not support multi-dimensional memories, | ||||
| does not support writing to individual bits of array elements, does not support | ||||
| initialization of arrays with ``$readmemb`` and ``$readmemh``, and has only | ||||
| limited support for tristate logic, to name just a few limitations. | ||||
| 
 | ||||
| That being said, Yosys can synthesize an overwhelming majority of | ||||
| real-world Verilog RTL code. The remaining cases can usually be modified | ||||
| to be compatible with Yosys quite easily. | ||||
| That being said, Yosys can synthesize an overwhelming majority of real-world | ||||
| Verilog RTL code. The remaining cases can usually be modified to be compatible | ||||
| with Yosys quite easily. | ||||
| 
 | ||||
| The various designs in yosys-bigsim are a good place to look for | ||||
| examples of what is within the capabilities of Yosys. | ||||
| The various designs in yosys-bigsim are a good place to look for examples of | ||||
| what is within the capabilities of Yosys. | ||||
| 
 | ||||
| Conclusion | ||||
| ========== | ||||
| 
 | ||||
| Yosys is a feature-rich Verilog-2005 synthesis tool. It has many uses, | ||||
| but one is to provide an easy gateway from high-level Verilog code to | ||||
| low-level logic circuits. | ||||
| Yosys is a feature-rich Verilog-2005 synthesis tool. It has many uses, but one | ||||
| is to provide an easy gateway from high-level Verilog code to low-level logic | ||||
| circuits. | ||||
| 
 | ||||
| The command line option -S can be used to quickly synthesize Verilog | ||||
| code to BLIF files without a hassle. | ||||
| The command line option ``-S`` can be used to quickly synthesize Verilog code to | ||||
| BLIF files without a hassle. | ||||
| 
 | ||||
| With custom synthesis scripts it becomes possible to easily perform | ||||
| high-level optimizations, such as re-encoding FSMs. In some extreme | ||||
| cases, such as the Amber23 ARMv2 CPU, the more advanced Yosys features | ||||
| can be used to change a design to fit a certain need without actually | ||||
| touching the RTL code. | ||||
| With custom synthesis scripts it becomes possible to easily perform high-level | ||||
| optimizations, such as re-encoding FSMs. In some extreme cases, such as the | ||||
| Amber23 ARMv2 CPU, the more advanced Yosys features can be used to change a | ||||
| design to fit a certain need without actually touching the RTL code. | ||||
|  |  | |||
|  | @ -315,7 +315,7 @@ simply be abbreviated using the last part. | |||
| Usually all interactive work is done with one module selected using the ``cd`` | ||||
| command. But it is also possible to work from the design-context (``cd ..``). In | ||||
| this case all object names must be prefixed with ``<module_name>/``. For example | ||||
| ``a*/b\*`` would refer to all objects whose names start with ``b`` from all | ||||
| ``a*/b*`` would refer to all objects whose names start with ``b`` from all | ||||
| modules whose names start with ``a``. | ||||
| 
 | ||||
| The ``dump`` command can be used to print all information about an object. For | ||||
|  | @ -416,7 +416,7 @@ will select all ``$add ``cells that have the ``foo`` attribute set: | |||
| 
 | ||||
|    select t:$add a:foo %i | ||||
| 
 | ||||
| The listing in :numref:`sumprod` uses the Yosys non-standard ``{... \*}`` syntax | ||||
| The listing in :numref:`sumprod` uses the Yosys non-standard ``{... *}`` syntax | ||||
| to set the attribute ``sumstuff`` on all cells generated by the first assign | ||||
| statement. (This works on arbitrary large blocks of Verilog code an can be used | ||||
| to mark portions of code for analysis.) | ||||
|  | @ -467,7 +467,7 @@ be a bit dull. So there is a shortcut for that: the number of iterations can be | |||
| appended to the action. So for example the action ``%ci3`` is identical to | ||||
| performing the ``%ci`` action three times. | ||||
| 
 | ||||
| The action ``%ci\*`` performs the ``%ci`` action over and over again until it | ||||
| The action ``%ci*`` performs the ``%ci`` action over and over again until it | ||||
| has no effect anymore. | ||||
| 
 | ||||
| .. figure:: ../../images/011/select_prod.* | ||||
|  |  | |||
|  | @ -586,7 +586,7 @@ use the Token-Type to make a decision on the grammatical role of a token. | |||
| 
 | ||||
| The parser then transforms the list of tokens into a parse tree that closely | ||||
| resembles the productions from the computer languages grammar. As the lexer, the | ||||
| parser is also typically generated by a code generator (e.g. bison ) from a | ||||
| parser is also typically generated by a code generator (e.g. bison) from a | ||||
| grammar description in Backus-Naur Form (BNF). | ||||
| 
 | ||||
| Let's consider the following BNF (in Bison syntax): | ||||
|  |  | |||
|  | @ -43,15 +43,15 @@ directories: | |||
|      simulation results of the synthesized design to the original sources to | ||||
|      logic equivalence checking of entire CPU cores. | ||||
| 
 | ||||
| The top-level Makefile includes frontends/\*/Makefile.inc, | ||||
| passes/\*/Makefile.inc and backends/\*/Makefile.inc. So when extending Yosys it | ||||
| is enough to create a new directory in frontends/, passes/ or backends/ with | ||||
| your sources and a Makefile.inc. The Yosys kernel automatically detects all | ||||
| commands linked with Yosys. So it is not needed to add additional commands to a | ||||
| central list of commands. | ||||
| The top-level Makefile includes ``frontends/*/Makefile.inc``, | ||||
| ``passes/*/Makefile.inc`` and ``backends/*/Makefile.inc``. So when extending | ||||
| Yosys it is enough to create a new directory in ``frontends/``, ``passes/`` or | ||||
| ``backends/`` with your sources and a ``Makefile.inc``. The Yosys kernel | ||||
| automatically detects all commands linked with Yosys. So it is not needed to add | ||||
| additional commands to a central list of commands. | ||||
| 
 | ||||
| Good starting points for reading example source code to learn how to write | ||||
| passes are passes/opt/opt_rmdff.cc and passes/opt/opt_merge.cc. | ||||
| passes are ``passes/opt/opt_rmdff.cc`` and ``passes/opt/opt_merge.cc``. | ||||
| 
 | ||||
| See the top-level README file for a quick Getting Started guide and build | ||||
| instructions. The Yosys build is based solely on Makefiles. | ||||
|  |  | |||
|  | @ -99,14 +99,14 @@ Selections intro | |||
| ~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| Most commands can operate not only on the entire design but also specifically on | ||||
| selected parts of the design. For example the command dump will print all | ||||
| selected objects in the current design while dump foobar will only print the | ||||
| module foobar and dump \* will print the entire design regardless of the current | ||||
| selection. | ||||
| selected parts of the design. For example the command ``dump`` will print all | ||||
| selected objects in the current design while ``dump foobar`` will only print the | ||||
| module ``foobar`` and ``dump *`` will print the entire design regardless of the | ||||
| current selection. | ||||
| 
 | ||||
| .. code:: yoscrypt | ||||
| 
 | ||||
| 	dump */t:$add %x:+[A] \*/w:\* %i | ||||
| 	dump */t:$add %x:+[A] */w:* %i | ||||
| 
 | ||||
| The selection mechanism is very powerful. For example the command above will | ||||
| print all wires that are connected to the ``\A`` port of a ``$add`` cell. | ||||
|  |  | |||
|  | @ -50,15 +50,6 @@ What you can do with Yosys | |||
| - Perform all kinds of operations on netlist (RTL, Logic, Gate) | ||||
| - Perform logic optimizations and gate mapping with ABC | ||||
| 
 | ||||
| Things you can't do | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| - Process high-level languages such as C/C++/SystemC | ||||
| - Create physical layouts (place&route) | ||||
|   + Check out `nextpnr`_ for that | ||||
| 
 | ||||
| .. _nextpnr: https://github.com/YosysHQ/nextpnr | ||||
| 
 | ||||
| Typical applications for Yosys | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
|  | @ -71,12 +62,21 @@ Typical applications for Yosys | |||
| - Framework for building custom flows (Not limited to synthesis but also formal | ||||
|   verification, reverse engineering, ...) | ||||
| 
 | ||||
| Things you can't do | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| - Process high-level languages such as C/C++/SystemC | ||||
| - Create physical layouts (place&route) | ||||
|   + Check out `nextpnr`_ for that | ||||
| 
 | ||||
| .. _nextpnr: https://github.com/YosysHQ/nextpnr | ||||
| 
 | ||||
| Benefits of open source HDL synthesis | ||||
| ------------------------------------- | ||||
| 
 | ||||
| - Cost (also applies to ``free as in free beer`` solutions):  | ||||
|    | ||||
|   Today the cost for a mask set in $\unit[180]{nm}$ technology is far less than | ||||
|   Today the cost for a mask set in 180nm technology is far less than | ||||
|   the cost for the design tools needed to design the mask layouts. Open Source | ||||
|   ASIC flows are an important enabler for ASIC-level Open Source Hardware. | ||||
| 
 | ||||
|  |  | |||
|  | @ -143,7 +143,7 @@ identifies cells with identical inputs and replaces them with a single instance | |||
| of the cell. | ||||
| 
 | ||||
| The option ``-nomux`` can be used to disable resource sharing for multiplexer | ||||
| cells (``$mux`` and ``$pmux.`` This can be useful as it prevents multiplexer | ||||
| cells (``$mux`` and ``$pmux``.) This can be useful as it prevents multiplexer | ||||
| trees to be merged, which might prevent ``opt_muxtree`` to identify possible | ||||
| optimizations. | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,54 +19,53 @@ Transforming Verilog to AST | |||
| --------------------------- | ||||
| 
 | ||||
| The Verilog frontend converts the Verilog sources to an internal AST | ||||
| representation that closely resembles the structure of the original | ||||
| Verilog code. The Verilog frontend consists of three components, the | ||||
| Preprocessor, the Lexer and the Parser. | ||||
| representation that closely resembles the structure of the original Verilog | ||||
| code. The Verilog frontend consists of three components, the Preprocessor, the | ||||
| Lexer and the Parser. | ||||
| 
 | ||||
| The source code to the Verilog frontend can be found in | ||||
| frontends/verilog/ in the Yosys source tree. | ||||
| The source code to the Verilog frontend can be found in ``frontends/verilog/`` | ||||
| in the Yosys source tree. | ||||
| 
 | ||||
| The Verilog preprocessor | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| The Verilog preprocessor scans over the Verilog source code and | ||||
| interprets some of the Verilog compiler directives such as | ||||
| :literal:`\`include`, :literal:`\`define` and :literal:`\`ifdef`. | ||||
| The Verilog preprocessor scans over the Verilog source code and interprets some | ||||
| of the Verilog compiler directives such as :literal:`\`include`, | ||||
| :literal:`\`define` and :literal:`\`ifdef`. | ||||
| 
 | ||||
| It is implemented as a C++ function that is passed a file descriptor as | ||||
| input and returns the pre-processed Verilog code as a ``std::string``. | ||||
| It is implemented as a C++ function that is passed a file descriptor as input | ||||
| and returns the pre-processed Verilog code as a ``std::string``. | ||||
| 
 | ||||
| The source code to the Verilog Preprocessor can be found in | ||||
| frontends/verilog/preproc.cc in the Yosys source tree. | ||||
| ``frontends/verilog/preproc.cc`` in the Yosys source tree. | ||||
| 
 | ||||
| The Verilog lexer | ||||
| ~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| The Verilog Lexer is written using the lexer generator flex . Its source | ||||
| code can be found in frontends/verilog/verilog_lexer.l in the Yosys | ||||
| source tree. The lexer does little more than identifying all keywords | ||||
| and literals recognised by the Yosys Verilog frontend. | ||||
| The Verilog Lexer is written using the lexer generator flex. Its source code | ||||
| can be found in ``frontends/verilog/verilog_lexer.l`` in the Yosys source tree. | ||||
| The lexer does little more than identifying all keywords and literals recognised | ||||
| by the Yosys Verilog frontend. | ||||
| 
 | ||||
| The lexer keeps track of the current location in the Verilog source code | ||||
| using some global variables. These variables are used by the constructor | ||||
| of AST nodes to annotate each node with the source code location it | ||||
| originated from. | ||||
| 
 | ||||
| Finally the lexer identifies and handles special comments such as | ||||
| "``// synopsys translate_off``" and "``// synopsys full_case``". (It is | ||||
| recommended to use :literal:`\`ifdef` constructs instead of the | ||||
| Synsopsys translate_on/off comments and attributes such as | ||||
| ``(* full_case *)`` over "``// synopsys full_case``" whenever possible.) | ||||
| Finally the lexer identifies and handles special comments such as "``// synopsys | ||||
| translate_off``" and "``// synopsys full_case``". (It is recommended to use | ||||
| :literal:`\`ifdef` constructs instead of the Synsopsys translate_on/off comments | ||||
| and attributes such as ``(* full_case *)`` over "``// synopsys full_case``" | ||||
| whenever possible.) | ||||
| 
 | ||||
| The Verilog parser | ||||
| ~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| The Verilog Parser is written using the parser generator bison . Its | ||||
| source code can be found in frontends/verilog/verilog_parser.y in the | ||||
| Yosys source tree. | ||||
| The Verilog Parser is written using the parser generator bison. Its source code | ||||
| can be found in ``frontends/verilog/verilog_parser.y`` in the Yosys source tree. | ||||
| 
 | ||||
| It generates an AST using the ``AST::AstNode`` data structure defined in | ||||
| frontends/ast/ast.h. An ``AST::AstNode`` object has the following | ||||
| ``frontends/ast/ast.h``. An ``AST::AstNode`` object has the following | ||||
| properties: | ||||
| 
 | ||||
| .. list-table:: AST node types with their corresponding Verilog constructs. | ||||
|  | @ -152,35 +151,32 @@ properties: | |||
| 
 | ||||
| -  | The node type | ||||
|    | This enum (``AST::AstNodeType``) specifies the role of the node. | ||||
|      :numref:`Table %s <tab:Verilog_AstNodeType>` | ||||
|      contains a list of all node types. | ||||
|      :numref:`Table %s <tab:Verilog_AstNodeType>` contains a list of all node | ||||
|      types. | ||||
| 
 | ||||
| -  | The child nodes | ||||
|    | This is a list of pointers to all children in the abstract syntax | ||||
|      tree. | ||||
|    | This is a list of pointers to all children in the abstract syntax tree. | ||||
| 
 | ||||
| -  | Attributes | ||||
|    | As almost every AST node might have Verilog attributes assigned to | ||||
|      it, the ``AST::AstNode`` has direct support for attributes. Note | ||||
|      that the attribute values are again AST nodes. | ||||
|    | As almost every AST node might have Verilog attributes assigned to it, the | ||||
|      ``AST::AstNode`` has direct support for attributes. Note that the attribute | ||||
|      values are again AST nodes. | ||||
| 
 | ||||
| -  | Node content | ||||
|    | Each node might have additional content data. A series of member | ||||
|      variables exist to hold such data. For example the member | ||||
|      ``std::string str`` can hold a string value and is used e.g. in the | ||||
|      AST_IDENTIFIER node type to store the identifier name. | ||||
|    | Each node might have additional content data. A series of member variables | ||||
|      exist to hold such data. For example the member ``std::string str`` can | ||||
|      hold a string value and is used e.g. in the ``AST_IDENTIFIER`` node type to | ||||
|      store the identifier name. | ||||
| 
 | ||||
| -  | Source code location | ||||
|    | Each ``AST::AstNode`` is automatically annotated with the current | ||||
|      source code location by the ``AST::AstNode`` constructor. It is | ||||
|      stored in the ``std::string filename`` and ``int linenum`` member | ||||
|      variables. | ||||
|    | Each ``AST::AstNode`` is automatically annotated with the current source | ||||
|      code location by the ``AST::AstNode`` constructor. It is stored in the | ||||
|      ``std::string filename`` and ``int linenum`` member variables. | ||||
| 
 | ||||
| The ``AST::AstNode`` constructor can be called with up to two child | ||||
| nodes that are automatically added to the list of child nodes for the | ||||
| new object. This simplifies the creation of AST nodes for simple | ||||
| expressions a bit. For example the bison code for parsing | ||||
| multiplications: | ||||
| The ``AST::AstNode`` constructor can be called with up to two child nodes that | ||||
| are automatically added to the list of child nodes for the new object. This | ||||
| simplifies the creation of AST nodes for simple expressions a bit. For example | ||||
| the bison code for parsing multiplications: | ||||
| 
 | ||||
| .. code:: none | ||||
|    	:number-lines: | ||||
|  | @ -190,49 +186,50 @@ multiplications: | |||
| 		append_attr($$, $3); | ||||
| 	} | | ||||
| 
 | ||||
| The generated AST data structure is then passed directly to the AST | ||||
| frontend that performs the actual conversion to RTLIL. | ||||
| The generated AST data structure is then passed directly to the AST frontend | ||||
| that performs the actual conversion to RTLIL. | ||||
| 
 | ||||
| Note that the Yosys command ``read_verilog`` provides the options ``-yydebug`` | ||||
| and ``-dump_ast`` that can be used to print the parse tree or abstract | ||||
| syntax tree respectively. | ||||
| and ``-dump_ast`` that can be used to print the parse tree or abstract syntax | ||||
| tree respectively. | ||||
| 
 | ||||
| Transforming AST to RTLIL | ||||
| ------------------------- | ||||
| 
 | ||||
| The AST Frontend converts a set of modules in AST representation to | ||||
| modules in RTLIL representation and adds them to the current design. | ||||
| This is done in two steps: simplification and RTLIL generation. | ||||
| The AST Frontend converts a set of modules in AST representation to modules in | ||||
| RTLIL representation and adds them to the current design. This is done in two | ||||
| steps: simplification and RTLIL generation. | ||||
| 
 | ||||
| The source code to the AST frontend can be found in ``frontends/ast/`` in | ||||
| the Yosys source tree. | ||||
| The source code to the AST frontend can be found in ``frontends/ast/`` in the | ||||
| Yosys source tree. | ||||
| 
 | ||||
| AST simplification | ||||
| ~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| A full-featured AST is too complex to be transformed into RTLIL | ||||
| directly. Therefore it must first be brought into a simpler form. This | ||||
| is done by calling the ``AST::AstNode::simplify()`` method of all | ||||
| AST_MODULE nodes in the AST. This initiates a recursive process that | ||||
| performs the following transformations on the AST data structure: | ||||
| A full-featured AST is too complex to be transformed into RTLIL directly. | ||||
| Therefore it must first be brought into a simpler form. This is done by calling | ||||
| the ``AST::AstNode::simplify()`` method of all ``AST_MODULE`` nodes in the AST. | ||||
| This initiates a recursive process that performs the following transformations | ||||
| on the AST data structure: | ||||
| 
 | ||||
| -  Inline all task and function calls. | ||||
| 
 | ||||
| -  Evaluate all ``generate``-statements and unroll all ``for``-loops. | ||||
| 
 | ||||
| -  Perform const folding where it is necessary (e.g. in the value part | ||||
|    of AST_PARAMETER, AST_LOCALPARAM, AST_PARASET and AST_RANGE nodes). | ||||
| -  Perform const folding where it is necessary (e.g. in the value part of | ||||
|    ``AST_PARAMETER``, ``AST_LOCALPARAM``, ``AST_PARASET`` and ``AST_RANGE`` | ||||
|    nodes). | ||||
| 
 | ||||
| -  Replace AST_PRIMITIVE nodes with appropriate AST_ASSIGN nodes. | ||||
| -  Replace ``AST_PRIMITIVE`` nodes with appropriate ``AST_ASSIGN`` nodes. | ||||
| 
 | ||||
| -  Replace dynamic bit ranges in the left-hand-side of assignments with | ||||
|    AST_CASE nodes with AST_COND children for each possible case. | ||||
|    ``AST_CASE`` nodes with ``AST_COND`` children for each possible case. | ||||
| 
 | ||||
| -  Detect array access patterns that are too complicated for the | ||||
|    RTLIL::Memory abstraction and replace them with a set of signals and | ||||
|    ``RTLIL::Memory`` abstraction and replace them with a set of signals and | ||||
|    cases for all reads and/or writes. | ||||
| 
 | ||||
| -  Otherwise replace array accesses with AST_MEMRD and AST_MEMWR nodes. | ||||
| -  Otherwise replace array accesses with ``AST_MEMRD`` and ``AST_MEMWR`` nodes. | ||||
| 
 | ||||
| In addition to these transformations, the simplifier also annotates the | ||||
| AST with additional information that is needed for the RTLIL generator, | ||||
|  | @ -242,70 +239,66 @@ namely: | |||
|    folded but (when a constant value is found) are also written to | ||||
|    member variables in the AST_RANGE node. | ||||
| 
 | ||||
| -  All identifiers are resolved and all AST_IDENTIFIER nodes are | ||||
|    annotated with a pointer to the AST node that contains the | ||||
|    declaration of the identifier. If no declaration has been found, an | ||||
|    AST_AUTOWIRE node is created and used for the annotation. | ||||
| -  All identifiers are resolved and all ``AST_IDENTIFIER`` nodes are annotated | ||||
|    with a pointer to the AST node that contains the declaration of the | ||||
|    identifier. If no declaration has been found, an ``AST_AUTOWIRE`` node is | ||||
|    created and used for the annotation. | ||||
| 
 | ||||
| This produces an AST that is fairly easy to convert to the RTLIL format. | ||||
| 
 | ||||
| Generating RTLIL | ||||
| ~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| After AST simplification, the ``AST::AstNode::genRTLIL()`` method of | ||||
| each AST_MODULE node in the AST is called. This initiates a recursive | ||||
| process that generates equivalent RTLIL data for the AST data. | ||||
| After AST simplification, the ``AST::AstNode::genRTLIL()`` method of each | ||||
| ``AST_MODULE`` node in the AST is called. This initiates a recursive process | ||||
| that generates equivalent RTLIL data for the AST data. | ||||
| 
 | ||||
| The ``AST::AstNode::genRTLIL()`` method returns an ``RTLIL::SigSpec`` | ||||
| structure. For nodes that represent expressions (operators, constants, | ||||
| signals, etc.), the cells needed to implement the calculation described | ||||
| by the expression are created and the resulting signal is returned. That | ||||
| way it is easy to generate the circuits for large expressions using | ||||
| depth-first recursion. For nodes that do not represent an expression | ||||
| (such as AST_CELL), the corresponding circuit is generated and an empty | ||||
| ``RTLIL::SigSpec`` is returned. | ||||
| The ``AST::AstNode::genRTLIL()`` method returns an ``RTLIL::SigSpec`` structure. | ||||
| For nodes that represent expressions (operators, constants, signals, etc.), the | ||||
| cells needed to implement the calculation described by the expression are | ||||
| created and the resulting signal is returned. That way it is easy to generate | ||||
| the circuits for large expressions using depth-first recursion. For nodes that | ||||
| do not represent an expression (such as ``AST_CELL``), the corresponding circuit | ||||
| is generated and an empty ``RTLIL::SigSpec`` is returned. | ||||
| 
 | ||||
| Synthesizing Verilog always blocks | ||||
| -------------------------------------- | ||||
| 
 | ||||
| For behavioural Verilog code (code utilizing ``always``- and | ||||
| ``initial``-blocks) it is necessary to also generate ``RTLIL::Process`` | ||||
| objects. This is done in the following way: | ||||
| For behavioural Verilog code (code utilizing ``always``- and ``initial``-blocks) | ||||
| it is necessary to also generate ``RTLIL::Process`` objects. This is done in the | ||||
| following way: | ||||
| 
 | ||||
| Whenever ``AST::AstNode::genRTLIL()`` encounters an ``always``- or | ||||
| ``initial``-block, it creates an instance of | ||||
| ``AST_INTERNAL::ProcessGenerator``. This object then generates the | ||||
| ``RTLIL::Process`` object for the block. It also calls | ||||
| ``AST::AstNode::genRTLIL()`` for all right-hand-side expressions | ||||
| contained within the block. | ||||
| ``initial``-block, it creates an instance of ``AST_INTERNAL::ProcessGenerator``. | ||||
| This object then generates the ``RTLIL::Process`` object for the block. It also | ||||
| calls ``AST::AstNode::genRTLIL()`` for all right-hand-side expressions contained | ||||
| within the block. | ||||
| 
 | ||||
| First the ``AST_INTERNAL::ProcessGenerator`` creates a list of all | ||||
| signals assigned within the block. It then creates a set of temporary | ||||
| signals using the naming scheme $\ <number> \\\ <original_name> for each | ||||
| of the assigned signals. | ||||
| First the ``AST_INTERNAL::ProcessGenerator`` creates a list of all signals | ||||
| assigned within the block. It then creates a set of temporary signals using the | ||||
| naming scheme ``$ <number> \ <original_name>`` for each of the assigned signals. | ||||
| 
 | ||||
| Then an ``RTLIL::Process`` is created that assigns all intermediate | ||||
| values for each left-hand-side signal to the temporary signal in its | ||||
| Then an ``RTLIL::Process`` is created that assigns all intermediate values for | ||||
| each left-hand-side signal to the temporary signal in its | ||||
| ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree. | ||||
| 
 | ||||
| Finally a ``RTLIL::SyncRule`` is created for the ``RTLIL::Process`` that | ||||
| assigns the temporary signals for the final values to the actual | ||||
| signals. | ||||
| Finally a ``RTLIL::SyncRule`` is created for the ``RTLIL::Process`` that assigns | ||||
| the temporary signals for the final values to the actual signals. | ||||
| 
 | ||||
| A process may also contain memory writes. A ``RTLIL::MemWriteAction`` is | ||||
| created for each of them. | ||||
| A process may also contain memory writes. A ``RTLIL::MemWriteAction`` is created | ||||
| for each of them. | ||||
| 
 | ||||
| Calls to ``AST::AstNode::genRTLIL()`` are generated for right hand sides | ||||
| as needed. When blocking assignments are used, | ||||
| ``AST::AstNode::genRTLIL()`` is configured using global variables to use | ||||
| the temporary signals that hold the correct intermediate values whenever | ||||
| one of the previously assigned signals is used in an expression. | ||||
| Calls to ``AST::AstNode::genRTLIL()`` are generated for right hand sides as | ||||
| needed. When blocking assignments are used, ``AST::AstNode::genRTLIL()`` is | ||||
| configured using global variables to use the temporary signals that hold the | ||||
| correct intermediate values whenever one of the previously assigned signals is | ||||
| used in an expression. | ||||
| 
 | ||||
| Unfortunately the generation of a correct | ||||
| ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree for behavioural code is a | ||||
| non-trivial task. The AST frontend solves the problem using the approach | ||||
| described on the following pages. The following example illustrates what | ||||
| the algorithm is supposed to do. Consider the following Verilog code: | ||||
| described on the following pages. The following example illustrates what the | ||||
| algorithm is supposed to do. Consider the following Verilog code: | ||||
| 
 | ||||
| .. code:: verilog | ||||
|    :number-lines: | ||||
|  | @ -325,9 +318,8 @@ the algorithm is supposed to do. Consider the following Verilog code: | |||
|        out1 = out1 ^ out2; | ||||
|    end | ||||
| 
 | ||||
| This is translated by the Verilog and AST frontends into the following | ||||
| RTLIL code (attributes, cell parameters and wire declarations not | ||||
| included): | ||||
| This is translated by the Verilog and AST frontends into the following RTLIL | ||||
| code (attributes, cell parameters and wire declarations not included): | ||||
| 
 | ||||
| .. code:: RTLIL | ||||
|    :number-lines: | ||||
|  | @ -372,47 +364,47 @@ included): | |||
|        update \out3 $0\out3[0:0] | ||||
|    end | ||||
| 
 | ||||
| Note that the two operators are translated into separate cells outside | ||||
| the generated process. The signal ``out1`` is assigned using blocking | ||||
| assignments and therefore ``out1`` has been replaced with a different | ||||
| signal in all expressions after the initial assignment. The signal | ||||
| ``out2`` is assigned using nonblocking assignments and therefore is not | ||||
| substituted on the right-hand-side expressions. | ||||
| Note that the two operators are translated into separate cells outside the | ||||
| generated process. The signal ``out1`` is assigned using blocking assignments | ||||
| and therefore ``out1`` has been replaced with a different signal in all | ||||
| expressions after the initial assignment. The signal ``out2`` is assigned using | ||||
| nonblocking assignments and therefore is not substituted on the right-hand-side | ||||
| expressions. | ||||
| 
 | ||||
| The ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree must be interpreted | ||||
| the following way: | ||||
| The ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree must be interpreted the | ||||
| following way: | ||||
| 
 | ||||
| -  On each case level (the body of the process is the root case), first | ||||
|    the actions on this level are evaluated and then the switches within | ||||
|    the case are evaluated. (Note that the last assignment on line 13 of | ||||
|    the Verilog code has been moved to the beginning of the RTLIL process | ||||
|    to line 13 of the RTLIL listing.) | ||||
| -  On each case level (the body of the process is the root case), first the | ||||
|    actions on this level are evaluated and then the switches within the case are | ||||
|    evaluated. (Note that the last assignment on line 13 of the Verilog code has | ||||
|    been moved to the beginning of the RTLIL process to line 13 of the RTLIL | ||||
|    listing.) | ||||
| 
 | ||||
|    I.e. the special cases deeper in the switch hierarchy override the | ||||
|    defaults on the upper levels. The assignments in lines 12 and 22 of | ||||
|    the RTLIL code serve as an example for this. | ||||
|    I.e. the special cases deeper in the switch hierarchy override the defaults | ||||
|    on the upper levels. The assignments in lines 12 and 22 of the RTLIL code | ||||
|    serve as an example for this. | ||||
| 
 | ||||
|    Note that in contrast to this, the order within the | ||||
|    ``RTLIL::SwitchRule`` objects within a ``RTLIL::CaseRule`` is | ||||
|    preserved with respect to the original AST and Verilog code. | ||||
|    Note that in contrast to this, the order within the ``RTLIL::SwitchRule`` | ||||
|    objects within a ``RTLIL::CaseRule`` is preserved with respect to the | ||||
|    original AST and Verilog code. | ||||
| 
 | ||||
| -  The whole ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree describes an | ||||
|    asynchronous circuit. I.e. the decision tree formed by the switches | ||||
|    can be seen independently for each assigned signal. Whenever one | ||||
|    assigned signal changes, all signals that depend on the changed | ||||
|    signals are to be updated. For example the assignments in lines 16 | ||||
|    and 18 in the RTLIL code in fact influence the assignment in line 12, | ||||
|    even though they are in the "wrong order". | ||||
|    asynchronous circuit. I.e. the decision tree formed by the switches can be | ||||
|    seen independently for each assigned signal. Whenever one assigned signal | ||||
|    changes, all signals that depend on the changed signals are to be updated. | ||||
|    For example the assignments in lines 16 and 18 in the RTLIL code in fact | ||||
|    influence the assignment in line 12, even though they are in the "wrong | ||||
|    order". | ||||
| 
 | ||||
| The only synchronous part of the process is in the ``RTLIL::SyncRule`` | ||||
| object generated at line 35 in the RTLIL code. The sync rule is the only | ||||
| part of the process where the original signals are assigned. The | ||||
| synchronization event from the original Verilog code has been translated | ||||
| into the synchronization type (posedge) and signal (\\clock) for the | ||||
| ``RTLIL::SyncRule`` object. In the case of this simple example the | ||||
| ``RTLIL::SyncRule`` object is later simply transformed into a set of | ||||
| d-type flip-flops and the ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree | ||||
| to a decision tree using multiplexers. | ||||
| The only synchronous part of the process is in the ``RTLIL::SyncRule`` object | ||||
| generated at line 35 in the RTLIL code. The sync rule is the only part of the | ||||
| process where the original signals are assigned. The synchronization event from | ||||
| the original Verilog code has been translated into the synchronization type | ||||
| (posedge) and signal (``\clock``) for the ``RTLIL::SyncRule`` object. In the | ||||
| case of this simple example the ``RTLIL::SyncRule`` object is later simply | ||||
| transformed into a set of d-type flip-flops and the | ||||
| ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree to a decision tree using | ||||
| multiplexers. | ||||
| 
 | ||||
| In more complex examples (e.g. asynchronous resets) the part of the | ||||
| ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree that describes the | ||||
|  | @ -426,64 +418,62 @@ The ``AST_INTERNAL::ProcessGenerator`` uses the following internal state | |||
| variables: | ||||
| 
 | ||||
| -  | ``subst_rvalue_from`` and ``subst_rvalue_to`` | ||||
|    | These two variables hold the replacement pattern that should be | ||||
|      used by ``AST::AstNode::genRTLIL()`` for signals with blocking | ||||
|      assignments. After initialization of | ||||
|      ``AST_INTERNAL::ProcessGenerator`` these two variables are empty. | ||||
|    | These two variables hold the replacement pattern that should be used by | ||||
|      ``AST::AstNode::genRTLIL()`` for signals with blocking assignments. After | ||||
|     initialization of ``AST_INTERNAL::ProcessGenerator`` these two variables are | ||||
|     empty. | ||||
| 
 | ||||
| -  | ``subst_lvalue_from`` and ``subst_lvalue_to`` | ||||
|    | These two variables contain the mapping from left-hand-side signals | ||||
|      (\\\ <name>) to the current temporary signal for the same thing | ||||
|      (initially $0\\\ <name>). | ||||
| -  | ``subst_lvalue_from`` and ``subst_lvalue_to``  | ||||
|    | These two variables contain the mapping from left-hand-side signals (``\ | ||||
|      <name>``) to the current temporary signal for the same thing (initially | ||||
|      ``$0\ <name>``). | ||||
| 
 | ||||
| -  | ``current_case`` | ||||
|    | A pointer to a ``RTLIL::CaseRule`` object. Initially this is the | ||||
|      root case of the generated ``RTLIL::Process``. | ||||
| -  | ``current_case``  | ||||
|    | A pointer to a ``RTLIL::CaseRule`` object. Initially this is the root case | ||||
|      of the generated ``RTLIL::Process``. | ||||
| 
 | ||||
| As the algorithm runs these variables are continuously modified as well | ||||
| as pushed to the stack and later restored to their earlier values by | ||||
| popping from the stack. | ||||
| As the algorithm runs these variables are continuously modified as well as | ||||
| pushed to the stack and later restored to their earlier values by popping from | ||||
| the stack. | ||||
| 
 | ||||
| On startup the ProcessGenerator generates a new ``RTLIL::Process`` | ||||
| object with an empty root case and initializes its state variables as | ||||
| described above. Then the ``RTLIL::SyncRule`` objects are created using | ||||
| the synchronization events from the AST_ALWAYS node and the initial | ||||
| values of ``subst_lvalue_from`` and ``subst_lvalue_to``. Then the AST | ||||
| for this process is evaluated recursively. | ||||
| On startup the ProcessGenerator generates a new ``RTLIL::Process`` object with | ||||
| an empty root case and initializes its state variables as described above. Then | ||||
| the ``RTLIL::SyncRule`` objects are created using the synchronization events | ||||
| from the AST_ALWAYS node and the initial values of ``subst_lvalue_from`` and | ||||
| ``subst_lvalue_to``. Then the AST for this process is evaluated recursively. | ||||
| 
 | ||||
| During this recursive evaluation, three different relevant types of AST | ||||
| nodes can be discovered: AST_ASSIGN_LE (nonblocking assignments), | ||||
| AST_ASSIGN_EQ (blocking assignments) and AST_CASE (``if`` or ``case`` | ||||
| During this recursive evaluation, three different relevant types of AST nodes | ||||
| can be discovered: ``AST_ASSIGN_LE`` (nonblocking assignments), | ||||
| ``AST_ASSIGN_EQ`` (blocking assignments) and ``AST_CASE`` (``if`` or ``case`` | ||||
| statement). | ||||
| 
 | ||||
| Handling of nonblocking assignments | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| When an AST_ASSIGN_LE node is discovered, the following actions are | ||||
| When an ``AST_ASSIGN_LE`` node is discovered, the following actions are | ||||
| performed by the ProcessGenerator: | ||||
| 
 | ||||
| -  The left-hand-side is evaluated using ``AST::AstNode::genRTLIL()`` | ||||
|    and mapped to a temporary signal name using ``subst_lvalue_from`` and | ||||
| -  The left-hand-side is evaluated using ``AST::AstNode::genRTLIL()`` and mapped | ||||
|    to a temporary signal name using ``subst_lvalue_from`` and | ||||
|    ``subst_lvalue_to``. | ||||
| 
 | ||||
| -  The right-hand-side is evaluated using ``AST::AstNode::genRTLIL()``. | ||||
|    For this call, the values of ``subst_rvalue_from`` and | ||||
|    ``subst_rvalue_to`` are used to map blocking-assigned signals | ||||
|    correctly. | ||||
| -  The right-hand-side is evaluated using ``AST::AstNode::genRTLIL()``. For this | ||||
|    call, the values of ``subst_rvalue_from`` and ``subst_rvalue_to`` are used to | ||||
|    map blocking-assigned signals correctly. | ||||
| 
 | ||||
| -  Remove all assignments to the same left-hand-side as this assignment | ||||
|    from the ``current_case`` and all cases within it. | ||||
| -  Remove all assignments to the same left-hand-side as this assignment from the | ||||
|    ``current_case`` and all cases within it. | ||||
| 
 | ||||
| -  Add the new assignment to the ``current_case``. | ||||
| 
 | ||||
| Handling of blocking assignments | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| When an AST_ASSIGN_EQ node is discovered, the following actions are | ||||
| When an ``AST_ASSIGN_EQ`` node is discovered, the following actions are | ||||
| performed by the ProcessGenerator: | ||||
| 
 | ||||
| -  Perform all the steps that would be performed for a nonblocking | ||||
|    assignment (see above). | ||||
| -  Perform all the steps that would be performed for a nonblocking assignment | ||||
|    (see above). | ||||
| 
 | ||||
| -  Remove the found left-hand-side (before lvalue mapping) from | ||||
|    ``subst_rvalue_from`` and also remove the respective bits from | ||||
|  | @ -496,36 +486,33 @@ performed by the ProcessGenerator: | |||
| Handling of cases and if-statements | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| When an AST_CASE node is discovered, the following actions are performed | ||||
| by the ProcessGenerator: | ||||
| When an ``AST_CASE`` node is discovered, the following actions are performed by | ||||
| the ProcessGenerator: | ||||
| 
 | ||||
| -  The values of ``subst_rvalue_from``, ``subst_rvalue_to``, | ||||
|    ``subst_lvalue_from`` and ``subst_lvalue_to`` are pushed to the | ||||
|    stack. | ||||
|    ``subst_lvalue_from`` and ``subst_lvalue_to`` are pushed to the stack. | ||||
| 
 | ||||
| -  A new ``RTLIL::SwitchRule`` object is generated, the selection | ||||
|    expression is evaluated using ``AST::AstNode::genRTLIL()`` (with the | ||||
|    use of ``subst_rvalue_from`` and ``subst_rvalue_to``) and added to | ||||
|    the ``RTLIL::SwitchRule`` object and the object is added to the | ||||
|    ``current_case``. | ||||
| -  A new ``RTLIL::SwitchRule`` object is generated, the selection expression is | ||||
|    evaluated using ``AST::AstNode::genRTLIL()`` (with the use of | ||||
|    ``subst_rvalue_from`` and ``subst_rvalue_to``) and added to the | ||||
|    ``RTLIL::SwitchRule`` object and the object is added to the ``current_case``. | ||||
| 
 | ||||
| -  All lvalues assigned to within the AST_CASE node using blocking | ||||
| -  All lvalues assigned to within the ``AST_CASE`` node using blocking | ||||
|    assignments are collected and saved in the local variable | ||||
|    ``this_case_eq_lvalue``. | ||||
| 
 | ||||
| -  New temporary signals are generated for all signals in | ||||
|    ``this_case_eq_lvalue`` and stored in ``this_case_eq_ltemp``. | ||||
| 
 | ||||
| -  The signals in ``this_case_eq_lvalue`` are mapped using | ||||
|    ``subst_rvalue_from`` and ``subst_rvalue_to`` and the resulting set | ||||
|    of signals is stored in ``this_case_eq_rvalue``. | ||||
| -  The signals in ``this_case_eq_lvalue`` are mapped using ``subst_rvalue_from`` | ||||
|    and ``subst_rvalue_to`` and the resulting set of signals is stored in | ||||
|    ``this_case_eq_rvalue``. | ||||
| 
 | ||||
| Then the following steps are performed for each AST_COND node within the | ||||
| AST_CASE node: | ||||
| Then the following steps are performed for each ``AST_COND`` node within the | ||||
| ``AST_CASE`` node: | ||||
| 
 | ||||
| -  Set ``subst_rvalue_from``, ``subst_rvalue_to``, ``subst_lvalue_from`` | ||||
|    and ``subst_lvalue_to`` to the values that have been pushed to the | ||||
|    stack. | ||||
| -  Set ``subst_rvalue_from``, ``subst_rvalue_to``, ``subst_lvalue_from`` and | ||||
|    ``subst_lvalue_to`` to the values that have been pushed to the stack. | ||||
| 
 | ||||
| -  Remove ``this_case_eq_lvalue`` from | ||||
|    ``subst_lvalue_from``/``subst_lvalue_to``. | ||||
|  | @ -535,33 +522,30 @@ AST_CASE node: | |||
| 
 | ||||
| -  Push the value of ``current_case``. | ||||
| 
 | ||||
| -  Create a new ``RTLIL::CaseRule``. Set ``current_case`` to the new | ||||
|    object and add the new object to the ``RTLIL::SwitchRule`` created | ||||
|    above. | ||||
| -  Create a new ``RTLIL::CaseRule``. Set ``current_case`` to the new object and | ||||
|    add the new object to the ``RTLIL::SwitchRule`` created above. | ||||
| 
 | ||||
| -  Add an assignment from ``this_case_eq_rvalue`` to | ||||
|    ``this_case_eq_ltemp`` to the new ``current_case``. | ||||
| -  Add an assignment from ``this_case_eq_rvalue`` to ``this_case_eq_ltemp`` to | ||||
|    the new ``current_case``. | ||||
| 
 | ||||
| -  Evaluate the compare value for this case using | ||||
|    ``AST::AstNode::genRTLIL()`` (with the use of ``subst_rvalue_from`` | ||||
|    and ``subst_rvalue_to``) modify the new ``current_case`` accordingly. | ||||
| 
 | ||||
| -  Recursion into the children of the AST_COND node. | ||||
| -  Recursion into the children of the ``AST_COND`` node. | ||||
| 
 | ||||
| -  Restore ``current_case`` by popping the old value from the stack. | ||||
| 
 | ||||
| Finally the following steps are performed: | ||||
| 
 | ||||
| -  The values of ``subst_rvalue_from``, ``subst_rvalue_to``, | ||||
|    ``subst_lvalue_from`` and ``subst_lvalue_to`` are popped from the | ||||
|    stack. | ||||
|    ``subst_lvalue_from`` and ``subst_lvalue_to`` are popped from the stack. | ||||
| 
 | ||||
| -  The signals from ``this_case_eq_lvalue`` are removed from the | ||||
|    ``subst_rvalue_from``/``subst_rvalue_to``-pair. | ||||
| 
 | ||||
| -  The value of ``this_case_eq_lvalue`` is appended to | ||||
|    ``subst_rvalue_from`` and the value of ``this_case_eq_ltemp`` is | ||||
|    appended to ``subst_rvalue_to``. | ||||
| -  The value of ``this_case_eq_lvalue`` is appended to ``subst_rvalue_from`` and | ||||
|    the value of ``this_case_eq_ltemp`` is appended to ``subst_rvalue_to``. | ||||
| 
 | ||||
| -  Map the signals in ``this_case_eq_lvalue`` using | ||||
|    ``subst_lvalue_from``/``subst_lvalue_to``. | ||||
|  | @ -569,98 +553,99 @@ Finally the following steps are performed: | |||
| -  Remove all assignments to signals in ``this_case_eq_lvalue`` in | ||||
|    ``current_case`` and all cases within it. | ||||
| 
 | ||||
| -  Add an assignment from ``this_case_eq_ltemp`` to | ||||
|    ``this_case_eq_lvalue`` to ``current_case``. | ||||
| -  Add an assignment from ``this_case_eq_ltemp`` to ``this_case_eq_lvalue`` to | ||||
|    ``current_case``. | ||||
| 
 | ||||
| Further analysis of the algorithm for cases and if-statements | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| With respect to nonblocking assignments the algorithm is easy: later | ||||
| assignments invalidate earlier assignments. For each signal assigned | ||||
| using nonblocking assignments exactly one temporary variable is | ||||
| generated (with the $0-prefix) and this variable is used for all | ||||
| assignments of the variable. | ||||
| With respect to nonblocking assignments the algorithm is easy: later assignments | ||||
| invalidate earlier assignments. For each signal assigned using nonblocking | ||||
| assignments exactly one temporary variable is generated (with the ``$0``-prefix) | ||||
| and this variable is used for all assignments of the variable. | ||||
| 
 | ||||
| Note how all the ``_eq_``-variables become empty when no blocking | ||||
| assignments are used and many of the steps in the algorithm can then be | ||||
| ignored as a result of this. | ||||
| Note how all the ``_eq_``-variables become empty when no blocking assignments | ||||
| are used and many of the steps in the algorithm can then be ignored as a result | ||||
| of this. | ||||
| 
 | ||||
| For a variable with blocking assignments the algorithm shows the | ||||
| following behaviour: First a new temporary variable is created. This new | ||||
| temporary variable is then registered as the assignment target for all | ||||
| assignments for this variable within the cases for this AST_CASE node. | ||||
| Then for each case the new temporary variable is first assigned the old | ||||
| temporary variable. This assignment is overwritten if the variable is | ||||
| actually assigned in this case and is kept as a default value otherwise. | ||||
| For a variable with blocking assignments the algorithm shows the following | ||||
| behaviour: First a new temporary variable is created. This new temporary | ||||
| variable is then registered as the assignment target for all assignments for | ||||
| this variable within the cases for this ``AST_CASE`` node. Then for each case | ||||
| the new temporary variable is first assigned the old temporary variable. This | ||||
| assignment is overwritten if the variable is actually assigned in this case and | ||||
| is kept as a default value otherwise. | ||||
| 
 | ||||
| This yields an ``RTLIL::CaseRule`` that assigns the new temporary | ||||
| variable in all branches. So when all cases have been processed a final | ||||
| assignment is added to the containing block that assigns the new | ||||
| temporary variable to the old one. Note how this step always overrides a | ||||
| previous assignment to the old temporary variable. Other than | ||||
| nonblocking assignments, the old assignment could still have an effect | ||||
| somewhere in the design, as there have been calls to | ||||
| This yields an ``RTLIL::CaseRule`` that assigns the new temporary variable in | ||||
| all branches. So when all cases have been processed a final assignment is added | ||||
| to the containing block that assigns the new temporary variable to the old one. | ||||
| Note how this step always overrides a previous assignment to the old temporary | ||||
| variable. Other than nonblocking assignments, the old assignment could still | ||||
| have an effect somewhere in the design, as there have been calls to | ||||
| ``AST::AstNode::genRTLIL()`` with a | ||||
| ``subst_rvalue_from``/``subst_rvalue_to``-tuple that contained the | ||||
| ``subst_rvalue_from``/ ``subst_rvalue_to``-tuple that contained the | ||||
| right-hand-side of the old assignment. | ||||
| 
 | ||||
| The proc pass | ||||
| ~~~~~~~~~~~~~ | ||||
| 
 | ||||
| The ProcessGenerator converts a behavioural model in AST representation | ||||
| to a behavioural model in ``RTLIL::Process`` representation. The actual | ||||
| conversion from a behavioural model to an RTL representation is | ||||
| performed by the proc pass and the passes it launches: | ||||
| The ProcessGenerator converts a behavioural model in AST representation to a | ||||
| behavioural model in ``RTLIL::Process`` representation. The actual conversion | ||||
| from a behavioural model to an RTL representation is performed by the ``proc`` | ||||
| pass and the passes it launches: | ||||
| 
 | ||||
| -  | proc_clean and proc_rmdead | ||||
|    | These two passes just clean up the ``RTLIL::Process`` structure. | ||||
|      The proc_clean pass removes empty parts (eg. empty assignments) | ||||
|      from the process and proc_rmdead detects and removes unreachable | ||||
|      branches from the process's decision trees. | ||||
| -  | proc_clean and proc_rmdead  | ||||
|    | These two passes just clean up the ``RTLIL::Process`` structure. The | ||||
|      ``proc_clean`` pass removes empty parts (eg. empty assignments) from the | ||||
|      process and ``proc_rmdead`` detects and removes unreachable branches from | ||||
|      the process's decision trees. | ||||
| 
 | ||||
| -  | proc_arst | ||||
| -  | proc_arst  | ||||
|    | This pass detects processes that describe d-type flip-flops with | ||||
|      asynchronous resets and rewrites the process to better reflect what | ||||
|      they are modelling: Before this pass, an asynchronous reset has two | ||||
|      edge-sensitive sync rules and one top-level for the reset path. | ||||
|      After this pass the sync rule for the reset is level-sensitive and | ||||
|      the top-level has been removed. | ||||
|      asynchronous resets and rewrites the process to better reflect what they | ||||
|      are modelling: Before this pass, an asynchronous reset has two | ||||
|      edge-sensitive sync rules and one top-level ``RTLIL::SwitchRule`` for the | ||||
|      reset path. After this pass the sync rule for the reset is level-sensitive | ||||
|      and the top-level ``RTLIL::SwitchRule`` has been removed. | ||||
| 
 | ||||
| -  | proc_mux | ||||
|    | This pass converts the /-tree to a tree of multiplexers per written | ||||
|      signal. After this, the structure only contains the s that describe | ||||
|      the output registers. | ||||
| -  | proc_mux  | ||||
|    | This pass converts the ``RTLIL::CaseRule``/ ``RTLIL::SwitchRule``-tree to a | ||||
|      tree of multiplexers per written signal. After this, the ``RTLIL::Process`` | ||||
|      structure only contains the ``RTLIL::SyncRule`` s that describe the output | ||||
|      registers. | ||||
| 
 | ||||
| -  | proc_dff | ||||
|    | This pass replaces the s to d-type flip-flops (with asynchronous | ||||
|      resets if necessary). | ||||
|    | This pass replaces the ``RTLIL::SyncRule`` s to d-type flip-flops (with | ||||
|      asynchronous resets if necessary). | ||||
| 
 | ||||
| -  | proc_dff | ||||
|    | This pass replaces the s with $memwr cells. | ||||
|    | This pass replaces the ``RTLIL::MemWriteAction`` s with ``$memwr`` cells. | ||||
| 
 | ||||
| -  | proc_clean | ||||
|    | A final call to proc_clean removes the now empty objects. | ||||
|    | A final call to ``proc_clean`` removes the now empty ``RTLIL::Process`` | ||||
|      objects. | ||||
| 
 | ||||
| Performing these last processing steps in passes instead of in the | ||||
| Verilog frontend has two important benefits: | ||||
| Performing these last processing steps in passes instead of in the Verilog | ||||
| frontend has two important benefits: | ||||
| 
 | ||||
| First it improves the transparency of the process. Everything that | ||||
| happens in a separate pass is easier to debug, as the RTLIL data | ||||
| structures can be easily investigated before and after each of the | ||||
| steps. | ||||
| First it improves the transparency of the process. Everything that happens in a | ||||
| separate pass is easier to debug, as the RTLIL data structures can be easily | ||||
| investigated before and after each of the steps. | ||||
| 
 | ||||
| Second it improves flexibility. This scheme can easily be extended to | ||||
| support other types of storage-elements, such as sr-latches or | ||||
| d-latches, without having to extend the actual Verilog frontend. | ||||
| Second it improves flexibility. This scheme can easily be extended to support | ||||
| other types of storage-elements, such as sr-latches or d-latches, without having | ||||
| to extend the actual Verilog frontend. | ||||
| 
 | ||||
| Synthesizing Verilog arrays | ||||
| --------------------------- | ||||
| 
 | ||||
| Add some information on the generation of $memrd and $memwr cells and | ||||
| .. TODO: these | ||||
| 
 | ||||
| Add some information on the generation of ``$memrd`` and ``$memwr`` cells and | ||||
| how they are processed in the memory pass. | ||||
| 
 | ||||
| Synthesizing parametric designs | ||||
| ------------------------------- | ||||
| 
 | ||||
| Add some information on the ``RTLIL::Module::derive()`` method and how | ||||
| it is used to synthesize parametric modules via the hierarchy pass. | ||||
| Add some information on the ``RTLIL::Module::derive()`` method and how it is | ||||
| used to synthesize parametric modules via the hierarchy pass. | ||||
|  |  | |||
|  | @ -816,17 +816,17 @@ techlibs/common/simcells.v in the Yosys source tree. | |||
| 	============== ============== ========= | ||||
| 
 | ||||
| 
 | ||||
| Tables \ :numref:`%s <tab:CellLib_gates>`, :numref:`%s | ||||
| <tab:CellLib_gates_dffe>`, :numref:`%s <tab:CellLib_gates_adff>`, :numref:`%s | ||||
| <tab:CellLib_gates_adffe>`, :numref:`%s <tab:CellLib_gates_dffsr>`, :numref:`%s | ||||
| <tab:CellLib_gates_dffsre>`, :numref:`%s <tab:CellLib_gates_adlatch>`, | ||||
| :numref:`%s <tab:CellLib_gates_dlatchsr>` and :numref:`%s | ||||
| <tab:CellLib_gates_sr>` list all cell types used for gate level logic. The cell | ||||
| types ``$_BUF_``, ``$_NOT_``, ``$_AND_``, ``$_NAND_``, ``$_ANDNOT_``, ``$_OR_``, | ||||
| ``$_NOR_``, ``$_ORNOT_``, ``$_XOR_``, ``$_XNOR_``, ``$_AOI3_``, ``$_OAI3_``, | ||||
| ``$_AOI4_``, ``$_OAI4_``, ``$_MUX_``, ``$_MUX4_``, ``$_MUX8_``, ``$_MUX16_`` and | ||||
| ``$_NMUX_`` are used to model combinatorial logic. The cell type ``$_TBUF_`` is | ||||
| used to model tristate logic. | ||||
| Tables :numref:`%s <tab:CellLib_gates>`, :numref:`%s <tab:CellLib_gates_dffe>`, | ||||
| :numref:`%s <tab:CellLib_gates_adff>`, :numref:`%s <tab:CellLib_gates_adffe>`, | ||||
| :numref:`%s <tab:CellLib_gates_dffsr>`, :numref:`%s <tab:CellLib_gates_dffsre>`, | ||||
| :numref:`%s <tab:CellLib_gates_adlatch>`, :numref:`%s | ||||
| <tab:CellLib_gates_dlatchsr>` and :numref:`%s <tab:CellLib_gates_sr>` list all | ||||
| cell types used for gate level logic. The cell types ``$_BUF_``, ``$_NOT_``, | ||||
| ``$_AND_``, ``$_NAND_``, ``$_ANDNOT_``, ``$_OR_``, ``$_NOR_``, ``$_ORNOT_``, | ||||
| ``$_XOR_``, ``$_XNOR_``, ``$_AOI3_``, ``$_OAI3_``, ``$_AOI4_``, ``$_OAI4_``, | ||||
| ``$_MUX_``, ``$_MUX4_``, ``$_MUX8_``, ``$_MUX16_`` and ``$_NMUX_`` are used to | ||||
| model combinatorial logic. The cell type ``$_TBUF_`` is used to model tristate | ||||
| logic. | ||||
| 
 | ||||
| The ``$_MUX4_``, ``$_MUX8_`` and ``$_MUX16_`` cells are used to model wide | ||||
| muxes, and correspond to the following Verilog code: | ||||
|  |  | |||
|  | @ -6,21 +6,21 @@ representation. The only exception are the high-level frontends that use the AST | |||
| representation as an intermediate step before generating RTLIL data. | ||||
| 
 | ||||
| In order to avoid reinventing names for the RTLIL classes, they are simply | ||||
| referred to by their full C++ name, i.e. including the RTLIL:: namespace prefix, | ||||
| referred to by their full C++ name, i.e. including the ``RTLIL::`` namespace prefix, | ||||
| in this document. | ||||
| 
 | ||||
| :numref:`Figure %s <fig:Overview_RTLIL>` shows a simplified Entity-Relationship | ||||
| Diagram (ER Diagram) of RTLIL. In :math:`1:N` relationships the arrow points | ||||
| from the :math:`N` side to the :math:`1`. For example one RTLIL::Design contains | ||||
| :math:`N` (zero to many) instances of RTLIL::Module. A two-pointed arrow | ||||
| from the :math:`N` side to the :math:`1`. For example one ``RTLIL::Design`` contains | ||||
| :math:`N` (zero to many) instances of ``RTLIL::Module`` . A two-pointed arrow | ||||
| indicates a :math:`1:1` relationship. | ||||
| 
 | ||||
| The RTLIL::Design is the root object of the RTLIL data structure. There is | ||||
| The ``RTLIL::Design`` is the root object of the RTLIL data structure. There is | ||||
| always one "current design" in memory which passes operate on, frontends add | ||||
| data to and backends convert to exportable formats. But in some cases passes | ||||
| internally generate additional RTLIL::Design objects. For example when a pass is | ||||
| internally generate additional ``RTLIL::Design`` objects. For example when a pass is | ||||
| reading an auxiliary Verilog file such as a cell library, it might create an | ||||
| additional RTLIL::Design object and call the Verilog frontend with this other | ||||
| additional ``RTLIL::Design`` object and call the Verilog frontend with this other | ||||
| object to parse the cell library. | ||||
| 
 | ||||
| .. figure:: ../../../images/overview_rtlil.* | ||||
|  | @ -29,23 +29,23 @@ object to parse the cell library. | |||
| 
 | ||||
| 	Simplified RTLIL Entity-Relationship Diagram | ||||
| 
 | ||||
| There is only one active RTLIL::Design object that is used by all frontends, | ||||
| There is only one active ``RTLIL::Design`` object that is used by all frontends, | ||||
| passes and backends called by the user, e.g. using a synthesis script. The | ||||
| RTLIL::Design then contains zero to many RTLIL::Module objects. This corresponds | ||||
| ``RTLIL::Design`` then contains zero to many ``RTLIL::Module`` objects. This corresponds | ||||
| to modules in Verilog or entities in VHDL. Each module in turn contains objects | ||||
| from three different categories: | ||||
| 
 | ||||
| -  RTLIL::Cell and RTLIL::Wire objects represent classical netlist data. | ||||
| -  ``RTLIL::Cell`` and ``RTLIL::Wire`` objects represent classical netlist data. | ||||
| 
 | ||||
| -  RTLIL::Process objects represent the decision trees (if-then-else statements, | ||||
| -  ``RTLIL::Process`` objects represent the decision trees (if-then-else statements, | ||||
|    etc.) and synchronization declarations (clock signals and sensitivity) from | ||||
|    Verilog always and VHDL process blocks. | ||||
| 
 | ||||
| -  RTLIL::Memory objects represent addressable memories (arrays). | ||||
| -  ``RTLIL::Memory`` objects represent addressable memories (arrays). | ||||
| 
 | ||||
| Usually the output of the synthesis procedure is a netlist, i.e. all | ||||
| RTLIL::Process and RTLIL::Memory objects must be replaced by RTLIL::Cell and | ||||
| RTLIL::Wire objects by synthesis passes. | ||||
| ``RTLIL::Process`` and ``RTLIL::Memory`` objects must be replaced by ``RTLIL::Cell`` and | ||||
| ``RTLIL::Wire`` objects by synthesis passes. | ||||
| 
 | ||||
| All features of the HDL that cannot be mapped directly to these RTLIL classes | ||||
| must be transformed to an RTLIL-compatible representation by the HDL frontend. | ||||
|  | @ -63,19 +63,22 @@ a backslash (\) or a dollar sign ($). | |||
| 
 | ||||
| Identifiers starting with a backslash are public visible identifiers. Usually | ||||
| they originate from one of the HDL input files. For example the signal name | ||||
| "\\sig42" is most likely a signal that was declared using the name "sig42" in an | ||||
| HDL input file. On the other hand the signal name "$sig42" is an auto-generated | ||||
| signal name. The backends convert all identifiers that start with a dollar sign | ||||
| to identifiers that do not collide with identifiers that start with a backslash. | ||||
| ``\sig42`` is most likely a signal that was declared using the name ``sig42`` in | ||||
| an HDL input file. On the other hand the signal name ``$sig42`` is an | ||||
| auto-generated signal name. The backends convert all identifiers that start with | ||||
| a dollar sign to identifiers that do not collide with identifiers that start | ||||
| with a backslash. | ||||
| 
 | ||||
| This has three advantages: | ||||
| 
 | ||||
| -  First, it is impossible that an auto-generated identifier collides with an | ||||
|    identifier that was provided by the user. | ||||
| 
 | ||||
| .. TODO: does opt_rmunused (still?) exist? | ||||
| 
 | ||||
| -  Second, the information about which identifiers were originally provided by | ||||
|    the user is always available which can help guide some optimizations. For | ||||
|    example the "opt_rmunused" tries to preserve signals with a user-provided | ||||
|    example the ``opt_rmunused`` tries to preserve signals with a user-provided | ||||
|    name but doesn't hesitate to delete signals that have auto-generated names | ||||
|    when they just duplicate other signals. | ||||
| 
 | ||||
|  | @ -98,25 +101,25 @@ All RTLIL identifiers are case sensitive. | |||
| 
 | ||||
| Some transformations, such as flattening, may have to change identifiers | ||||
| provided by the user to avoid name collisions. When that happens, attribute | ||||
| "hdlname" is attached to the object with the changed identifier. This attribute | ||||
| contains one name (if emitted directly by the frontend, or is a result of | ||||
| disambiguation) or multiple names separated by spaces (if a result of | ||||
| flattening). All names specified in the "hdlname" attribute are public and do | ||||
| not include the leading "\". | ||||
| ``hdlname`` is attached to the object with the changed identifier. This | ||||
| attribute contains one name (if emitted directly by the frontend, or is a result | ||||
| of disambiguation) or multiple names separated by spaces (if a result of | ||||
| flattening). All names specified in the ``hdlname`` attribute are public and do | ||||
| not include the leading ``\``. | ||||
| 
 | ||||
| RTLIL::Design and RTLIL::Module | ||||
| ------------------------------- | ||||
| 
 | ||||
| The RTLIL::Design object is basically just a container for RTLIL::Module | ||||
| objects. In addition to a list of RTLIL::Module objects the RTLIL::Design also | ||||
| keeps a list of selected objects, i.e. the objects that passes should operate | ||||
| on. In most cases the whole design is selected and therefore passes operate on | ||||
| the whole design. But this mechanism can be useful for more complex synthesis | ||||
| jobs in which only parts of the design should be affected by certain passes. | ||||
| The ``RTLIL::Design`` object is basically just a container for ``RTLIL::Module`` | ||||
| objects. In addition to a list of ``RTLIL::Module`` objects the | ||||
| ``RTLIL::Design`` also keeps a list of selected objects, i.e. the objects that | ||||
| passes should operate on. In most cases the whole design is selected and | ||||
| therefore passes operate on the whole design. But this mechanism can be useful | ||||
| for more complex synthesis jobs in which only parts of the design should be | ||||
| affected by certain passes. | ||||
| 
 | ||||
| Besides the objects shown in the ER diagram in :numref:`Fig. %s | ||||
| <fig:Overview_RTLIL>` an RTLIL::Module object contains the following additional | ||||
| properties: | ||||
| Besides the objects shown in the :ref:`ER diagram <fig:Overview_RTLIL>` above, | ||||
| an ``RTLIL::Module`` object contains the following additional properties: | ||||
| 
 | ||||
| -  The module name | ||||
| -  A list of attributes | ||||
|  | @ -132,7 +135,7 @@ script but not by others. | |||
| Verilog and VHDL both support parametric modules (known as "generic entities" in | ||||
| VHDL). The RTLIL format does not support parametric modules itself. Instead each | ||||
| module contains a callback function into the AST frontend to generate a | ||||
| parametrized variation of the RTLIL::Module as needed. This callback then | ||||
| parametrized variation of the ``RTLIL::Module`` as needed. This callback then | ||||
| returns the auto-generated name of the parametrized variation of the module. (A | ||||
| hash over the parameters and the module name is used to prohibit the same | ||||
| parametrized variation from being generated twice. For modules with only a few | ||||
|  | @ -144,14 +147,14 @@ hash string.) | |||
| RTLIL::Cell and RTLIL::Wire | ||||
| --------------------------- | ||||
| 
 | ||||
| A module contains zero to many RTLIL::Cell and RTLIL::Wire objects. Objects of | ||||
| these types are used to model netlists. Usually the goal of all synthesis | ||||
| efforts is to convert all modules to a state where the functionality of the | ||||
| module is implemented only by cells from a given cell library and wires to | ||||
| connect these cells with each other. Note that module ports are just wires with | ||||
| a special property. | ||||
| A module contains zero to many ``RTLIL::Cell`` and ``RTLIL::Wire`` objects. | ||||
| Objects of these types are used to model netlists. Usually the goal of all | ||||
| synthesis efforts is to convert all modules to a state where the functionality | ||||
| of the module is implemented only by cells from a given cell library and wires | ||||
| to connect these cells with each other. Note that module ports are just wires | ||||
| with a special property. | ||||
| 
 | ||||
| An RTLIL::Wire object has the following properties: | ||||
| An ``RTLIL::Wire`` object has the following properties: | ||||
| 
 | ||||
| -  The wire name | ||||
| -  A list of attributes | ||||
|  | @ -174,15 +177,16 @@ the lowest or the highest bit index. In RTLIL, bit 0 always corresponds to LSB; | |||
| however, information from the HDL frontend is preserved so that the bus will be | ||||
| correctly indexed in error messages, backend output, constraint files, etc. | ||||
| 
 | ||||
| An RTLIL::Cell object has the following properties: | ||||
| An ``RTLIL::Cell`` object has the following properties: | ||||
| 
 | ||||
| -  The cell name and type | ||||
| -  A list of attributes | ||||
| -  A list of parameters (for parametric cells) | ||||
| -  Cell ports and the connections of ports to wires and constants | ||||
| 
 | ||||
| The connections of ports to wires are coded by assigning an RTLIL::SigSpec to | ||||
| each cell port. The RTLIL::SigSpec data type is described in the next section. | ||||
| The connections of ports to wires are coded by assigning an ``RTLIL::SigSpec`` to | ||||
| each cell port. The ``RTLIL::SigSpec`` data type is described in the next | ||||
| section. | ||||
| 
 | ||||
| .. _sec:rtlil_sigspec: | ||||
| 
 | ||||
|  | @ -200,12 +204,12 @@ A "signal" is everything that can be applied to a cell port. I.e. | |||
| -  | Concatenations of the above | ||||
|    | 1em For example: ``{16'd1337, mywire[15:8]}`` | ||||
| 
 | ||||
| The RTLIL::SigSpec data type is used to represent signals. The RTLIL::Cell | ||||
| object contains one RTLIL::SigSpec for each cell port. | ||||
| The ``RTLIL::SigSpec`` data type is used to represent signals. The ``RTLIL::Cell`` | ||||
| object contains one ``RTLIL::SigSpec`` for each cell port. | ||||
| 
 | ||||
| In addition, connections between wires are represented using a pair of | ||||
| RTLIL::SigSpec objects. Such pairs are needed in different locations. Therefore | ||||
| the type name RTLIL::SigSig was defined for such a pair. | ||||
| ``RTLIL::SigSpec`` objects. Such pairs are needed in different locations. | ||||
| Therefore the type name ``RTLIL::SigSig`` was defined for such a pair. | ||||
| 
 | ||||
| .. _sec:rtlil_process: | ||||
| 
 | ||||
|  | @ -213,9 +217,9 @@ RTLIL::Process | |||
| -------------- | ||||
| 
 | ||||
| When a high-level HDL frontend processes behavioural code it splits it up into | ||||
| data path logic (e.g. the expression a + b is replaced by the output of an adder | ||||
| that takes a and b as inputs) and an RTLIL::Process that models the control | ||||
| logic of the behavioural code. Let's consider a simple example: | ||||
| data path logic (e.g. the expression ``a + b`` is replaced by the output of an | ||||
| adder that takes a and b as inputs) and an ``RTLIL::Process`` that models the | ||||
| control logic of the behavioural code. Let's consider a simple example: | ||||
| 
 | ||||
| .. code:: verilog | ||||
|    :number-lines: | ||||
|  | @ -230,9 +234,9 @@ logic of the behavioural code. Let's consider a simple example: | |||
|            q <= d; | ||||
|    endmodule | ||||
| 
 | ||||
| In this example there is no data path and therefore the RTLIL::Module generated | ||||
| by the frontend only contains a few RTLIL::Wire objects and an RTLIL::Process. | ||||
| The RTLIL::Process in RTLIL syntax: | ||||
| In this example there is no data path and therefore the ``RTLIL::Module`` generated | ||||
| by the frontend only contains a few ``RTLIL::Wire`` objects and an ``RTLIL::Process`` . | ||||
| The ``RTLIL::Process`` in RTLIL syntax: | ||||
| 
 | ||||
| .. code:: RTLIL | ||||
|    :number-lines: | ||||
|  | @ -255,34 +259,37 @@ The RTLIL::Process in RTLIL syntax: | |||
|            update \q $0\q[0:0] | ||||
|    end | ||||
| 
 | ||||
| This RTLIL::Process contains two RTLIL::SyncRule objects, two RTLIL::SwitchRule | ||||
| objects and five RTLIL::CaseRule objects. The wire $0\q[0:0] is an automatically | ||||
| created wire that holds the next value of \\q. The lines :math:`2 \dots 12` | ||||
| describe how $0\q[0:0] should be calculated. The lines :math:`13 \dots 16` | ||||
| describe how the value of $0\q[0:0] is used to update \\q. | ||||
| This ``RTLIL::Process`` contains two ``RTLIL::SyncRule`` objects, two | ||||
| ``RTLIL::SwitchRule`` objects and five ``RTLIL::CaseRule`` objects. The wire | ||||
| ``$0\q[0:0]`` is an automatically created wire that holds the next value of | ||||
| ``\q``. The lines 2..12 describe how ``$0\q[0:0]`` should be calculated. The | ||||
| lines 13..16 describe how the value of ``$0\q[0:0]`` is used to update ``\q``. | ||||
| 
 | ||||
| An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and | ||||
| exactly one RTLIL::CaseRule object, which is called the root case. | ||||
| An ``RTLIL::Process`` is a container for zero or more ``RTLIL::SyncRule`` | ||||
| objects and exactly one ``RTLIL::CaseRule`` object, which is called the root | ||||
| case. | ||||
| 
 | ||||
| An RTLIL::SyncRule object contains an (optional) synchronization condition | ||||
| (signal and edge-type), zero or more assignments (RTLIL::SigSig), and zero or | ||||
| more memory writes (RTLIL::MemWriteAction). The always synchronization condition | ||||
| is used to break combinatorial loops when a latch should be inferred instead. | ||||
| An ``RTLIL::SyncRule`` object contains an (optional) synchronization condition | ||||
| (signal and edge-type), zero or more assignments (``RTLIL::SigSig``), and zero | ||||
| or more memory writes (``RTLIL::MemWriteAction``). The always synchronization | ||||
| condition is used to break combinatorial loops when a latch should be inferred | ||||
| instead. | ||||
| 
 | ||||
| An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig) | ||||
| and zero or more RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a | ||||
| container for zero or more RTLIL::CaseRule objects. | ||||
| An ``RTLIL::CaseRule`` is a container for zero or more assignments | ||||
| (``RTLIL::SigSig``) and zero or more ``RTLIL::SwitchRule`` objects. An | ||||
| ``RTLIL::SwitchRule`` objects is a container for zero or more | ||||
| ``RTLIL::CaseRule`` objects. | ||||
| 
 | ||||
| In the above example the lines :math:`2 \dots 12` are the root case. Here | ||||
| $0\q[0:0] is first assigned the old value \\q as default value (line 2). The | ||||
| root case also contains an RTLIL::SwitchRule object (lines :math:`3 \dots 12`). | ||||
| Such an object is very similar to the C switch statement as it uses a control | ||||
| signal (\\reset in this case) to determine which of its cases should be active. | ||||
| The RTLIL::SwitchRule object then contains one RTLIL::CaseRule object per case. | ||||
| In this example there is a case [1]_ for \\reset == 1 that causes $0\q[0:0] to | ||||
| be set (lines 4 and 5) and a default case that in turn contains a switch that | ||||
| sets $0\q[0:0] to the value of \\d if \\enable is active (lines :math:`6 \dots | ||||
| 11`). | ||||
| In the above example the lines 2..12 are the root case. Here ``$0\q[0:0]`` is | ||||
| first assigned the old value ``\q`` as default value (line 2). The root case | ||||
| also contains an ``RTLIL::SwitchRule`` object (lines 3..12). Such an object is | ||||
| very similar to the C switch statement as it uses a control signal (``\reset`` | ||||
| in this case) to determine which of its cases should be active. The | ||||
| ``RTLIL::SwitchRule`` object then contains one ``RTLIL::CaseRule`` object per | ||||
| case. In this example there is a case [1]_ for ``\reset == 1`` that causes | ||||
| ``$0\q[0:0]`` to be set (lines 4 and 5) and a default case that in turn contains | ||||
| a switch that sets ``$0\q[0:0]`` to the value of ``\d`` if ``\enable`` is active | ||||
| (lines 6..11). | ||||
| 
 | ||||
| A case can specify zero or more compare values that will determine whether it | ||||
| matches. Each of the compare values must be the exact same width as the control | ||||
|  | @ -299,8 +306,8 @@ violated, the behavior is undefined. These attributes are useful when an | |||
| invariant invisible to the synthesizer causes the control signal to never take | ||||
| certain bit patterns. | ||||
| 
 | ||||
| The lines :math:`13 \dots 16` then cause \\q to be updated whenever there is a | ||||
| positive clock edge on \\clock or \\reset. | ||||
| The lines 13..16 then cause ``\q`` to be updated whenever there is a positive | ||||
| clock edge on ``\clock`` or ``\reset``. | ||||
| 
 | ||||
| In order to generate such a representation, the language frontend must be able | ||||
| to handle blocking and nonblocking assignments correctly. However, the language | ||||
|  | @ -313,8 +320,8 @@ trees before further processing them. | |||
| 
 | ||||
| One of the first actions performed on a design in RTLIL representation in most | ||||
| synthesis scripts is identifying asynchronous resets. This is usually done using | ||||
| the proc_arst pass. This pass transforms the above example to the following | ||||
| RTLIL::Process: | ||||
| the ``proc_arst`` pass. This pass transforms the above example to the following | ||||
| ``RTLIL::Process``: | ||||
| 
 | ||||
| .. code:: RTLIL | ||||
|    :number-lines: | ||||
|  | @ -332,9 +339,9 @@ RTLIL::Process: | |||
|            update \q 1'0 | ||||
|    end | ||||
| 
 | ||||
| This pass has transformed the outer RTLIL::SwitchRule into a modified | ||||
| RTLIL::SyncRule object for the \\reset signal. Further processing converts the | ||||
| RTLIL::Process into e.g. a d-type flip-flop with asynchronous reset and a | ||||
| This pass has transformed the outer ``RTLIL::SwitchRule`` into a modified | ||||
| ``RTLIL::SyncRule`` object for the ``\reset`` signal. Further processing converts the | ||||
| ``RTLIL::Process`` into e.g. a d-type flip-flop with asynchronous reset and a | ||||
| multiplexer for the enable signal: | ||||
| 
 | ||||
| .. code:: RTLIL | ||||
|  | @ -358,11 +365,11 @@ multiplexer for the enable signal: | |||
|        connect \Y $0\q[0:0] | ||||
|    end | ||||
| 
 | ||||
| Different combinations of passes may yield different results. Note that $adff | ||||
| and $mux are internal cell types that still need to be mapped to cell types from | ||||
| the target cell library. | ||||
| Different combinations of passes may yield different results. Note that | ||||
| ``$adff`` and ``$mux`` are internal cell types that still need to be mapped to | ||||
| cell types from the target cell library. | ||||
| 
 | ||||
| Some passes refuse to operate on modules that still contain RTLIL::Process | ||||
| Some passes refuse to operate on modules that still contain ``RTLIL::Process``  | ||||
| objects as the presence of these objects in a module increases the complexity. | ||||
| Therefore the passes to translate processes to a netlist of cells are usually | ||||
| called early in a synthesis script. The proc pass calls a series of other passes | ||||
|  | @ -374,7 +381,7 @@ synthesis tasks. | |||
| RTLIL::Memory | ||||
| ------------- | ||||
| 
 | ||||
| For every array (memory) in the HDL code an RTLIL::Memory object is created. A | ||||
| For every array (memory) in the HDL code an ``RTLIL::Memory`` object is created. A | ||||
| memory object has the following properties: | ||||
| 
 | ||||
| -  The memory name | ||||
|  | @ -382,27 +389,28 @@ memory object has the following properties: | |||
| -  The width of an addressable word | ||||
| -  The size of the memory in number of words | ||||
| 
 | ||||
| All read accesses to the memory are transformed to $memrd cells and all write | ||||
| accesses to $memwr cells by the language frontend. These cells consist of | ||||
| independent read- and write-ports to the memory. Memory initialization is | ||||
| transformed to $meminit cells by the language frontend. The ``\MEMID`` parameter | ||||
| on these cells is used to link them together and to the RTLIL::Memory object | ||||
| they belong to. | ||||
| All read accesses to the memory are transformed to ``$memrd`` cells and all | ||||
| write accesses to ``$memwr`` cells by the language frontend. These cells consist | ||||
| of independent read- and write-ports to the memory. Memory initialization is | ||||
| transformed to ``$meminit`` cells by the language frontend. The ``\MEMID`` | ||||
| parameter on these cells is used to link them together and to the | ||||
| ``RTLIL::Memory`` object they belong to. | ||||
| 
 | ||||
| The rationale behind using separate cells for the individual ports versus | ||||
| creating a large multiport memory cell right in the language frontend is that | ||||
| the separate $memrd and $memwr cells can be consolidated using resource sharing. | ||||
| As resource sharing is a non-trivial optimization problem where different | ||||
| synthesis tasks can have different requirements it lends itself to do the | ||||
| optimisation in separate passes and merge the RTLIL::Memory objects and $memrd | ||||
| and $memwr cells to multiport memory blocks after resource sharing is completed. | ||||
| the separate ``$memrd`` and ``$memwr`` cells can be consolidated using resource | ||||
| sharing. As resource sharing is a non-trivial optimization problem where | ||||
| different synthesis tasks can have different requirements it lends itself to do | ||||
| the optimisation in separate passes and merge the ``RTLIL::Memory`` objects and | ||||
| ``$memrd`` and ``$memwr`` cells to multiport memory blocks after resource | ||||
| sharing is completed. | ||||
| 
 | ||||
| The memory pass performs this conversion and can (depending on the options | ||||
| passed to it) transform the memories directly to d-type flip-flops and address | ||||
| logic or yield multiport memory blocks (represented using $mem cells). | ||||
| logic or yield multiport memory blocks (represented using ``$mem`` cells). | ||||
| 
 | ||||
| See :ref:`sec:memcells` for details about the memory cell types. | ||||
| 
 | ||||
| .. [1] | ||||
|    The syntax 1'1 in the RTLIL code specifies a constant with a length of one | ||||
|    bit (the first "1"), and this bit is a one (the second "1"). | ||||
|    The syntax ``1'1`` in the RTLIL code specifies a constant with a length of | ||||
|    one bit (the first ``1``), and this bit is a one (the second ``1``). | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue