mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Merge pull request #4332 from YosysHQ/krys/help_docs
Add docs generation from cells help output
This commit is contained in:
		
						commit
						f137509505
					
				
					 69 changed files with 3779 additions and 2442 deletions
				
			
		
							
								
								
									
										5
									
								
								.github/workflows/prepare-docs.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/prepare-docs.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -64,6 +64,11 @@ jobs: | ||||||
|             docs/source/_images |             docs/source/_images | ||||||
|             docs/source/code_examples |             docs/source/code_examples | ||||||
| 
 | 
 | ||||||
|  |       - name: Install doc prereqs | ||||||
|  |         shell: bash | ||||||
|  |         run: | | ||||||
|  |           make docs/reqs | ||||||
|  | 
 | ||||||
|       - name: Test build docs |       - name: Test build docs | ||||||
|         shell: bash |         shell: bash | ||||||
|         run: | |         run: | | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -981,8 +981,20 @@ endif | ||||||
| 
 | 
 | ||||||
| # also others, but so long as it doesn't fail this is enough to know we tried
 | # also others, but so long as it doesn't fail this is enough to know we tried
 | ||||||
| docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS) | docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS) | ||||||
| 	mkdir -p docs/source/cmd | 	$(Q) mkdir -p docs/source/cmd | ||||||
| 	./$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual' | 	$(Q) mkdir -p temp/docs/source/cmd | ||||||
|  | 	$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual' | ||||||
|  | 	$(Q) rsync -rc temp/docs/source/cmd docs/source | ||||||
|  | 	$(Q) rm -rf temp | ||||||
|  | docs/source/cell/word_add.rst: $(TARGETS) $(EXTRA_TARGETS) | ||||||
|  | 	$(Q) mkdir -p docs/source/cell | ||||||
|  | 	$(Q) mkdir -p temp/docs/source/cell | ||||||
|  | 	$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-cells-manual' | ||||||
|  | 	$(Q) rsync -rc temp/docs/source/cell docs/source | ||||||
|  | 	$(Q) rm -rf temp | ||||||
|  | 
 | ||||||
|  | docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS) | ||||||
|  | 	$(Q) ./$(PROGRAM_PREFIX)yosys -p 'help -dump-cells-json $@' | ||||||
| 
 | 
 | ||||||
| PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs | PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs | ||||||
| docs/gen_examples: $(TARGETS) | docs/gen_examples: $(TARGETS) | ||||||
|  | @ -1025,7 +1037,7 @@ docs/reqs: | ||||||
| 	$(Q) $(MAKE) -C docs reqs | 	$(Q) $(MAKE) -C docs reqs | ||||||
| 
 | 
 | ||||||
| .PHONY: docs/prep | .PHONY: docs/prep | ||||||
| docs/prep: docs/source/cmd/abc.rst docs/gen_examples docs/gen_images docs/guidelines docs/usage | docs/prep: docs/source/cmd/abc.rst docs/source/generated/cells.json docs/gen_examples docs/gen_images docs/guidelines docs/usage | ||||||
| 
 | 
 | ||||||
| DOC_TARGET ?= html | DOC_TARGET ?= html | ||||||
| docs: docs/prep | docs: docs/prep | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 33 KiB | 
|  | @ -1,40 +0,0 @@ | ||||||
| /* Don't hide the right sidebar as we're placing our fixed links there */ |  | ||||||
| aside.no-toc { |  | ||||||
|     display: block !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Colorful headings */ |  | ||||||
| h1 { |  | ||||||
|     color: var(--color-brand-primary); |  | ||||||
|   } |  | ||||||
|    |  | ||||||
| h2, h3, h4, h5, h6 { |  | ||||||
|     color: var(--color-brand-content); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Use a different color for external links */ |  | ||||||
| a.external { |  | ||||||
|     color: var(--color-brand-primary) !important; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .wy-table-responsive table td { |  | ||||||
|     white-space: normal; |  | ||||||
| } |  | ||||||
|    |  | ||||||
| th { |  | ||||||
|     text-align: left; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| body[data-theme="dark"] { |  | ||||||
|     .invert-helper { |  | ||||||
|         filter: url("data:image/svg+xml,<svg xmlns='http%3A//www.w3.org/2000/svg'><filter id='f'><feColorMatrix color-interpolation-filters='sRGB' type='matrix' values='1.47 -1.73 -0.467 0 0.867 -0.733 0.467 -0.467 0 0.867 -0.667 -1.07 1.07 0 0.867 0 0 0 1.0 0'></feColorMatrix></filter></svg>#f"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @media (prefers-color-scheme: dark) { |  | ||||||
|     body:not([data-theme="light"]) { |  | ||||||
|         .invert-helper { |  | ||||||
|             filter: url("data:image/svg+xml,<svg xmlns='http%3A//www.w3.org/2000/svg'><filter id='f'><feColorMatrix color-interpolation-filters='sRGB' type='matrix' values='1.47 -1.73 -0.467 0 0.867 -0.733 0.467 -0.467 0 0.867 -0.667 -1.07 1.07 0 0.867 0 0 0 1.0 0'></feColorMatrix></filter></svg>#f"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,44 +0,0 @@ | ||||||
| {# |  | ||||||
| 
 |  | ||||||
| See https://github.com/pradyunsg/furo/blob/main/src/furo/theme/furo/page.html for the original |  | ||||||
| block this is overwriting. |  | ||||||
| 
 |  | ||||||
| The part that is customized is between the "begin of custom part" and "end of custom part" |  | ||||||
| comments below. It uses the same styles as the existing right sidebar code. |  | ||||||
| 
 |  | ||||||
| #} |  | ||||||
| {% extends "furo/page.html" %} |  | ||||||
| {% block right_sidebar %} |  | ||||||
| <div class="toc-sticky toc-scroll"> |  | ||||||
| 	{# begin of custom part #} |  | ||||||
| 	<div class="toc-title-container"> |  | ||||||
| 	<span class="toc-title"> |  | ||||||
| 	YosysHQ |  | ||||||
| 	</span> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="toc-tree-container yosyshq-links" style="padding-bottom: 0"> |  | ||||||
| 	<div class="toc-tree"> |  | ||||||
| 	<ul> |  | ||||||
| 	<li></li> |  | ||||||
| 	<li><a class="reference external" href="https://yosyshq.readthedocs.io">Docs</a></li> |  | ||||||
| 	<li><a class="reference external" href="https://blog.yosyshq.com">Blog</a></li> |  | ||||||
| 	<li><a class="reference external" href="https://www.yosyshq.com">Website</a></li> |  | ||||||
| 	</ul> |  | ||||||
| 	</div> |  | ||||||
| 	</div> |  | ||||||
| 	{# end of custom part #} |  | ||||||
| 	{% if not furo_hide_toc %} |  | ||||||
| 	<div class="toc-title-container"> |  | ||||||
| 	<span class="toc-title"> |  | ||||||
| 	{{ _("On this page") }} |  | ||||||
| 	</span> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="toc-tree-container"> |  | ||||||
| 	<div class="toc-tree"> |  | ||||||
| 	{{ toc }} |  | ||||||
| 	</div> |  | ||||||
| 	</div> |  | ||||||
| 	{% endif %} |  | ||||||
| </div> |  | ||||||
| {% endblock %} |  | ||||||
| 	 |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| Appendix |  | ||||||
| ======== |  | ||||||
| 
 |  | ||||||
| .. toctree:: |  | ||||||
| 	:maxdepth: 2 |  | ||||||
| 	:includehidden: |  | ||||||
| 
 |  | ||||||
| 	appendix/primer |  | ||||||
| 	appendix/auxlibs |  | ||||||
| 	appendix/auxprogs |  | ||||||
| 
 |  | ||||||
| 	bib |  | ||||||
| 
 |  | ||||||
| .. toctree:: |  | ||||||
| 	:maxdepth: 1 |  | ||||||
| 	:includehidden: |  | ||||||
| 
 |  | ||||||
| 	cmd_ref |  | ||||||
|  | @ -29,7 +29,7 @@ ezSAT | ||||||
| 
 | 
 | ||||||
| The files in ``libs/ezsat`` provide a library for simplifying generating CNF | The files in ``libs/ezsat`` provide a library for simplifying generating CNF | ||||||
| formulas for SAT solvers. It also contains bindings of MiniSAT. The ezSAT | formulas for SAT solvers. It also contains bindings of MiniSAT. The ezSAT | ||||||
| library is written by C. Wolf. It is used by the :cmd:ref:`sat` pass (see | library is written by C. Wolf. It is used by the `sat` pass (see | ||||||
| :doc:`/cmd/sat`). | :doc:`/cmd/sat`). | ||||||
| 
 | 
 | ||||||
| fst | fst | ||||||
|  | @ -37,22 +37,22 @@ fst | ||||||
| 
 | 
 | ||||||
| ``libfst`` files from `gtkwave`_ are included in ``libs/fst`` to support | ``libfst`` files from `gtkwave`_ are included in ``libs/fst`` to support | ||||||
| reading/writing signal traces from/to the GTKWave developed FST format.  This is | reading/writing signal traces from/to the GTKWave developed FST format.  This is | ||||||
| primarily used in the :cmd:ref:`sim` command. | primarily used in the `sim` command. | ||||||
| 
 | 
 | ||||||
| .. _gtkwave: https://github.com/gtkwave/gtkwave | .. _gtkwave: https://github.com/gtkwave/gtkwave | ||||||
| 
 | 
 | ||||||
| json11 | json11 | ||||||
| ------ | ------ | ||||||
| 
 | 
 | ||||||
| For reading/writing designs from/to JSON, :cmd:ref:`read_json` and | For reading/writing designs from/to JSON, `read_json` and | ||||||
| :cmd:ref:`write_json` should be used.  For everything else there is the `json11 | `write_json` should be used.  For everything else there is the `json11 | ||||||
| library`_: | library`_: | ||||||
| 
 | 
 | ||||||
|    json11 is a tiny JSON library for C++11, providing JSON parsing and |    json11 is a tiny JSON library for C++11, providing JSON parsing and | ||||||
|    serialization. |    serialization. | ||||||
| 
 | 
 | ||||||
| This library is used for outputting machine-readable statistics (:cmd:ref:`stat` | This library is used for outputting machine-readable statistics (`stat` | ||||||
| with ``-json`` flag), using the RPC frontend (:cmd:ref:`connect_rpc`), and the | with ``-json`` flag), using the RPC frontend (`connect_rpc`), and the | ||||||
| yosys-witness ``yw`` format. | yosys-witness ``yw`` format. | ||||||
| 
 | 
 | ||||||
| .. _json11 library: https://github.com/dropbox/json11 | .. _json11 library: https://github.com/dropbox/json11 | ||||||
|  | @ -61,7 +61,7 @@ MiniSAT | ||||||
| ------- | ------- | ||||||
| 
 | 
 | ||||||
| The files in ``libs/minisat`` provide a high-performance SAT solver, used by the | The files in ``libs/minisat`` provide a high-performance SAT solver, used by the | ||||||
| :cmd:ref:`sat` command. | `sat` command. | ||||||
| 
 | 
 | ||||||
| SHA1 | SHA1 | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ Yosys environment variables | ||||||
| 
 | 
 | ||||||
| ``HOME`` | ``HOME`` | ||||||
|    Yosys command history is stored in :file:`$HOME/.yosys_history`.  Graphics |    Yosys command history is stored in :file:`$HOME/.yosys_history`.  Graphics | ||||||
|    (from :cmd:ref:`show` and :cmd:ref:`viz` commands) will output to this |    (from `show` and `viz` commands) will output to this | ||||||
|    directory by default.  This environment variable is also used in some cases |    directory by default.  This environment variable is also used in some cases | ||||||
|    for resolving filenames with :file:`~`. |    for resolving filenames with :file:`~`. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -223,8 +223,8 @@ Cells | ||||||
| Declares a cell, with zero or more attributes, with the given identifier and | Declares a cell, with zero or more attributes, with the given identifier and | ||||||
| type in the enclosing module. | type in the enclosing module. | ||||||
| 
 | 
 | ||||||
| Cells perform functions on input signals. See | Cells perform functions on input signals. See :doc:`/cell_index` for a detailed | ||||||
| :doc:`/yosys_internals/formats/cell_library` for a detailed list of cell types. | list of cell types. | ||||||
| 
 | 
 | ||||||
| .. code:: BNF | .. code:: BNF | ||||||
| 
 | 
 | ||||||
							
								
								
									
										53
									
								
								docs/source/cell/gate_comb_combined.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								docs/source/cell/gate_comb_combined.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Combinatorial cells (combined) | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  | These cells combine two or more combinatorial cells (simple) into a single cell. | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level combinatorial cells (combined) | ||||||
|  | 
 | ||||||
|  |    ======================================= ============= | ||||||
|  |    Verilog                                 Cell Type | ||||||
|  |    ======================================= ============= | ||||||
|  |    :verilog:`Y = A & ~B`                   `$_ANDNOT_` | ||||||
|  |    :verilog:`Y = A | ~B`                   `$_ORNOT_` | ||||||
|  |    :verilog:`Y = ~((A & B) | C)`           `$_AOI3_` | ||||||
|  |    :verilog:`Y = ~((A | B) & C)`           `$_OAI3_` | ||||||
|  |    :verilog:`Y = ~((A & B) | (C & D))`     `$_AOI4_` | ||||||
|  |    :verilog:`Y = ~((A | B) & (C | D))`     `$_OAI4_` | ||||||
|  |    :verilog:`Y = ~(S ? B : A)`             `$_NMUX_` | ||||||
|  |    (see below)                             `$_MUX4_` | ||||||
|  |    (see below)                             `$_MUX8_` | ||||||
|  |    (see below)                             `$_MUX16_` | ||||||
|  |    ======================================= ============= | ||||||
|  | 
 | ||||||
|  | The `$_MUX4_`, `$_MUX8_` and `$_MUX16_` cells are used to model wide muxes, and | ||||||
|  | correspond to the following Verilog code: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    // $_MUX4_ | ||||||
|  |    assign Y = T ? (S ? D : C) : | ||||||
|  |                   (S ? B : A); | ||||||
|  |    // $_MUX8_ | ||||||
|  |    assign Y = U ? T ? (S ? H : G) : | ||||||
|  |                       (S ? F : E) : | ||||||
|  |                   T ? (S ? D : C) : | ||||||
|  |                       (S ? B : A); | ||||||
|  |    // $_MUX16_ | ||||||
|  |    assign Y = V ? U ? T ? (S ? P : O) : | ||||||
|  |                           (S ? N : M) : | ||||||
|  |                       T ? (S ? L : K) : | ||||||
|  |                           (S ? J : I) : | ||||||
|  |                   U ? T ? (S ? H : G) : | ||||||
|  |                           (S ? F : E) : | ||||||
|  |                       T ? (S ? D : C) : | ||||||
|  |                           (S ? B : A); | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: comb_combined | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										26
									
								
								docs/source/cell/gate_comb_simple.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								docs/source/cell/gate_comb_simple.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Combinatorial cells (simple) | ||||||
|  | ---------------------------- | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level combinatorial cells (simple) | ||||||
|  | 
 | ||||||
|  |    ======================================= ============= | ||||||
|  |    Verilog                                 Cell Type | ||||||
|  |    ======================================= ============= | ||||||
|  |    :verilog:`Y = A`                        `$_BUF_` | ||||||
|  |    :verilog:`Y = ~A`                       `$_NOT_` | ||||||
|  |    :verilog:`Y = A & B`                    `$_AND_` | ||||||
|  |    :verilog:`Y = ~(A & B)`                 `$_NAND_` | ||||||
|  |    :verilog:`Y = A | B`                    `$_OR_` | ||||||
|  |    :verilog:`Y = ~(A | B)`                 `$_NOR_` | ||||||
|  |    :verilog:`Y = A ^ B`                    `$_XOR_` | ||||||
|  |    :verilog:`Y = ~(A ^ B)`                 `$_XNOR_` | ||||||
|  |    :verilog:`Y = S ? B : A`                `$_MUX_` | ||||||
|  |    ======================================= ============= | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: comb_simple | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										8
									
								
								docs/source/cell/gate_other.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/source/cell/gate_other.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | Other gate-level cells | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: gate_other | ||||||
|  |    :caption: Other gate-level cells | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										231
									
								
								docs/source/cell/gate_reg_ff.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								docs/source/cell/gate_reg_ff.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,231 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Flip-flop cells | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | The cell types `$_DFF_N_` and `$_DFF_P_` represent d-type flip-flops. | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for basic flip-flops | ||||||
|  | 
 | ||||||
|  |    ======================================= ============= | ||||||
|  |    Verilog                                 Cell Type | ||||||
|  |    ======================================= ============= | ||||||
|  |    :verilog:`always @(negedge C) Q <= D`   `$_DFF_N_` | ||||||
|  |    :verilog:`always @(posedge C) Q <= D`   `$_DFF_P_` | ||||||
|  |    ======================================= ============= | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DFFE_[NP][NP]_`` implement d-type flip-flops with enable. The | ||||||
|  | values in the table for these cell types relate to the following Verilog code | ||||||
|  | template. | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C) | ||||||
|  |       if (EN == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (FFs with enable) | ||||||
|  |    :name: tab:CellLib_gates_dffe | ||||||
|  | 
 | ||||||
|  |    ================== ============= ============ | ||||||
|  |    :math:`ClkEdge`    :math:`EnLvl` Cell Type | ||||||
|  |    ================== ============= ============ | ||||||
|  |    :verilog:`negedge` ``0``         `$_DFFE_NN_` | ||||||
|  |    :verilog:`negedge` ``1``         `$_DFFE_NP_` | ||||||
|  |    :verilog:`posedge` ``0``         `$_DFFE_PN_` | ||||||
|  |    :verilog:`posedge` ``1``         `$_DFFE_PP_` | ||||||
|  |    ================== ============= ============ | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DFF_[NP][NP][01]_`` implement d-type flip-flops with | ||||||
|  | asynchronous reset. The values in the table for these cell types relate to the | ||||||
|  | following Verilog code template, where ``RST_EDGE`` is ``posedge`` if | ||||||
|  | ``RST_LVL`` if ``1``, and ``negedge`` otherwise. | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C, RST_EDGE R) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= RST_VAL; | ||||||
|  |       else | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | The cell types ``$_SDFF_[NP][NP][01]_`` implement d-type flip-flops with | ||||||
|  | synchronous reset. The values in the table for these cell types relate to the | ||||||
|  | following Verilog code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= RST_VAL; | ||||||
|  |       else | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (FFs with reset) | ||||||
|  |    :name: tab:CellLib_gates_adff | ||||||
|  | 
 | ||||||
|  |    ================== ============== ============== =========================== | ||||||
|  |    :math:`ClkEdge`    :math:`RstLvl` :math:`RstVal` Cell Type | ||||||
|  |    ================== ============== ============== =========================== | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          `$_DFF_NN0_`, `$_SDFF_NN0_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          `$_DFF_NN1_`, `$_SDFF_NN1_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          `$_DFF_NP0_`, `$_SDFF_NP0_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          `$_DFF_NP1_`, `$_SDFF_NP1_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          `$_DFF_PN0_`, `$_SDFF_PN0_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          `$_DFF_PN1_`, `$_SDFF_PN1_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          `$_DFF_PP0_`, `$_SDFF_PP0_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          `$_DFF_PP1_`, `$_SDFF_PP1_` | ||||||
|  |    ================== ============== ============== =========================== | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DFFE_[NP][NP][01][NP]_`` implement d-type flip-flops with | ||||||
|  | asynchronous reset and enable. The values in the table for these cell types | ||||||
|  | relate to the following Verilog code template, where ``RST_EDGE`` is ``posedge`` | ||||||
|  | if ``RST_LVL`` if ``1``, and ``negedge`` otherwise. | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C, RST_EDGE R) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= RST_VAL; | ||||||
|  |       else if (EN == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | The cell types ``$_SDFFE_[NP][NP][01][NP]_`` implement d-type flip-flops with | ||||||
|  | synchronous reset and enable, with reset having priority over enable. The values | ||||||
|  | in the table for these cell types relate to the following Verilog code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= RST_VAL; | ||||||
|  |       else if (EN == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | The cell types ``$_SDFFCE_[NP][NP][01][NP]_`` implement d-type flip-flops with | ||||||
|  | synchronous reset and enable, with enable having priority over reset. The values | ||||||
|  | in the table for these cell types relate to the following Verilog code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C) | ||||||
|  |       if (EN == EN_LVL) | ||||||
|  |          if (R == RST_LVL) | ||||||
|  |             Q <= RST_VAL; | ||||||
|  |          else | ||||||
|  |             Q <= D; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (FFs with reset and enable) | ||||||
|  |    :name: tab:CellLib_gates_adffe | ||||||
|  | 
 | ||||||
|  |    ================== ============== ============== ============= ================================================= | ||||||
|  |    :math:`ClkEdge`    :math:`RstLvl` :math:`RstVal` :math:`EnLvl` Cell Type | ||||||
|  |    ================== ============== ============== ============= ================================================= | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          ``0``         `$_DFFE_NN0N_`, `$_SDFFE_NN0N_`, `$_SDFFCE_NN0N_` | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          ``1``         `$_DFFE_NN0P_`, `$_SDFFE_NN0P_`, `$_SDFFCE_NN0P_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          ``0``         `$_DFFE_NN1N_`, `$_SDFFE_NN1N_`, `$_SDFFCE_NN1N_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          ``1``         `$_DFFE_NN1P_`, `$_SDFFE_NN1P_`, `$_SDFFCE_NN1P_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          ``0``         `$_DFFE_NP0N_`, `$_SDFFE_NP0N_`, `$_SDFFCE_NP0N_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          ``1``         `$_DFFE_NP0P_`, `$_SDFFE_NP0P_`, `$_SDFFCE_NP0P_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          ``0``         `$_DFFE_NP1N_`, `$_SDFFE_NP1N_`, `$_SDFFCE_NP1N_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          ``1``         `$_DFFE_NP1P_`, `$_SDFFE_NP1P_`, `$_SDFFCE_NP1P_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          ``0``         `$_DFFE_PN0N_`, `$_SDFFE_PN0N_`, `$_SDFFCE_PN0N_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          ``1``         `$_DFFE_PN0P_`, `$_SDFFE_PN0P_`, `$_SDFFCE_PN0P_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          ``0``         `$_DFFE_PN1N_`, `$_SDFFE_PN1N_`, `$_SDFFCE_PN1N_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          ``1``         `$_DFFE_PN1P_`, `$_SDFFE_PN1P_`, `$_SDFFCE_PN1P_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          ``0``         `$_DFFE_PP0N_`, `$_SDFFE_PP0N_`, `$_SDFFCE_PP0N_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          ``1``         `$_DFFE_PP0P_`, `$_SDFFE_PP0P_`, `$_SDFFCE_PP0P_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          ``0``         `$_DFFE_PP1N_`, `$_SDFFE_PP1N_`, `$_SDFFCE_PP1N_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          ``1``         `$_DFFE_PP1P_`, `$_SDFFE_PP1P_`, `$_SDFFCE_PP1P_` | ||||||
|  |    ================== ============== ============== ============= ================================================= | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DFFSR_[NP][NP][NP]_`` implement d-type flip-flops with | ||||||
|  | asynchronous set and reset. The values in the table for these cell types relate | ||||||
|  | to the following Verilog code template, where ``RST_EDGE`` is ``posedge`` if | ||||||
|  | ``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is ``posedge`` if | ||||||
|  | ``SET_LVL`` if ``1``, ``negedge`` otherwise. | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C, RST_EDGE R, SET_EDGE S) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= 0; | ||||||
|  |       else if (S == SET_LVL) | ||||||
|  |          Q <= 1; | ||||||
|  |       else | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (FFs with set and reset) | ||||||
|  |    :name: tab:CellLib_gates_dffsr | ||||||
|  | 
 | ||||||
|  |    ================== ============== ============== ============== | ||||||
|  |    :math:`ClkEdge`    :math:`SetLvl` :math:`RstLvl` Cell Type | ||||||
|  |    ================== ============== ============== ============== | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          `$_DFFSR_NNN_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          `$_DFFSR_NNP_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          `$_DFFSR_NPN_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          `$_DFFSR_NPP_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          `$_DFFSR_PNN_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          `$_DFFSR_PNP_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          `$_DFFSR_PPN_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          `$_DFFSR_PPP_` | ||||||
|  |    ================== ============== ============== ============== | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DFFSRE_[NP][NP][NP][NP]_`` implement d-type flip-flops with | ||||||
|  | asynchronous set and reset and enable. The values in the table for these cell | ||||||
|  | types relate to the following Verilog code template, where ``RST_EDGE`` is | ||||||
|  | ``posedge`` if ``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is | ||||||
|  | ``posedge`` if ``SET_LVL`` if ``1``, ``negedge`` otherwise. | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @(CLK_EDGE C, RST_EDGE R, SET_EDGE S) | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= 0; | ||||||
|  |       else if (S == SET_LVL) | ||||||
|  |          Q <= 1; | ||||||
|  |       else if (E == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (FFs with set and reset and enable) | ||||||
|  |    :name: tab:CellLib_gates_dffsre | ||||||
|  | 
 | ||||||
|  |    ================== ============== ============== ============= ================ | ||||||
|  |    :math:`ClkEdge`    :math:`SetLvl` :math:`RstLvl` :math:`EnLvl` Cell Type | ||||||
|  |    ================== ============== ============== ============= ================ | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          ``0``         `$_DFFSRE_NNNN_` | ||||||
|  |    :verilog:`negedge` ``0``          ``0``          ``1``         `$_DFFSRE_NNNP_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          ``0``         `$_DFFSRE_NNPN_` | ||||||
|  |    :verilog:`negedge` ``0``          ``1``          ``1``         `$_DFFSRE_NNPP_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          ``0``         `$_DFFSRE_NPNN_` | ||||||
|  |    :verilog:`negedge` ``1``          ``0``          ``1``         `$_DFFSRE_NPNP_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          ``0``         `$_DFFSRE_NPPN_` | ||||||
|  |    :verilog:`negedge` ``1``          ``1``          ``1``         `$_DFFSRE_NPPP_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          ``0``         `$_DFFSRE_PNNN_` | ||||||
|  |    :verilog:`posedge` ``0``          ``0``          ``1``         `$_DFFSRE_PNNP_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          ``0``         `$_DFFSRE_PNPN_` | ||||||
|  |    :verilog:`posedge` ``0``          ``1``          ``1``         `$_DFFSRE_PNPP_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          ``0``         `$_DFFSRE_PPNN_` | ||||||
|  |    :verilog:`posedge` ``1``          ``0``          ``1``         `$_DFFSRE_PPNP_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          ``0``         `$_DFFSRE_PPPN_` | ||||||
|  |    :verilog:`posedge` ``1``          ``1``          ``1``         `$_DFFSRE_PPPP_` | ||||||
|  |    ================== ============== ============== ============= ================ | ||||||
|  | 
 | ||||||
|  | .. todo:: flip-flops with async load, ``$_ALDFFE?_[NP]{2,3}_`` | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: reg_ff | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										105
									
								
								docs/source/cell/gate_reg_latch.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								docs/source/cell/gate_reg_latch.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Latch cells | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
|  | The cell types `$_DLATCH_N_` and `$_DLATCH_P_` represent d-type latches. | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for basic latches | ||||||
|  | 
 | ||||||
|  |    ======================================= ============= | ||||||
|  |    Verilog                                 Cell Type | ||||||
|  |    ======================================= ============= | ||||||
|  |    :verilog:`always @* if (!E) Q <= D`     `$_DLATCH_N_` | ||||||
|  |    :verilog:`always @* if (E)  Q <= D`     `$_DLATCH_P_` | ||||||
|  |    ======================================= ============= | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DLATCH_[NP][NP][01]_`` implement d-type latches with reset. | ||||||
|  | The values in the table for these cell types relate to the following Verilog | ||||||
|  | code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @* | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= RST_VAL; | ||||||
|  |       else if (E == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (latches with reset) | ||||||
|  |    :name: tab:CellLib_gates_adlatch | ||||||
|  | 
 | ||||||
|  |    ============= ============== ============== =============== | ||||||
|  |    :math:`EnLvl` :math:`RstLvl` :math:`RstVal` Cell Type | ||||||
|  |    ============= ============== ============== =============== | ||||||
|  |    ``0``         ``0``          ``0``          `$_DLATCH_NN0_` | ||||||
|  |    ``0``         ``0``          ``1``          `$_DLATCH_NN1_` | ||||||
|  |    ``0``         ``1``          ``0``          `$_DLATCH_NP0_` | ||||||
|  |    ``0``         ``1``          ``1``          `$_DLATCH_NP1_` | ||||||
|  |    ``1``         ``0``          ``0``          `$_DLATCH_PN0_` | ||||||
|  |    ``1``         ``0``          ``1``          `$_DLATCH_PN1_` | ||||||
|  |    ``1``         ``1``          ``0``          `$_DLATCH_PP0_` | ||||||
|  |    ``1``         ``1``          ``1``          `$_DLATCH_PP1_` | ||||||
|  |    ============= ============== ============== =============== | ||||||
|  | 
 | ||||||
|  | The cell types ``$_DLATCHSR_[NP][NP][NP]_`` implement d-type latches with set | ||||||
|  | and reset. The values in the table for these cell types relate to the following | ||||||
|  | Verilog code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @* | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= 0; | ||||||
|  |       else if (S == SET_LVL) | ||||||
|  |          Q <= 1; | ||||||
|  |       else if (E == EN_LVL) | ||||||
|  |          Q <= D; | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (latches with set and reset) | ||||||
|  |    :name: tab:CellLib_gates_dlatchsr | ||||||
|  | 
 | ||||||
|  |    ============= ============== ============== ================= | ||||||
|  |    :math:`EnLvl` :math:`SetLvl` :math:`RstLvl` Cell Type | ||||||
|  |    ============= ============== ============== ================= | ||||||
|  |    ``0``         ``0``          ``0``          `$_DLATCHSR_NNN_` | ||||||
|  |    ``0``         ``0``          ``1``          `$_DLATCHSR_NNP_` | ||||||
|  |    ``0``         ``1``          ``0``          `$_DLATCHSR_NPN_` | ||||||
|  |    ``0``         ``1``          ``1``          `$_DLATCHSR_NPP_` | ||||||
|  |    ``1``         ``0``          ``0``          `$_DLATCHSR_PNN_` | ||||||
|  |    ``1``         ``0``          ``1``          `$_DLATCHSR_PNP_` | ||||||
|  |    ``1``         ``1``          ``0``          `$_DLATCHSR_PPN_` | ||||||
|  |    ``1``         ``1``          ``1``          `$_DLATCHSR_PPP_` | ||||||
|  |    ============= ============== ============== ================= | ||||||
|  | 
 | ||||||
|  | The cell types ``$_SR_[NP][NP]_`` implement sr-type latches. The values in the | ||||||
|  | table for these cell types relate to the following Verilog code template: | ||||||
|  | 
 | ||||||
|  | .. code-block:: verilog | ||||||
|  |    :force: | ||||||
|  | 
 | ||||||
|  |    always @* | ||||||
|  |       if (R == RST_LVL) | ||||||
|  |          Q <= 0; | ||||||
|  |       else if (S == SET_LVL) | ||||||
|  |          Q <= 1; | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for gate level logic networks (SR latches) | ||||||
|  |    :name: tab:CellLib_gates_sr | ||||||
|  | 
 | ||||||
|  |    ============== ============== ========== | ||||||
|  |    :math:`SetLvl` :math:`RstLvl` Cell Type | ||||||
|  |    ============== ============== ========== | ||||||
|  |    ``0``          ``0``          `$_SR_NN_` | ||||||
|  |    ``0``          ``1``          `$_SR_NP_` | ||||||
|  |    ``1``          ``0``          `$_SR_PN_` | ||||||
|  |    ``1``          ``1``          `$_SR_PP_` | ||||||
|  |    ============== ============== ========== | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: reg_latch | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										25
									
								
								docs/source/cell/index_gate.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								docs/source/cell/index_gate.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | .. _sec:celllib_gates: | ||||||
|  | 
 | ||||||
|  | Gate-level cells | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  | For gate level logic networks, fixed function single bit cells are used that do | ||||||
|  | not provide any parameters. | ||||||
|  | 
 | ||||||
|  | Simulation models for these cells can be found in the file | ||||||
|  | :file:`techlibs/common/simcells.v` in the Yosys source tree. | ||||||
|  | 
 | ||||||
|  | In most cases gate level logic networks are created from RTL networks using the | ||||||
|  | techmap pass. The flip-flop cells from the gate level logic network can be | ||||||
|  | mapped to physical flip-flop cells from a Liberty file using the dfflibmap pass. | ||||||
|  | The combinatorial logic cells can be mapped to physical cells from a Liberty | ||||||
|  | file via ABC using the abc pass. | ||||||
|  | 
 | ||||||
|  | .. toctree:: | ||||||
|  |    :maxdepth: 2 | ||||||
|  | 
 | ||||||
|  |    /cell/gate_comb_simple | ||||||
|  |    /cell/gate_comb_combined | ||||||
|  |    /cell/gate_reg_ff | ||||||
|  |    /cell/gate_reg_latch | ||||||
|  |    /cell/gate_other | ||||||
							
								
								
									
										30
									
								
								docs/source/cell/index_word.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								docs/source/cell/index_word.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | Word-level cells | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  | Most of the RTL cells closely resemble the operators available in HDLs such as | ||||||
|  | Verilog or VHDL. Therefore Verilog operators are used in the following sections | ||||||
|  | to define the behaviour of the RTL cells. | ||||||
|  | 
 | ||||||
|  | Note that all RTL cells have parameters indicating the size of inputs and | ||||||
|  | outputs. When passes modify RTL cells they must always keep the values of these | ||||||
|  | parameters in sync with the size of the signals connected to the inputs and | ||||||
|  | outputs. | ||||||
|  | 
 | ||||||
|  | Simulation models for the RTL cells can be found in the file | ||||||
|  | :file:`techlibs/common/simlib.v` in the Yosys source tree. | ||||||
|  | 
 | ||||||
|  | .. toctree:: | ||||||
|  |    :maxdepth: 2 | ||||||
|  | 
 | ||||||
|  |    /cell/word_unary | ||||||
|  |    /cell/word_binary | ||||||
|  |    /cell/word_mux | ||||||
|  |    /cell/word_reg | ||||||
|  |    /cell/word_mem | ||||||
|  |    /cell/word_fsm | ||||||
|  |    /cell/word_arith | ||||||
|  |    /cell/word_logic | ||||||
|  |    /cell/word_spec | ||||||
|  |    /cell/word_formal | ||||||
|  |    /cell/word_debug | ||||||
|  |    /cell/word_wire | ||||||
							
								
								
									
										21
									
								
								docs/source/cell/properties.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/source/cell/properties.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | Cell properties | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | .. cell:defprop:: is_evaluable | ||||||
|  | 
 | ||||||
|  |    These cells are able to be used in conjunction with the `eval` command.  Some | ||||||
|  |    passes, such as `opt_expr`, may also be able to perform additional | ||||||
|  |    optimizations on cells which are evaluable. | ||||||
|  | 
 | ||||||
|  | .. cell:defprop:: x-aware | ||||||
|  | 
 | ||||||
|  |    Some passes will treat these cells as the non 'x' aware cell.  For example, | ||||||
|  |    during synthesis `$eqx` will typically be treated as `$eq`. | ||||||
|  | 
 | ||||||
|  | .. cell:defprop:: x-output | ||||||
|  | 
 | ||||||
|  |    These cells can produce 'x' output even if all inputs are defined.  For | ||||||
|  |    example, a `$div` cell with divisor (``B``) equal to zero has undefined | ||||||
|  |    output. | ||||||
|  | 
 | ||||||
|  | Refer to the :ref:`propindex` for the list of cells with a given property. | ||||||
							
								
								
									
										50
									
								
								docs/source/cell/word_arith.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								docs/source/cell/word_arith.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | Coarse arithmetics | ||||||
|  | ------------------ | ||||||
|  | 
 | ||||||
|  | .. todo:: Add information about `$alu`, `$fa`, and `$lcu` cells. | ||||||
|  | 
 | ||||||
|  | The `$macc` cell type represents a generalized multiply and accumulate | ||||||
|  | operation. The cell is purely combinational. It outputs the result of summing up | ||||||
|  | a sequence of products and other injected summands. | ||||||
|  | 
 | ||||||
|  | .. code-block:: | ||||||
|  | 
 | ||||||
|  |    Y = 0 +- a0factor1 * a0factor2 +- a1factor1 * a1factor2 +- ... | ||||||
|  |         + B[0] + B[1] + ... | ||||||
|  | 
 | ||||||
|  | The A port consists of concatenated pairs of multiplier inputs ("factors"). A | ||||||
|  | zero length factor2 acts as a constant 1, turning factor1 into a simple summand. | ||||||
|  | 
 | ||||||
|  | In this pseudocode, ``u(foo)`` means an unsigned int that's foo bits long. | ||||||
|  | 
 | ||||||
|  | .. code-block:: | ||||||
|  | 
 | ||||||
|  |    struct A { | ||||||
|  |       u(CONFIG.mul_info[0].factor1_len) a0factor1; | ||||||
|  |       u(CONFIG.mul_info[0].factor2_len) a0factor2; | ||||||
|  |       u(CONFIG.mul_info[1].factor1_len) a1factor1; | ||||||
|  |       u(CONFIG.mul_info[1].factor2_len) a1factor2; | ||||||
|  |       ... | ||||||
|  |    }; | ||||||
|  | 
 | ||||||
|  | The cell's ``CONFIG`` parameter determines the layout of cell port ``A``. The | ||||||
|  | CONFIG parameter carries the following information: | ||||||
|  | 
 | ||||||
|  | .. code-block:: | ||||||
|  | 
 | ||||||
|  |    struct CONFIG { | ||||||
|  |       u4 num_bits; | ||||||
|  |       struct mul_info { | ||||||
|  |          bool is_signed; | ||||||
|  |          bool is_subtract; | ||||||
|  |          u(num_bits) factor1_len; | ||||||
|  |          u(num_bits) factor2_len; | ||||||
|  |       }[num_ports]; | ||||||
|  |    }; | ||||||
|  | 
 | ||||||
|  | B is an array of concatenated 1-bit-wide unsigned integers to also be summed up. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: arith | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										91
									
								
								docs/source/cell/word_binary.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								docs/source/cell/word_binary.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Binary operators | ||||||
|  | ~~~~~~~~~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | All binary RTL cells have two input ports ``A`` and ``B`` and one output port | ||||||
|  | ``Y``. They also have the following parameters: | ||||||
|  | 
 | ||||||
|  | ``A_SIGNED`` | ||||||
|  |    Set to a non-zero value if the input ``A`` is signed and therefore should be | ||||||
|  |    sign-extended when needed. | ||||||
|  | 
 | ||||||
|  | ``A_WIDTH`` | ||||||
|  |    The width of the input port ``A``. | ||||||
|  | 
 | ||||||
|  | ``B_SIGNED`` | ||||||
|  |    Set to a non-zero value if the input ``B`` is signed and therefore should be | ||||||
|  |    sign-extended when needed. | ||||||
|  | 
 | ||||||
|  | ``B_WIDTH`` | ||||||
|  |    The width of the input port ``B``. | ||||||
|  | 
 | ||||||
|  | ``Y_WIDTH`` | ||||||
|  |    The width of the output port ``Y``. | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for binary operators with their corresponding Verilog expressions. | ||||||
|  | 
 | ||||||
|  |    ======================= =============== ======================= =========== | ||||||
|  |    Verilog                 Cell Type       Verilog                 Cell Type | ||||||
|  |    ======================= =============== ======================= =========== | ||||||
|  |    :verilog:`Y = A  & B`   `$and`          :verilog:`Y = A ** B`   `$pow` | ||||||
|  |    :verilog:`Y = A  | B`   `$or`           :verilog:`Y = A <  B`   `$lt` | ||||||
|  |    :verilog:`Y = A  ^ B`   `$xor`          :verilog:`Y = A <= B`   `$le` | ||||||
|  |    :verilog:`Y = A ~^ B`   `$xnor`         :verilog:`Y = A == B`   `$eq` | ||||||
|  |    :verilog:`Y = A << B`   `$shl`          :verilog:`Y = A != B`   `$ne` | ||||||
|  |    :verilog:`Y = A >> B`   `$shr`          :verilog:`Y = A >= B`   `$ge` | ||||||
|  |    :verilog:`Y = A <<< B`  `$sshl`         :verilog:`Y = A >  B`   `$gt` | ||||||
|  |    :verilog:`Y = A >>> B`  `$sshr`         :verilog:`Y = A  + B`   `$add` | ||||||
|  |    :verilog:`Y = A && B`   `$logic_and`    :verilog:`Y = A  - B`   `$sub` | ||||||
|  |    :verilog:`Y = A || B`   `$logic_or`     :verilog:`Y = A  * B`   `$mul` | ||||||
|  |    :verilog:`Y = A === B`  `$eqx`          :verilog:`Y = A  / B`   `$div` | ||||||
|  |    :verilog:`Y = A !== B`  `$nex`          :verilog:`Y = A  % B`   `$mod` | ||||||
|  |    ``N/A``                 `$shift`        ``N/A``                 `$divfloor` | ||||||
|  |    ``N/A``                 `$shiftx`       ``N/A``                 `$modfloor` | ||||||
|  |    ======================= =============== ======================= =========== | ||||||
|  | 
 | ||||||
|  | The `$shl` and `$shr` cells implement logical shifts, whereas the `$sshl` and | ||||||
|  | `$sshr` cells implement arithmetic shifts. The `$shl` and `$sshl` cells | ||||||
|  | implement the same operation. All four of these cells interpret the second | ||||||
|  | operand as unsigned, and require ``B_SIGNED`` to be zero. | ||||||
|  | 
 | ||||||
|  | Two additional shift operator cells are available that do not directly | ||||||
|  | correspond to any operator in Verilog, `$shift` and `$shiftx`. The `$shift` cell | ||||||
|  | performs a right logical shift if the second operand is positive (or unsigned), | ||||||
|  | and a left logical shift if it is negative. The `$shiftx` cell performs the same | ||||||
|  | operation as the `$shift` cell, but the vacated bit positions are filled with | ||||||
|  | undef (x) bits, and corresponds to the Verilog indexed part-select expression. | ||||||
|  | 
 | ||||||
|  | For the binary cells that output a logical value (`$logic_and`, `$logic_or`, | ||||||
|  | `$eqx`, `$nex`, `$lt`, `$le`, `$eq`, `$ne`, `$ge`, `$gt`), when the ``Y_WIDTH`` | ||||||
|  | parameter is greater than 1, the output is zero-extended, and only the least | ||||||
|  | significant bit varies. | ||||||
|  | 
 | ||||||
|  | Division and modulo cells are available in two rounding modes. The original | ||||||
|  | `$div` and `$mod` cells are based on truncating division, and correspond to the | ||||||
|  | semantics of the verilog ``/`` and ``%`` operators. The `$divfloor` and | ||||||
|  | `$modfloor` cells represent flooring division and flooring modulo, the latter of | ||||||
|  | which corresponds to the ``%`` operator in Python. See the following table for a | ||||||
|  | side-by-side comparison between the different semantics. | ||||||
|  | 
 | ||||||
|  | .. table:: Comparison between different rounding modes for division and modulo cells. | ||||||
|  | 
 | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  |    | Division  | Result |      Truncating       |        Flooring       | | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  |    |           |        | $div      | $mod      | $divfloor | $modfloor | | ||||||
|  |    +===========+========+===========+===========+===========+===========+ | ||||||
|  |    | -10 / 3   | -3.3   | -3        |        -1 | -4        |  2        | | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  |    | 10 / -3   | -3.3   | -3        |         1 | -4        | -2        | | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  |    | -10 / -3  |  3.3   |  3        |        -1 |  3        | -1        | | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  |    | 10 / 3    |  3.3   |  3        |         1 |  3        |  1        | | ||||||
|  |    +-----------+--------+-----------+-----------+-----------+-----------+ | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: binary | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										138
									
								
								docs/source/cell/word_debug.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								docs/source/cell/word_debug.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,138 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Debugging cells | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | The `$print` cell is used to log the values of signals, akin to (and | ||||||
|  | translatable to) the ``$display`` and ``$write`` family of tasks in Verilog.  It | ||||||
|  | has the following parameters: | ||||||
|  | 
 | ||||||
|  | ``FORMAT`` | ||||||
|  |    The internal format string.  The syntax is described below. | ||||||
|  | 
 | ||||||
|  | ``ARGS_WIDTH`` | ||||||
|  |    The width (in bits) of the signal on the ``ARGS`` port. | ||||||
|  | 
 | ||||||
|  | ``TRG_ENABLE`` | ||||||
|  |    True if triggered on specific signals defined in ``TRG``; false if triggered | ||||||
|  |    whenever ``ARGS`` or ``EN`` change and ``EN`` is 1. | ||||||
|  | 
 | ||||||
|  | If ``TRG_ENABLE`` is true, the following parameters also apply: | ||||||
|  | 
 | ||||||
|  | ``TRG_WIDTH`` | ||||||
|  |    The number of bits in the ``TRG`` port. | ||||||
|  | 
 | ||||||
|  | ``TRG_POLARITY`` | ||||||
|  |    For each bit in ``TRG``, 1 if that signal is positive-edge triggered, 0 if | ||||||
|  |    negative-edge triggered. | ||||||
|  | 
 | ||||||
|  | ``PRIORITY`` | ||||||
|  |    When multiple `$print` or `$check` cells fire on the same trigger, they | ||||||
|  |    execute in descending priority order. | ||||||
|  | 
 | ||||||
|  | Ports: | ||||||
|  | 
 | ||||||
|  | ``TRG`` | ||||||
|  |    The signals that control when this `$print` cell is triggered. | ||||||
|  | 
 | ||||||
|  |    If the width of this port is zero and ``TRG_ENABLE`` is true, the cell is | ||||||
|  |    triggered during initial evaluation (time zero) only. | ||||||
|  | 
 | ||||||
|  | ``EN`` | ||||||
|  |    Enable signal for the whole cell. | ||||||
|  | 
 | ||||||
|  | ``ARGS`` | ||||||
|  |    The values to be displayed, in format string order. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: debug | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
|  | 
 | ||||||
|  | Format string syntax | ||||||
|  | ~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | The format string syntax resembles Python f-strings.  Regular text is passed | ||||||
|  | through unchanged until a format specifier is reached, starting with a ``{``. | ||||||
|  | 
 | ||||||
|  | Format specifiers have the following syntax.  Unless noted, all items are | ||||||
|  | required: | ||||||
|  | 
 | ||||||
|  | ``{`` | ||||||
|  |    Denotes the start of the format specifier. | ||||||
|  | 
 | ||||||
|  | size | ||||||
|  |    Signal size in bits; this many bits are consumed from the ``ARGS`` port by | ||||||
|  |    this specifier. | ||||||
|  | 
 | ||||||
|  | ``:`` | ||||||
|  |    Separates the size from the remaining items. | ||||||
|  | 
 | ||||||
|  | justify | ||||||
|  |    ``>`` for right-justified, ``<`` for left-justified. | ||||||
|  | 
 | ||||||
|  | padding | ||||||
|  |    ``0`` for zero-padding, or a space for space-padding. | ||||||
|  | 
 | ||||||
|  | width\ *?* | ||||||
|  |    (optional) The number of characters wide to pad to. | ||||||
|  | 
 | ||||||
|  | base | ||||||
|  |    * ``b`` for base-2 integers (binary) | ||||||
|  |    * ``o`` for base-8 integers	(octal) | ||||||
|  |    * ``d`` for base-10 integers (decimal) | ||||||
|  |    * ``h`` for base-16	integers (hexadecimal) | ||||||
|  |    * ``c`` for ASCII characters/strings | ||||||
|  |    * ``t`` and ``r`` for simulation time (corresponding to :verilog:`$time` and | ||||||
|  |      :verilog:`$realtime`) | ||||||
|  | 
 | ||||||
|  | For integers, this item may follow: | ||||||
|  | 
 | ||||||
|  | ``+``\ *?* | ||||||
|  |    (optional, decimals only) Include a leading plus for non-negative numbers. | ||||||
|  |    This can assist with symmetry with negatives in tabulated output. | ||||||
|  | 
 | ||||||
|  | signedness | ||||||
|  |    ``u`` for unsigned, ``s`` for signed.  This distinction is only respected | ||||||
|  |    when rendering decimals. | ||||||
|  | 
 | ||||||
|  | ASCII characters/strings have no special options, but the signal size must be | ||||||
|  | divisible by 8. | ||||||
|  | 
 | ||||||
|  | For simulation time, the signal size must be zero. | ||||||
|  | 
 | ||||||
|  | Finally: | ||||||
|  | 
 | ||||||
|  | ``}`` | ||||||
|  |    Denotes the end of the format specifier. | ||||||
|  | 
 | ||||||
|  | Some example format specifiers: | ||||||
|  | 
 | ||||||
|  | + ``{8:>02hu}`` - 8-bit unsigned integer rendered as hexadecimal, | ||||||
|  |   right-justified, zero-padded to 2 characters wide. | ||||||
|  | + ``{32:< 15d+s}`` - 32-bit signed integer rendered as decimal, left-justified, | ||||||
|  |   space-padded to 15 characters wide, positive values prefixed with ``+``. | ||||||
|  | + ``{16:< 10hu}`` - 16-bit unsigned integer rendered as hexadecimal, | ||||||
|  |   left-justified, space-padded to 10 characters wide. | ||||||
|  | + ``{0:>010t}`` - simulation time, right-justified, zero-padded to 10 characters | ||||||
|  |   wide. | ||||||
|  | 
 | ||||||
|  | To include literal ``{`` and ``}`` characters in your format string, use ``{{`` | ||||||
|  | and ``}}`` respectively. | ||||||
|  | 
 | ||||||
|  | It is an error for a format string to consume more or less bits from ``ARGS`` | ||||||
|  | than the port width. | ||||||
|  | 
 | ||||||
|  | Values are never truncated, regardless of the specified width. | ||||||
|  | 
 | ||||||
|  | Note that further restrictions on allowable combinations of options may apply | ||||||
|  | depending on the backend used. | ||||||
|  | 
 | ||||||
|  | For example, Verilog does not have a format specifier that allows zero-padding a | ||||||
|  | string (i.e. more than 1 ASCII character), though zero-padding a single | ||||||
|  | character is permitted. | ||||||
|  | 
 | ||||||
|  | Thus, while the RTLIL format specifier ``{8:>02c}`` translates to ``%02c``, | ||||||
|  | ``{16:>02c}`` cannot be represented in Verilog and will fail to emit.  In this | ||||||
|  | case, ``{16:> 02c}`` must be used, which translates to ``%2s``. | ||||||
							
								
								
									
										31
									
								
								docs/source/cell/word_formal.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								docs/source/cell/word_formal.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | Formal verification cells | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  | .. role:: yoscrypt(code) | ||||||
|  |    :language: yoscrypt | ||||||
|  | 
 | ||||||
|  | .. note:: | ||||||
|  | 
 | ||||||
|  |    Some front-ends may not support the generic `$check` cell, in such cases | ||||||
|  |    calling :yoscrypt:`chformal -lower` will convert each `$check` cell into it's | ||||||
|  |    equivalent.  See `chformal` for more. | ||||||
|  | 
 | ||||||
|  | .. todo:: Describe formal cells | ||||||
|  | 
 | ||||||
|  |    `$check`, `$assert`, `$assume`, `$live`, `$fair`, `$cover`, `$equiv`, | ||||||
|  |    `$initstate`, `$anyconst`, `$anyseq`, `$anyinit`, `$allconst`, and `$allseq`. | ||||||
|  | 
 | ||||||
|  |    Also `$ff` and `$_FF_` cells. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: formal | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
|  | 
 | ||||||
|  | Formal support cells | ||||||
|  | ~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: formal_tag | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										9
									
								
								docs/source/cell/word_fsm.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docs/source/cell/word_fsm.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | Finite state machines | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  | .. todo:: Describe `$fsm` cell | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: fsm | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										46
									
								
								docs/source/cell/word_logic.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								docs/source/cell/word_logic.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | Arbitrary logic functions | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  | The `$lut` cell type implements a single-output LUT (lookup table). It | ||||||
|  | implements an arbitrary logic function with its ``\LUT`` parameter to map input | ||||||
|  | port ``\A`` to values of ``\Y`` output port values. In psuedocode: ``Y = | ||||||
|  | \LUT[A]``. ``\A`` has width set by parameter ``\WIDTH`` and ``\Y`` has a width | ||||||
|  | of 1. Every logic function with a single bit output has a unique `$lut` | ||||||
|  | representation. | ||||||
|  | 
 | ||||||
|  | The `$sop` cell type implements a sum-of-products expression, also known as | ||||||
|  | disjunctive normal form (DNF). It implements an arbitrary logic function. Its | ||||||
|  | structure mimics a programmable logic array (PLA). Output port ``\Y`` is the sum | ||||||
|  | of products of the bits of the input port ``\A`` as defined by parameter | ||||||
|  | ``\TABLE``. ``\A`` is ``\WIDTH`` bits wide. The number of products in the sum is | ||||||
|  | set by parameter ``\DEPTH``, and each product has two bits for each input bit - | ||||||
|  | for the presence of the unnegated and negated version of said input bit in the | ||||||
|  | product. Therefore the ``\TABLE`` parameter holds ``2 * \WIDTH * \DEPTH`` bits. | ||||||
|  | 
 | ||||||
|  | For example: | ||||||
|  | 
 | ||||||
|  | Let ``\WIDTH`` be 3. We would like to represent ``\Y =~\A[0] + \A[1]~\A[2]``. | ||||||
|  | There are 2 products to be summed, so ``\DEPTH`` shall be 2. | ||||||
|  | 
 | ||||||
|  | .. code-block:: | ||||||
|  | 
 | ||||||
|  |     ~A[2]-----+ | ||||||
|  |      A[2]----+| | ||||||
|  |     ~A[1]---+|| | ||||||
|  |      A[1]--+||| | ||||||
|  |     ~A[0]-+|||| | ||||||
|  |      A[0]+|||||  | ||||||
|  |          |||||| product formula | ||||||
|  |          010000 ~\A[0] | ||||||
|  |          001001 \A[1]~\A[2] | ||||||
|  | 
 | ||||||
|  | So the value of ``\TABLE`` will become ``010000001001``. | ||||||
|  | 
 | ||||||
|  | Any logic function with a single bit output can be represented with ``$sop`` but | ||||||
|  | may have variously minimized or ordered summands represented in the ``\TABLE`` | ||||||
|  | values. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: logic | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										281
									
								
								docs/source/cell/word_mem.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								docs/source/cell/word_mem.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,281 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | .. _sec:memcells: | ||||||
|  | 
 | ||||||
|  | Memories | ||||||
|  | ~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | Memories are either represented using ``RTLIL::Memory`` objects, `$memrd_v2`, | ||||||
|  | `$memwr_v2`, and `$meminit_v2` cells, or by `$mem_v2` cells alone. | ||||||
|  | 
 | ||||||
|  | In the first alternative the ``RTLIL::Memory`` objects hold the general metadata | ||||||
|  | for the memory (bit width, size in number of words, etc.) and for each port a | ||||||
|  | `$memrd_v2` (read port) or `$memwr_v2` (write port) cell is created. Having | ||||||
|  | individual cells for read and write ports has the advantage that they can be | ||||||
|  | consolidated using resource sharing passes. In some cases this drastically | ||||||
|  | reduces the number of required ports on the memory cell. In this alternative, | ||||||
|  | memory initialization data is represented by `$meminit_v2` cells, which allow | ||||||
|  | delaying constant folding for initialization addresses and data until after the | ||||||
|  | frontend finishes. | ||||||
|  | 
 | ||||||
|  | The `$memrd_v2` cells have a clock input ``CLK``, an enable input ``EN``, an | ||||||
|  | address input ``ADDR``, a data output ``DATA``, an asynchronous reset input | ||||||
|  | ``ARST``, and a synchronous reset input ``SRST``. They also have the following | ||||||
|  | parameters: | ||||||
|  | 
 | ||||||
|  | ``MEMID`` | ||||||
|  |    The name of the ``RTLIL::Memory`` object that is associated with this read | ||||||
|  |    port. | ||||||
|  | 
 | ||||||
|  | ``ABITS`` | ||||||
|  |    The number of address bits (width of the ``ADDR`` input port). | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The number of data bits (width of the ``DATA`` output port).  Note that this | ||||||
|  |    may be a power-of-two multiple of the underlying memory's width -- such ports | ||||||
|  |    are called wide ports and access an aligned group of cells at once.  In this | ||||||
|  |    case, the corresponding low bits of ``ADDR`` must be tied to 0. | ||||||
|  | 
 | ||||||
|  | ``CLK_ENABLE`` | ||||||
|  |    When this parameter is non-zero, the clock is used. Otherwise this read port | ||||||
|  |    is asynchronous and the ``CLK`` input is not used. | ||||||
|  | 
 | ||||||
|  | ``CLK_POLARITY`` | ||||||
|  |    Clock is active on the positive edge if this parameter has the value ``1'b1`` | ||||||
|  |    and on the negative edge if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``TRANSPARENCY_MASK`` | ||||||
|  |    This parameter is a bitmask of write ports that this read port is transparent | ||||||
|  |    with. The bits of this parameter are indexed by the write port's ``PORTID`` | ||||||
|  |    parameter. Transparency can only be enabled between synchronous ports sharing | ||||||
|  |    a clock domain. When transparency is enabled for a given port pair, a read | ||||||
|  |    and write to the same address in the same cycle will return the new value. | ||||||
|  |    Otherwise the old value is returned. | ||||||
|  | 
 | ||||||
|  | ``COLLISION_X_MASK`` | ||||||
|  |    This parameter is a bitmask of write ports that have undefined collision | ||||||
|  |    behavior with this port. The bits of this parameter are indexed by the write | ||||||
|  |    port's ``PORTID`` parameter. This behavior can only be enabled between | ||||||
|  |    synchronous ports sharing a clock domain. When undefined collision is enabled | ||||||
|  |    for a given port pair, a read and write to the same address in the same cycle | ||||||
|  |    will return the undefined (all-X) value.This option is exclusive (for a given | ||||||
|  |    port pair) with the transparency option. | ||||||
|  | 
 | ||||||
|  | ``ARST_VALUE`` | ||||||
|  |    Whenever the ``ARST`` input is asserted, the data output will be reset to | ||||||
|  |    this value. Only used for synchronous ports. | ||||||
|  | 
 | ||||||
|  | ``SRST_VALUE`` | ||||||
|  |    Whenever the ``SRST`` input is synchronously asserted, the data output will | ||||||
|  |    be reset to this value. Only used for synchronous ports. | ||||||
|  | 
 | ||||||
|  | ``INIT_VALUE`` | ||||||
|  |    The initial value of the data output, for synchronous ports. | ||||||
|  | 
 | ||||||
|  | ``CE_OVER_SRST`` | ||||||
|  |    If this parameter is non-zero, the ``SRST`` input is only recognized when | ||||||
|  |    ``EN`` is true. Otherwise, ``SRST`` is recognized regardless of ``EN``. | ||||||
|  | 
 | ||||||
|  | The `$memwr_v2` cells have a clock input ``CLK``, an enable input ``EN`` (one | ||||||
|  | enable bit for each data bit), an address input ``ADDR`` and a data input | ||||||
|  | ``DATA``. They also have the following parameters: | ||||||
|  | 
 | ||||||
|  | ``MEMID`` | ||||||
|  |    The name of the ``RTLIL::Memory`` object that is associated with this write | ||||||
|  |    port. | ||||||
|  | 
 | ||||||
|  | ``ABITS`` | ||||||
|  |    The number of address bits (width of the ``ADDR`` input port). | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The number of data bits (width of the ``DATA`` output port). Like with | ||||||
|  |    `$memrd_v2` cells, the width is allowed to be any power-of-two multiple of | ||||||
|  |    memory width, with the corresponding restriction on address. | ||||||
|  | 
 | ||||||
|  | ``CLK_ENABLE`` | ||||||
|  |    When this parameter is non-zero, the clock is used. Otherwise this write port | ||||||
|  |    is asynchronous and the ``CLK`` input is not used. | ||||||
|  | 
 | ||||||
|  | ``CLK_POLARITY`` | ||||||
|  |    Clock is active on positive edge if this parameter has the value ``1'b1`` and | ||||||
|  |    on the negative edge if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``PORTID`` | ||||||
|  |    An identifier for this write port, used to index write port bit mask | ||||||
|  |    parameters. | ||||||
|  | 
 | ||||||
|  | ``PRIORITY_MASK`` | ||||||
|  |    This parameter is a bitmask of write ports that this write port has priority | ||||||
|  |    over in case of writing to the same address.  The bits of this parameter are | ||||||
|  |    indexed by the other write port's ``PORTID`` parameter. Write ports can only | ||||||
|  |    have priority over write ports with lower port ID. When two ports write to | ||||||
|  |    the same address and neither has priority over the other, the result is | ||||||
|  |    undefined.  Priority can only be set between two synchronous ports sharing | ||||||
|  |    the same clock domain. | ||||||
|  | 
 | ||||||
|  | The `$meminit_v2` cells have an address input ``ADDR``, a data input ``DATA``, | ||||||
|  | with the width of the ``DATA`` port equal to ``WIDTH`` parameter times ``WORDS`` | ||||||
|  | parameter, and a bit enable mask input ``EN`` with width equal to ``WIDTH`` | ||||||
|  | parameter. All three of the inputs must resolve to a constant for synthesis to | ||||||
|  | succeed. | ||||||
|  | 
 | ||||||
|  | ``MEMID`` | ||||||
|  |    The name of the ``RTLIL::Memory`` object that is associated with this | ||||||
|  |    initialization cell. | ||||||
|  | 
 | ||||||
|  | ``ABITS`` | ||||||
|  |    The number of address bits (width of the ``ADDR`` input port). | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The number of data bits per memory location. | ||||||
|  | 
 | ||||||
|  | ``WORDS`` | ||||||
|  |    The number of consecutive memory locations initialized by this cell. | ||||||
|  | 
 | ||||||
|  | ``PRIORITY`` | ||||||
|  |    The cell with the higher integer value in this parameter wins an | ||||||
|  |    initialization conflict. | ||||||
|  | 
 | ||||||
|  | The HDL frontend models a memory using ``RTLIL::Memory`` objects and | ||||||
|  | asynchronous `$memrd_v2` and `$memwr_v2` cells. The `memory` pass (i.e. its | ||||||
|  | various sub-passes) migrates `$dff` cells into the `$memrd_v2` and `$memwr_v2` | ||||||
|  | cells making them synchronous, then converts them to a single `$mem_v2` cell and | ||||||
|  | (optionally) maps this cell type to `$dff` cells for the individual words and | ||||||
|  | multiplexer-based address decoders for the read and write interfaces. When the | ||||||
|  | last step is disabled or not possible, a `$mem_v2` cell is left in the design. | ||||||
|  | 
 | ||||||
|  | The `$mem_v2` cell provides the following parameters: | ||||||
|  | 
 | ||||||
|  | ``MEMID`` | ||||||
|  |    The name of the original ``RTLIL::Memory`` object that became this `$mem_v2` | ||||||
|  |    cell. | ||||||
|  | 
 | ||||||
|  | ``SIZE`` | ||||||
|  |    The number of words in the memory. | ||||||
|  | 
 | ||||||
|  | ``ABITS`` | ||||||
|  |    The number of address bits. | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The number of data bits per word. | ||||||
|  | 
 | ||||||
|  | ``INIT`` | ||||||
|  |    The initial memory contents. | ||||||
|  | 
 | ||||||
|  | ``RD_PORTS`` | ||||||
|  |    The number of read ports on this memory cell. | ||||||
|  | 
 | ||||||
|  | ``RD_WIDE_CONTINUATION`` | ||||||
|  |    This parameter is ``RD_PORTS`` bits wide, containing a bitmask of "wide | ||||||
|  |    continuation" read ports. Such ports are used to represent the extra data | ||||||
|  |    bits of wide ports in the combined cell, and must have all control signals | ||||||
|  |    identical with the preceding port, except for address, which must have the | ||||||
|  |    proper sub-cell address encoded in the low bits. | ||||||
|  | 
 | ||||||
|  | ``RD_CLK_ENABLE`` | ||||||
|  |    This parameter is ``RD_PORTS`` bits wide, containing a clock enable bit for | ||||||
|  |    each read port. | ||||||
|  | 
 | ||||||
|  | ``RD_CLK_POLARITY`` | ||||||
|  |    This parameter is ``RD_PORTS`` bits wide, containing a clock polarity bit for | ||||||
|  |    each read port. | ||||||
|  | 
 | ||||||
|  | ``RD_TRANSPARENCY_MASK`` | ||||||
|  |    This parameter is ``RD_PORTS*WR_PORTS`` bits wide, containing a concatenation | ||||||
|  |    of all ``TRANSPARENCY_MASK`` values of the original `$memrd_v2` cells. | ||||||
|  | 
 | ||||||
|  | ``RD_COLLISION_X_MASK`` | ||||||
|  |    This parameter is ``RD_PORTS*WR_PORTS`` bits wide, containing a concatenation | ||||||
|  |    of all ``COLLISION_X_MASK`` values of the original `$memrd_v2` cells. | ||||||
|  | 
 | ||||||
|  | ``RD_CE_OVER_SRST`` | ||||||
|  |    This parameter is ``RD_PORTS`` bits wide, determining relative synchronous | ||||||
|  |    reset and enable priority for each read port. | ||||||
|  | 
 | ||||||
|  | ``RD_INIT_VALUE`` | ||||||
|  |    This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the initial value | ||||||
|  |    for each synchronous read port. | ||||||
|  | 
 | ||||||
|  | ``RD_ARST_VALUE`` | ||||||
|  |    This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the asynchronous | ||||||
|  |    reset value for each synchronous read port. | ||||||
|  | 
 | ||||||
|  | ``RD_SRST_VALUE`` | ||||||
|  |    This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the synchronous | ||||||
|  |    reset value for each synchronous read port. | ||||||
|  | 
 | ||||||
|  | ``WR_PORTS`` | ||||||
|  |    The number of write ports on this memory cell. | ||||||
|  | 
 | ||||||
|  | ``WR_WIDE_CONTINUATION`` | ||||||
|  |    This parameter is ``WR_PORTS`` bits wide, containing a bitmask of "wide | ||||||
|  |    continuation" write ports. | ||||||
|  | 
 | ||||||
|  | ``WR_CLK_ENABLE`` | ||||||
|  |    This parameter is ``WR_PORTS`` bits wide, containing a clock enable bit for | ||||||
|  |    each write port. | ||||||
|  | 
 | ||||||
|  | ``WR_CLK_POLARITY`` | ||||||
|  |    This parameter is ``WR_PORTS`` bits wide, containing a clock polarity bit for | ||||||
|  |    each write port. | ||||||
|  | 
 | ||||||
|  | ``WR_PRIORITY_MASK`` | ||||||
|  |    This parameter is ``WR_PORTS*WR_PORTS`` bits wide, containing a concatenation | ||||||
|  |    of all ``PRIORITY_MASK`` values of the original `$memwr_v2` cells. | ||||||
|  | 
 | ||||||
|  | The `$mem_v2` cell has the following ports: | ||||||
|  | 
 | ||||||
|  | ``RD_CLK`` | ||||||
|  |    This input is ``RD_PORTS`` bits wide, containing all clock signals for the | ||||||
|  |    read ports. | ||||||
|  | 
 | ||||||
|  | ``RD_EN`` | ||||||
|  |    This input is ``RD_PORTS`` bits wide, containing all enable signals for the | ||||||
|  |    read ports. | ||||||
|  | 
 | ||||||
|  | ``RD_ADDR`` | ||||||
|  |    This input is ``RD_PORTS*ABITS`` bits wide, containing all address signals | ||||||
|  |    for the read ports. | ||||||
|  | 
 | ||||||
|  | ``RD_DATA`` | ||||||
|  |    This output is ``RD_PORTS*WIDTH`` bits wide, containing all data signals for | ||||||
|  |    the read ports. | ||||||
|  | 
 | ||||||
|  | ``RD_ARST`` | ||||||
|  |    This input is ``RD_PORTS`` bits wide, containing all asynchronous reset | ||||||
|  |    signals for the read ports. | ||||||
|  | 
 | ||||||
|  | ``RD_SRST`` | ||||||
|  |    This input is ``RD_PORTS`` bits wide, containing all synchronous reset | ||||||
|  |    signals for the read ports. | ||||||
|  | 
 | ||||||
|  | ``WR_CLK`` | ||||||
|  |    This input is ``WR_PORTS`` bits wide, containing all clock signals for the | ||||||
|  |    write ports. | ||||||
|  | 
 | ||||||
|  | ``WR_EN`` | ||||||
|  |    This input is ``WR_PORTS*WIDTH`` bits wide, containing all enable signals for | ||||||
|  |    the write ports. | ||||||
|  | 
 | ||||||
|  | ``WR_ADDR`` | ||||||
|  |    This input is ``WR_PORTS*ABITS`` bits wide, containing all address signals | ||||||
|  |    for the write ports. | ||||||
|  | 
 | ||||||
|  | ``WR_DATA`` | ||||||
|  |    This input is ``WR_PORTS*WIDTH`` bits wide, containing all data signals for | ||||||
|  |    the write ports. | ||||||
|  | 
 | ||||||
|  | The `memory_collect` pass can be used to convert discrete `$memrd_v2`, | ||||||
|  | `$memwr_v2`, and `$meminit_v2` cells belonging to the same memory to a single | ||||||
|  | `$mem_v2` cell, whereas the `memory_unpack` pass performs the inverse operation. | ||||||
|  | The `memory_dff` pass can combine asynchronous memory ports that are fed by or | ||||||
|  | feeding registers into synchronous memory ports. The `memory_bram` pass can be | ||||||
|  | used to recognize `$mem_v2` cells that can be implemented with a block RAM | ||||||
|  | resource on an FPGA. The `memory_map` pass can be used to implement `$mem_v2` | ||||||
|  | cells as basic logic: word-wide DFFs and address decoders. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: mem | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										47
									
								
								docs/source/cell/word_mux.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								docs/source/cell/word_mux.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Multiplexers | ||||||
|  | ------------ | ||||||
|  | 
 | ||||||
|  | Multiplexers are generated by the Verilog HDL frontend for ``?:``-expressions. | ||||||
|  | Multiplexers are also generated by the proc pass to map the decision trees from | ||||||
|  | RTLIL::Process objects to logic. | ||||||
|  | 
 | ||||||
|  | The simplest multiplexer cell type is `$mux`. Cells of this type have a | ||||||
|  | ``WITDH`` parameter and data inputs ``A`` and ``B`` and a data output ``Y``, all | ||||||
|  | of the specified width. This cell also has a single bit control input ``S``. If | ||||||
|  | ``S`` is 0 the value from the input ``A`` is sent to the output, if it is 1 the | ||||||
|  | value from the ``B`` input is sent to the output. So the `$mux` cell implements | ||||||
|  | the function :verilog:`Y = S ? B : A`. | ||||||
|  | 
 | ||||||
|  | The `$pmux` cell is used to multiplex between many inputs using a one-hot select | ||||||
|  | signal. Cells of this type have a ``WIDTH`` and a ``S_WIDTH`` parameter and | ||||||
|  | inputs ``A``, ``B``, and ``S`` and an output ``Y``. The ``S`` input is | ||||||
|  | ``S_WIDTH`` bits wide. The ``A`` input and the output are both ``WIDTH`` bits | ||||||
|  | wide and the ``B`` input is ``WIDTH*S_WIDTH`` bits wide. When all bits of ``S`` | ||||||
|  | are zero, the value from ``A`` input is sent to the output. If the :math:`n`\ | ||||||
|  | 'th bit from ``S`` is set, the value :math:`n`\ 'th ``WIDTH`` bits wide slice of | ||||||
|  | the ``B`` input is sent to the output. When more than one bit from ``S`` is set | ||||||
|  | the output is undefined. Cells of this type are used to model "parallel cases" | ||||||
|  | (defined by using the ``parallel_case`` attribute or detected by an | ||||||
|  | optimization). | ||||||
|  | 
 | ||||||
|  | The `$tribuf` cell is used to implement tristate logic. Cells of this type have | ||||||
|  | a ``WIDTH`` parameter and inputs ``A`` and ``EN`` and an output ``Y``. The ``A`` | ||||||
|  | input and ``Y`` output are ``WIDTH`` bits wide, and the ``EN`` input is one bit | ||||||
|  | wide. When ``EN`` is 0, the output is not driven. When ``EN`` is 1, the value | ||||||
|  | from ``A`` input is sent to the ``Y`` output. Therefore, the `$tribuf` cell | ||||||
|  | implements the function :verilog:`Y = EN ? A : 'bz`. | ||||||
|  | 
 | ||||||
|  | Behavioural code with cascaded if-then-else- and case-statements usually results | ||||||
|  | in trees of multiplexer cells. Many passes (from various optimizations to FSM | ||||||
|  | extraction) heavily depend on these multiplexer trees to understand dependencies | ||||||
|  | between signals. Therefore optimizations should not break these multiplexer | ||||||
|  | trees (e.g. by replacing a multiplexer between a calculated signal and a | ||||||
|  | constant zero with an `$and` gate). | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: mux | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										124
									
								
								docs/source/cell/word_reg.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								docs/source/cell/word_reg.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,124 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Registers | ||||||
|  | --------- | ||||||
|  | 
 | ||||||
|  | SR-type latches are represented by `$sr` cells. These cells have input ports | ||||||
|  | ``SET`` and ``CLR`` and an output port ``Q``. They have the following | ||||||
|  | parameters: | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The width of inputs ``SET`` and ``CLR`` and output ``Q``. | ||||||
|  | 
 | ||||||
|  | ``SET_POLARITY`` | ||||||
|  |    The set input bits are active-high if this parameter has the value ``1'b1`` | ||||||
|  |    and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``CLR_POLARITY`` | ||||||
|  |    The reset input bits are active-high if this parameter has the value ``1'b1`` | ||||||
|  |    and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | Both set and reset inputs have separate bits for every output bit. When both the | ||||||
|  | set and reset inputs of an `$sr` cell are active for a given bit index, the | ||||||
|  | reset input takes precedence. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops are represented by `$dff` cells. These cells have a clock port | ||||||
|  | ``CLK``, an input port ``D`` and an output port ``Q``. The following parameters | ||||||
|  | are available for `$dff` cells: | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The width of input ``D`` and output ``Q``. | ||||||
|  | 
 | ||||||
|  | ``CLK_POLARITY`` | ||||||
|  |    Clock is active on the positive edge if this parameter has the value ``1'b1`` | ||||||
|  |    and on the negative edge if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops with asynchronous reset are represented by `$adff` cells. As | ||||||
|  | the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also | ||||||
|  | have a single-bit ``ARST`` input port for the reset pin and the following | ||||||
|  | additional two parameters: | ||||||
|  | 
 | ||||||
|  | ``ARST_POLARITY`` | ||||||
|  |    The asynchronous reset is active-high if this parameter has the value | ||||||
|  |    ``1'b1`` and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``ARST_VALUE`` | ||||||
|  |       The state of ``Q`` will be set to this value when the reset is active. | ||||||
|  | 
 | ||||||
|  | Usually these cells are generated by the `proc` pass using the information in | ||||||
|  | the designs RTLIL::Process objects. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops with synchronous reset are represented by `$sdff` cells. As | ||||||
|  | the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also | ||||||
|  | have a single-bit ``SRST`` input port for the reset pin and the following | ||||||
|  | additional two parameters: | ||||||
|  | 
 | ||||||
|  | ``SRST_POLARITY`` | ||||||
|  |    The synchronous reset is active-high if this parameter has the value ``1'b1`` | ||||||
|  |    and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``SRST_VALUE`` | ||||||
|  |    The state of ``Q`` will be set to this value when the reset is active. | ||||||
|  | 
 | ||||||
|  | Note that the `$adff` and `$sdff` cells can only be used when the reset value is | ||||||
|  | constant. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops with asynchronous load are represented by `$aldff` cells. As | ||||||
|  | the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also | ||||||
|  | have a single-bit ``ALOAD`` input port for the async load enable pin, a ``AD`` | ||||||
|  | input port with the same width as data for the async load data, and the | ||||||
|  | following additional parameter: | ||||||
|  | 
 | ||||||
|  | ``ALOAD_POLARITY`` | ||||||
|  |    The asynchronous load is active-high if this parameter has the value ``1'b1`` | ||||||
|  |    and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops with asynchronous set and reset are represented by `$dffsr` | ||||||
|  | cells. As the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition | ||||||
|  | they also have multi-bit ``SET`` and ``CLR`` input ports and the corresponding | ||||||
|  | polarity parameters, like `$sr` cells. | ||||||
|  | 
 | ||||||
|  | D-type flip-flops with enable are represented by `$dffe`, `$adffe`, `$aldffe`, | ||||||
|  | `$dffsre`, `$sdffe`, and `$sdffce` cells, which are enhanced variants of `$dff`, | ||||||
|  | `$adff`, `$aldff`, `$dffsr`, `$sdff` (with reset over enable) and `$sdff` (with | ||||||
|  | enable over reset) cells, respectively.  They have the same ports and parameters | ||||||
|  | as their base cell. In addition they also have a single-bit ``EN`` input port | ||||||
|  | for the enable pin and the following parameter: | ||||||
|  | 
 | ||||||
|  | ``EN_POLARITY`` | ||||||
|  |    The enable input is active-high if this parameter has the value ``1'b1`` and | ||||||
|  |    active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | D-type latches are represented by `$dlatch` cells.  These cells have an enable | ||||||
|  | port ``EN``, an input port ``D``, and an output port ``Q``.  The following | ||||||
|  | parameters are available for `$dlatch` cells: | ||||||
|  | 
 | ||||||
|  | ``WIDTH`` | ||||||
|  |    The width of input ``D`` and output ``Q``. | ||||||
|  | 
 | ||||||
|  | ``EN_POLARITY`` | ||||||
|  |    The enable input is active-high if this parameter has the value ``1'b1`` and | ||||||
|  |    active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | The latch is transparent when the ``EN`` input is active. | ||||||
|  | 
 | ||||||
|  | D-type latches with reset are represented by `$adlatch` cells.  In addition to | ||||||
|  | `$dlatch` ports and parameters, they also have a single-bit ``ARST`` input port | ||||||
|  | for the reset pin and the following additional parameters: | ||||||
|  | 
 | ||||||
|  | ``ARST_POLARITY`` | ||||||
|  |    The asynchronous reset is active-high if this parameter has the value | ||||||
|  |    ``1'b1`` and active-low if this parameter is ``1'b0``. | ||||||
|  | 
 | ||||||
|  | ``ARST_VALUE`` | ||||||
|  |    The state of ``Q`` will be set to this value when the reset is active. | ||||||
|  | 
 | ||||||
|  | D-type latches with set and reset are represented by `$dlatchsr` cells. In | ||||||
|  | addition to `$dlatch` ports and parameters, they also have multi-bit ``SET`` and | ||||||
|  | ``CLR`` input ports and the corresponding polarity parameters, like `$sr` cells. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: reg | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										9
									
								
								docs/source/cell/word_spec.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docs/source/cell/word_spec.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | Specify rules | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | .. todo:: `$specify2`, `$specify3`, and `$specrule` cells. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: spec | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										50
									
								
								docs/source/cell/word_unary.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								docs/source/cell/word_unary.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | .. role:: verilog(code) | ||||||
|  |    :language: Verilog | ||||||
|  | 
 | ||||||
|  | Unary operators | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | All unary RTL cells have one input port ``A`` and one output port ``Y``. They | ||||||
|  | also have the following parameters: | ||||||
|  | 
 | ||||||
|  | ``A_SIGNED`` | ||||||
|  |    Set to a non-zero value if the input ``A`` is signed and therefore should be | ||||||
|  |    sign-extended when needed. | ||||||
|  | 
 | ||||||
|  | ``A_WIDTH`` | ||||||
|  |    The width of the input port ``A``. | ||||||
|  | 
 | ||||||
|  | ``Y_WIDTH`` | ||||||
|  |    The width of the output port ``Y``. | ||||||
|  | 
 | ||||||
|  | .. table:: Cell types for unary operators with their corresponding Verilog expressions. | ||||||
|  | 
 | ||||||
|  |    ================== ============== | ||||||
|  |    Verilog            Cell Type | ||||||
|  |    ================== ============== | ||||||
|  |    :verilog:`Y =  ~A` `$not` | ||||||
|  |    :verilog:`Y =  +A` `$pos` | ||||||
|  |    :verilog:`Y =  -A` `$neg` | ||||||
|  |    :verilog:`Y =  &A` `$reduce_and` | ||||||
|  |    :verilog:`Y =  |A` `$reduce_or` | ||||||
|  |    :verilog:`Y =  ^A` `$reduce_xor` | ||||||
|  |    :verilog:`Y = ~^A` `$reduce_xnor` | ||||||
|  |    :verilog:`Y =  |A` `$reduce_bool` | ||||||
|  |    :verilog:`Y =  !A` `$logic_not` | ||||||
|  |    ================== ============== | ||||||
|  | 
 | ||||||
|  | For the unary cells that output a logical value (`$reduce_and`, `$reduce_or`, | ||||||
|  | `$reduce_xor`, `$reduce_xnor`, `$reduce_bool`, `$logic_not`), when the | ||||||
|  | ``Y_WIDTH`` parameter is greater than 1, the output is zero-extended, and only | ||||||
|  | the least significant bit varies. | ||||||
|  | 
 | ||||||
|  | Note that `$reduce_or` and `$reduce_bool` generally represent the same logic | ||||||
|  | function. But the `read_verilog` frontend will generate them in different | ||||||
|  | situations. A `$reduce_or` cell is generated when the prefix ``|`` operator is | ||||||
|  | being used. A `$reduce_bool` cell is generated when a bit vector is used as a | ||||||
|  | condition in an ``if``-statement or ``?:``-expression. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: unary | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										9
									
								
								docs/source/cell/word_wire.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docs/source/cell/word_wire.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | Wire cells | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  | .. todo:: Add information about `$slice` and `$concat` cells. | ||||||
|  | 
 | ||||||
|  | .. autocellgroup:: wire | ||||||
|  |    :members: | ||||||
|  |    :source: | ||||||
|  |    :linenos: | ||||||
							
								
								
									
										15
									
								
								docs/source/cell_index.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docs/source/cell_index.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | Internal cell library | ||||||
|  | ===================== | ||||||
|  | 
 | ||||||
|  | The intermediate language used by Yosys (RTLIL) represents logic and memory with | ||||||
|  | a series of cells. This section provides details for those cells, breaking them | ||||||
|  | down into two major categories: coarse-grain word-level cells; and fine-grain | ||||||
|  | gate-level cells. An additional section contains a list of properties which may | ||||||
|  | be shared across multiple cells. | ||||||
|  | 
 | ||||||
|  | .. toctree:: | ||||||
|  |    :maxdepth: 2 | ||||||
|  | 
 | ||||||
|  |    /cell/index_word | ||||||
|  |    /cell/index_gate | ||||||
|  |    /cell/properties | ||||||
|  | @ -4,8 +4,8 @@ YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys | ||||||
| 
 | 
 | ||||||
| .PHONY: all dots examples | .PHONY: all dots examples | ||||||
| all: dots examples | all: dots examples | ||||||
| dots: test1.dot | dots: test1.dot my_cmd.so | ||||||
| examples: test0.log test1.log test2.log | examples: test0.log test1.log test2.log my_cmd.so | ||||||
| 
 | 
 | ||||||
| CXXFLAGS=$(shell $(YOSYS)-config --cxxflags) | CXXFLAGS=$(shell $(YOSYS)-config --cxxflags) | ||||||
| DATDIR=$(shell $(YOSYS)-config --datdir) | DATDIR=$(shell $(YOSYS)-config --datdir) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								docs/source/code_examples/fifo/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								docs/source/code_examples/fifo/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | *.out | ||||||
|  | *.stat | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
|  | from pathlib import Path | ||||||
| import sys | import sys | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
|  | @ -8,39 +9,18 @@ copyright ='2024 YosysHQ GmbH' | ||||||
| yosys_ver = "0.46" | yosys_ver = "0.46" | ||||||
| 
 | 
 | ||||||
| # select HTML theme | # select HTML theme | ||||||
| html_theme = 'furo' | html_theme = 'furo-ys' | ||||||
| templates_path = ["_templates"] | html_css_files = ['custom.css'] | ||||||
| html_logo = '_static/logo.png' |  | ||||||
| html_favicon = '_static/favico.png' |  | ||||||
| html_css_files = ['yosyshq.css', 'custom.css'] |  | ||||||
| 
 |  | ||||||
| html_theme_options = { |  | ||||||
|     "sidebar_hide_name": True, |  | ||||||
| 
 |  | ||||||
|     "light_css_variables": { |  | ||||||
|         "color-brand-primary": "#d6368f", |  | ||||||
|         "color-brand-content": "#4b72b8", |  | ||||||
|         "color-api-name": "#8857a3", |  | ||||||
|         "color-api-pre-name": "#4b72b8", |  | ||||||
|         "color-link": "#8857a3", |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     "dark_css_variables": { |  | ||||||
|         "color-brand-primary": "#e488bb", |  | ||||||
|         "color-brand-content": "#98bdff", |  | ||||||
|         "color-api-name": "#8857a3", |  | ||||||
|         "color-api-pre-name": "#4b72b8", |  | ||||||
|         "color-link": "#be95d5", |  | ||||||
|     }, |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| # These folders are copied to the documentation's HTML output | # These folders are copied to the documentation's HTML output | ||||||
| html_static_path = ['_static', "_images"] | html_static_path = ['_static', "_images"] | ||||||
| 
 | 
 | ||||||
| # code blocks style  | # default to no highlight | ||||||
| pygments_style = 'colorful' |  | ||||||
| highlight_language = 'none' | highlight_language = 'none' | ||||||
| 
 | 
 | ||||||
|  | # default single quotes to attempt auto reference, or fallback to code | ||||||
|  | default_role = 'autoref' | ||||||
|  | 
 | ||||||
| extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex'] | extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex'] | ||||||
| 
 | 
 | ||||||
| if os.getenv("READTHEDOCS"): | if os.getenv("READTHEDOCS"): | ||||||
|  | @ -97,9 +77,15 @@ latex_elements = { | ||||||
| sys.path += [os.path.dirname(__file__) + "/../"] | sys.path += [os.path.dirname(__file__) + "/../"] | ||||||
| extensions.append('util.cmdref') | extensions.append('util.cmdref') | ||||||
| 
 | 
 | ||||||
| def setup(sphinx): | # use autodocs | ||||||
| 	from util.RtlilLexer import RtlilLexer | extensions.append('sphinx.ext.autodoc') | ||||||
| 	sphinx.add_lexer("RTLIL", RtlilLexer) | extensions.append('util.cellref') | ||||||
|  | cells_json = Path(__file__).parent / 'generated' / 'cells.json' | ||||||
| 
 | 
 | ||||||
| 	from util.YoscryptLexer import YoscryptLexer | from sphinx.application import Sphinx | ||||||
| 	sphinx.add_lexer("yoscrypt", YoscryptLexer) | def setup(app: Sphinx) -> None: | ||||||
|  |     from util.RtlilLexer import RtlilLexer | ||||||
|  |     app.add_lexer("RTLIL", RtlilLexer) | ||||||
|  | 
 | ||||||
|  |     from furo_ys.lexers.YoscryptLexer import YoscryptLexer | ||||||
|  |     app.add_lexer("yoscrypt", YoscryptLexer) | ||||||
|  |  | ||||||
|  | @ -2,13 +2,12 @@ Synthesis starter | ||||||
| ----------------- | ----------------- | ||||||
| 
 | 
 | ||||||
| This page will be a guided walkthrough of the prepackaged iCE40 FPGA synthesis | This page will be a guided walkthrough of the prepackaged iCE40 FPGA synthesis | ||||||
| script - :cmd:ref:`synth_ice40`.  We will take a simple design through each | script - `synth_ice40`.  We will take a simple design through each step, looking | ||||||
| step, looking at the commands being called and what they do to the design. While | at the commands being called and what they do to the design. While `synth_ice40` | ||||||
| :cmd:ref:`synth_ice40` is specific to the iCE40 platform, most of the operations | is specific to the iCE40 platform, most of the operations we will be discussing | ||||||
| we will be discussing are common across the majority of FPGA synthesis scripts. | are common across the majority of FPGA synthesis scripts. Thus, this document | ||||||
| Thus, this document will provide a good foundational understanding of how | will provide a good foundational understanding of how synthesis in Yosys is | ||||||
| synthesis in Yosys is performed, regardless of the actual architecture being | performed, regardless of the actual architecture being used. | ||||||
| used. |  | ||||||
| 
 | 
 | ||||||
| .. seealso:: Advanced usage docs for | .. seealso:: Advanced usage docs for | ||||||
|    :doc:`/using_yosys/synthesis/synth` |    :doc:`/using_yosys/synthesis/synth` | ||||||
|  | @ -59,8 +58,8 @@ can run each of the commands individually for a better sense of how each part | ||||||
| contributes to the flow.  We will also start with just a single module; | contributes to the flow.  We will also start with just a single module; | ||||||
| ``addr_gen``. | ``addr_gen``. | ||||||
| 
 | 
 | ||||||
| At the bottom of the :cmd:ref:`help` output for | At the bottom of the `help` output for | ||||||
| :cmd:ref:`synth_ice40` is the complete list of commands called by this script. | `synth_ice40` is the complete list of commands called by this script. | ||||||
| Let's start with the section labeled ``begin``: | Let's start with the section labeled ``begin``: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|  | @ -105,10 +104,10 @@ Since we're just getting started, let's instead begin with :yoscrypt:`hierarchy | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    :cmd:ref:`hierarchy` should always be the first command after the design has |    `hierarchy` should always be the first command after the design has been | ||||||
|    been read.  By specifying the top module, :cmd:ref:`hierarchy` will also set |    read.  By specifying the top module, `hierarchy` will also set the ``(* top | ||||||
|    the ``(* top *)`` attribute on it.  This is used by other commands that need |    *)`` attribute on it.  This is used by other commands that need to know which | ||||||
|    to know which module is the top. |    module is the top. | ||||||
| 
 | 
 | ||||||
| .. use doscon for a console-like display that supports the `yosys> [command]` format. | .. use doscon for a console-like display that supports the `yosys> [command]` format. | ||||||
| 
 | 
 | ||||||
|  | @ -125,24 +124,24 @@ Our ``addr_gen`` circuit now looks like this: | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: addr_gen_hier |    :name: addr_gen_hier | ||||||
| 
 | 
 | ||||||
|    ``addr_gen`` module after :cmd:ref:`hierarchy` |    ``addr_gen`` module after `hierarchy` | ||||||
| 
 | 
 | ||||||
| Simple operations like ``addr + 1`` and ``addr == MAX_DATA-1`` can be extracted | Simple operations like ``addr + 1`` and ``addr == MAX_DATA-1`` can be extracted | ||||||
| from our ``always @`` block in :ref:`addr_gen-v`. This gives us the highlighted | from our ``always @`` block in :ref:`addr_gen-v`. This gives us the highlighted | ||||||
| ``$add`` and ``$eq`` cells we see. But control logic (like the ``if .. else``) | `$add` and `$eq` cells we see. But control logic (like the ``if .. else``) and | ||||||
| and memory elements (like the ``addr <= 0``) are not so straightforward.  These | memory elements (like the ``addr <= 0``) are not so straightforward.  These get | ||||||
| get put into "processes", shown in the schematic as ``PROC``.  Note how the | put into "processes", shown in the schematic as ``PROC``.  Note how the second | ||||||
| second line refers to the line numbers of the start/end of the corresponding | line refers to the line numbers of the start/end of the corresponding ``always | ||||||
| ``always @`` block.  In the case of an ``initial`` block, we instead see the | @`` block.  In the case of an ``initial`` block, we instead see the ``PROC`` | ||||||
| ``PROC`` referring to line 0. | referring to line 0. | ||||||
| 
 | 
 | ||||||
| To handle these, let us now introduce the next command: :doc:`/cmd/proc`. | To handle these, let us now introduce the next command: :doc:`/cmd/proc`. `proc` | ||||||
| :cmd:ref:`proc` is a macro command like :cmd:ref:`synth_ice40`.  Rather than | is a macro command like `synth_ice40`.  Rather than modifying the design | ||||||
| modifying the design directly, it instead calls a series of other commands.  In | directly, it instead calls a series of other commands.  In the case of `proc`, | ||||||
| the case of :cmd:ref:`proc`, these sub-commands work to convert the behavioral | these sub-commands work to convert the behavioral logic of processes into | ||||||
| logic of processes into multiplexers and registers.  Let's see what happens when | multiplexers and registers.  Let's see what happens when we run it.  For now, we | ||||||
| we run it.  For now, we will call :yoscrypt:`proc -noopt` to prevent some | will call :yoscrypt:`proc -noopt` to prevent some automatic optimizations which | ||||||
| automatic optimizations which would normally happen. | would normally happen. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/addr_gen_proc.* | .. figure:: /_images/code_examples/fifo/addr_gen_proc.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|  | @ -151,19 +150,18 @@ automatic optimizations which would normally happen. | ||||||
|    ``addr_gen`` module after :yoscrypt:`proc -noopt` |    ``addr_gen`` module after :yoscrypt:`proc -noopt` | ||||||
| 
 | 
 | ||||||
| There are now a few new cells from our ``always @``, which have been | There are now a few new cells from our ``always @``, which have been | ||||||
| highlighted.  The ``if`` statements are now modeled with ``$mux`` cells, while | highlighted.  The ``if`` statements are now modeled with `$mux` cells, while the | ||||||
| the register uses an ``$adff`` cell.  If we look at the terminal output we can | register uses an `$adff` cell.  If we look at the terminal output we can also | ||||||
| also see all of the different ``proc_*`` commands being called.  We will look at | see all of the different ``proc_*`` commands being called.  We will look at each | ||||||
| each of these in more detail in :doc:`/using_yosys/synthesis/proc`. | of these in more detail in :doc:`/using_yosys/synthesis/proc`. | ||||||
| 
 | 
 | ||||||
| Notice how in the top left of :ref:`addr_gen_proc` we have a floating wire, | Notice how in the top left of :ref:`addr_gen_proc` we have a floating wire, | ||||||
| generated from the initial assignment of 0 to the ``addr`` wire.  However, this | generated from the initial assignment of 0 to the ``addr`` wire.  However, this | ||||||
| initial assignment is not synthesizable, so this will need to be cleaned up | initial assignment is not synthesizable, so this will need to be cleaned up | ||||||
| before we can generate the physical hardware.  We can do this now by calling | before we can generate the physical hardware.  We can do this now by calling | ||||||
| :cmd:ref:`clean`.  We're also going to call :cmd:ref:`opt_expr` now, which would | `clean`.  We're also going to call `opt_expr` now, which would normally be | ||||||
| normally be called at the end of :cmd:ref:`proc`.  We can call both commands at | called at the end of `proc`.  We can call both commands at the same time by | ||||||
| the same time by separating them with a colon and space: :yoscrypt:`opt_expr; | separating them with a colon and space: :yoscrypt:`opt_expr; clean`. | ||||||
| clean`. |  | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/addr_gen_clean.* | .. figure:: /_images/code_examples/fifo/addr_gen_clean.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|  | @ -171,24 +169,24 @@ clean`. | ||||||
| 
 | 
 | ||||||
|    ``addr_gen`` module after :yoscrypt:`opt_expr; clean` |    ``addr_gen`` module after :yoscrypt:`opt_expr; clean` | ||||||
| 
 | 
 | ||||||
| You may also notice that the highlighted ``$eq`` cell input of ``255`` has | You may also notice that the highlighted `$eq` cell input of ``255`` has changed | ||||||
| changed to ``8'11111111``.  Constant values are presented in the format | to ``8'11111111``.  Constant values are presented in the format | ||||||
| ``<bit_width>'<bits>``, with 32-bit values instead using the decimal number. | ``<bit_width>'<bits>``, with 32-bit values instead using the decimal number. | ||||||
| This indicates that the constant input has been reduced from 32-bit wide to | This indicates that the constant input has been reduced from 32-bit wide to | ||||||
| 8-bit wide.  This is a side-effect of running :cmd:ref:`opt_expr`, which | 8-bit wide.  This is a side-effect of running `opt_expr`, which performs | ||||||
| performs constant folding and simple expression rewriting.    For more on why | constant folding and simple expression rewriting.    For more on why this | ||||||
| this happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section | happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section on | ||||||
| on opt_expr <adv_opt_expr>`. | opt_expr <adv_opt_expr>`. | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    :doc:`/cmd/clean` can also be called with two semicolons after any command, |    :doc:`/cmd/clean` can also be called with two semicolons after any command, | ||||||
|    for example we could have called :yoscrypt:`opt_expr;;` instead of |    for example we could have called :yoscrypt:`opt_expr;;` instead of | ||||||
|    :yoscrypt:`opt_expr; clean`.  You may notice some scripts will end each line |    :yoscrypt:`opt_expr; clean`.  You may notice some scripts will end each line | ||||||
|    with ``;;``.  It is beneficial to run :cmd:ref:`clean` before inspecting |    with ``;;``.  It is beneficial to run `clean` before inspecting intermediate | ||||||
|    intermediate products to remove disconnected parts of the circuit which have |    products to remove disconnected parts of the circuit which have been left | ||||||
|    been left over, and in some cases can reduce the processing required in |    over, and in some cases can reduce the processing required in subsequent | ||||||
|    subsequent commands. |    commands. | ||||||
| 
 | 
 | ||||||
| .. todo:: consider a brief glossary for terms like adff | .. todo:: consider a brief glossary for terms like adff | ||||||
| 
 | 
 | ||||||
|  | @ -202,8 +200,8 @@ The full example | ||||||
| 
 | 
 | ||||||
| Let's now go back and check on our full design by using :yoscrypt:`hierarchy | Let's now go back and check on our full design by using :yoscrypt:`hierarchy | ||||||
| -check -top fifo`.  By passing the ``-check`` option there we are also telling | -check -top fifo`.  By passing the ``-check`` option there we are also telling | ||||||
| the :cmd:ref:`hierarchy` command that if the design includes any non-blackbox | the `hierarchy` command that if the design includes any non-blackbox modules | ||||||
| modules without an implementation it should return an error. | without an implementation it should return an error. | ||||||
| 
 | 
 | ||||||
| Note that if we tried to run this command now then we would get an error.  This | Note that if we tried to run this command now then we would get an error.  This | ||||||
| is because we already removed all of the modules other than ``addr_gen``.  We | is because we already removed all of the modules other than ``addr_gen``.  We | ||||||
|  | @ -218,18 +216,17 @@ could restart our shell session, but instead let's use two new commands: | ||||||
|    :end-before: yosys> proc |    :end-before: yosys> proc | ||||||
|    :caption: reloading :file:`fifo.v` and running :yoscrypt:`hierarchy -check -top fifo` |    :caption: reloading :file:`fifo.v` and running :yoscrypt:`hierarchy -check -top fifo` | ||||||
| 
 | 
 | ||||||
| Notice how this time we didn't see any of those `$abstract` modules?  That's | Notice how this time we didn't see any of those ``$abstract`` modules?  That's | ||||||
| because when we ran ``yosys fifo.v``, the first command Yosys called was | because when we ran ``yosys fifo.v``, the first command Yosys called was | ||||||
| :yoscrypt:`read_verilog -defer fifo.v`.  The ``-defer`` option there tells | :yoscrypt:`read_verilog -defer fifo.v`.  The ``-defer`` option there tells | ||||||
| :cmd:ref:`read_verilog` only read the abstract syntax tree and defer actual | `read_verilog` only read the abstract syntax tree and defer actual compilation | ||||||
| compilation to a later :cmd:ref:`hierarchy` command. This is useful in cases | to a later `hierarchy` command. This is useful in cases where the default | ||||||
| where the default parameters of modules yield invalid code which is not | parameters of modules yield invalid code which is not synthesizable. This is why | ||||||
| synthesizable. This is why Yosys defers compilation automatically and is one of | Yosys defers compilation automatically and is one of the reasons why hierarchy | ||||||
| the reasons why hierarchy should always be the first command after loading the | should always be the first command after loading the design.  If we know that | ||||||
| design.  If we know that our design won't run into this issue, we can skip the | our design won't run into this issue, we can skip the ``-defer``. | ||||||
| ``-defer``. |  | ||||||
| 
 | 
 | ||||||
| .. todo:: :cmd:ref:`hierarchy` failure modes | .. todo:: `hierarchy` failure modes | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|  | @ -243,19 +240,19 @@ design.  If we know that our design won't run into this issue, we can skip the | ||||||
|    interactive terminal.  :kbd:`ctrl+c` (i.e. SIGINT) will also end the terminal |    interactive terminal.  :kbd:`ctrl+c` (i.e. SIGINT) will also end the terminal | ||||||
|    session but will return an error code rather than exiting gracefully. |    session but will return an error code rather than exiting gracefully. | ||||||
| 
 | 
 | ||||||
| We can also run :cmd:ref:`proc` now to finish off the full :ref:`synth_begin`. | We can also run `proc` now to finish off the full :ref:`synth_begin`. Because | ||||||
| Because the design schematic is quite large, we will be showing just the data | the design schematic is quite large, we will be showing just the data path for | ||||||
| path for the ``rdata`` output.  If you would like to see the entire design for | the ``rdata`` output.  If you would like to see the entire design for yourself, | ||||||
| yourself, you can do so with :doc:`/cmd/show`.  Note that the :cmd:ref:`show` | you can do so with :doc:`/cmd/show`.  Note that the `show` command only works | ||||||
| command only works with a single module, so you may need to call it with | with a single module, so you may need to call it with :yoscrypt:`show fifo`. | ||||||
| :yoscrypt:`show fifo`.  :ref:`show_intro` section in | :ref:`show_intro` section in :doc:`/getting_started/scripting_intro` has more on | ||||||
| :doc:`/getting_started/scripting_intro` has more on how to use :cmd:ref:`show`. | how to use `show`. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_proc.* | .. figure:: /_images/code_examples/fifo/rdata_proc.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_proc |    :name: rdata_proc | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`proc` |    ``rdata`` output after `proc` | ||||||
| 
 | 
 | ||||||
| The highlighted ``fifo_reader`` block contains an instance of the | The highlighted ``fifo_reader`` block contains an instance of the | ||||||
| :ref:`addr_gen_proc` that we looked at earlier.  Notice how the type is shown as | :ref:`addr_gen_proc` that we looked at earlier.  Notice how the type is shown as | ||||||
|  | @ -263,10 +260,10 @@ The highlighted ``fifo_reader`` block contains an instance of the | ||||||
| instance of the ``addr_gen`` module with the ``MAX_DATA`` parameter set to the | instance of the ``addr_gen`` module with the ``MAX_DATA`` parameter set to the | ||||||
| given value. | given value. | ||||||
| 
 | 
 | ||||||
| The other highlighted block is a ``$memrd`` cell.  At this stage of synthesis we | The other highlighted block is a `$memrd` cell.  At this stage of synthesis we | ||||||
| don't yet know what type of memory is going to be implemented, but we *do* know | don't yet know what type of memory is going to be implemented, but we *do* know | ||||||
| that ``rdata <= data[raddr];`` could be implemented as a read from memory. Note | that ``rdata <= data[raddr];`` could be implemented as a read from memory. Note | ||||||
| that the ``$memrd`` cell here is asynchronous, with both the clock and enable | that the `$memrd` cell here is asynchronous, with both the clock and enable | ||||||
| signal undefined; shown with the ``1'x`` inputs. | signal undefined; shown with the ``1'x`` inputs. | ||||||
| 
 | 
 | ||||||
| .. seealso:: Advanced usage docs for | .. seealso:: Advanced usage docs for | ||||||
|  | @ -276,7 +273,7 @@ Flattening | ||||||
| ~~~~~~~~~~ | ~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| At this stage of a synthesis flow there are a few other commands we could run. | At this stage of a synthesis flow there are a few other commands we could run. | ||||||
| In :cmd:ref:`synth_ice40` we get these: | In `synth_ice40` we get these: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -286,7 +283,7 @@ In :cmd:ref:`synth_ice40` we get these: | ||||||
|    :name: synth_flatten |    :name: synth_flatten | ||||||
|    :caption: ``flatten`` section |    :caption: ``flatten`` section | ||||||
| 
 | 
 | ||||||
| First off is :cmd:ref:`flatten`.  Flattening the design like this can allow for | First off is `flatten`.  Flattening the design like this can allow for | ||||||
| optimizations between modules which would otherwise be missed.  Let's run | optimizations between modules which would otherwise be missed.  Let's run | ||||||
| :yoscrypt:`flatten;;` on our design. | :yoscrypt:`flatten;;` on our design. | ||||||
| 
 | 
 | ||||||
|  | @ -309,23 +306,22 @@ optimizations between modules which would otherwise be missed.  Let's run | ||||||
| The pieces have moved around a bit, but we can see :ref:`addr_gen_proc` from | The pieces have moved around a bit, but we can see :ref:`addr_gen_proc` from | ||||||
| earlier has replaced the ``fifo_reader`` block in :ref:`rdata_proc`.  We can | earlier has replaced the ``fifo_reader`` block in :ref:`rdata_proc`.  We can | ||||||
| also see that the ``addr`` output has been renamed to :file:`fifo_reader.addr` | also see that the ``addr`` output has been renamed to :file:`fifo_reader.addr` | ||||||
| and merged with the ``raddr`` wire feeding into the ``$memrd`` cell.  This wire | and merged with the ``raddr`` wire feeding into the `$memrd` cell.  This wire | ||||||
| merging happened during the call to :cmd:ref:`clean` which we can see in the | merging happened during the call to `clean` which we can see in the | ||||||
| :ref:`flat_clean`. | :ref:`flat_clean`. | ||||||
| 
 | 
 | ||||||
| .. note::  | .. note::  | ||||||
| 
 | 
 | ||||||
|    :cmd:ref:`flatten` and :cmd:ref:`clean` would normally be combined into a |    `flatten` and `clean` would normally be combined into a | ||||||
|    single :yoterm:`yosys> flatten;;` output, but they appear separately here as |    single :yoterm:`yosys> flatten;;` output, but they appear separately here as | ||||||
|    a side effect of using :cmd:ref:`echo` for generating the terminal style |    a side effect of using `echo` for generating the terminal style | ||||||
|    output. |    output. | ||||||
| 
 | 
 | ||||||
| Depending on the target architecture, this stage of synthesis might also see | Depending on the target architecture, this stage of synthesis might also see | ||||||
| commands such as :cmd:ref:`tribuf` with the ``-logic`` option and | commands such as `tribuf` with the ``-logic`` option and `deminout`.  These | ||||||
| :cmd:ref:`deminout`.  These remove tristate and inout constructs respectively, | remove tristate and inout constructs respectively, replacing them with logic | ||||||
| replacing them with logic suitable for mapping to an FPGA.  Since we do not have | suitable for mapping to an FPGA.  Since we do not have any such constructs in | ||||||
| any such constructs in our example running these commands does not change our | our example running these commands does not change our design. | ||||||
| design. |  | ||||||
| 
 | 
 | ||||||
| The coarse-grain representation | The coarse-grain representation | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -342,9 +338,9 @@ optimizations and other transformations done previously. | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    While the iCE40 flow had a :ref:`synth_flatten` and put :cmd:ref:`proc` in |    While the iCE40 flow had a :ref:`synth_flatten` and put `proc` in the | ||||||
|    the :ref:`synth_begin`, some synthesis scripts will instead include these in |    :ref:`synth_begin`, some synthesis scripts will instead include these in this | ||||||
|    this section. |    section. | ||||||
| 
 | 
 | ||||||
| Part 1 | Part 1 | ||||||
| ^^^^^^ | ^^^^^^ | ||||||
|  | @ -359,36 +355,35 @@ In the iCE40 flow, we start with the following commands: | ||||||
|    :caption: ``coarse`` section (part 1) |    :caption: ``coarse`` section (part 1) | ||||||
|    :name: synth_coarse1 |    :name: synth_coarse1 | ||||||
| 
 | 
 | ||||||
| We've already come across :cmd:ref:`opt_expr`, and :cmd:ref:`opt_clean` is the | We've already come across `opt_expr`, and `opt_clean` is the same as `clean` but | ||||||
| same as :cmd:ref:`clean` but with more verbose output.  The :cmd:ref:`check` | with more verbose output.  The `check` pass identifies a few obvious problems | ||||||
| pass identifies a few obvious problems which will cause errors later.  Calling | which will cause errors later.  Calling it here lets us fail faster rather than | ||||||
| it here lets us fail faster rather than wasting time on something we know is | wasting time on something we know is impossible. | ||||||
| impossible. |  | ||||||
| 
 | 
 | ||||||
| Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple | Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple | ||||||
| optimizations on the design.  This command also ensures that only a specific | optimizations on the design.  This command also ensures that only a specific | ||||||
| subset of FF types are included, in preparation for the next command: | subset of FF types are included, in preparation for the next command: | ||||||
| :doc:`/cmd/fsm`.  Both :cmd:ref:`opt` and :cmd:ref:`fsm` are macro commands | :doc:`/cmd/fsm`.  Both `opt` and `fsm` are macro commands which are explored in | ||||||
| which are explored in more detail in :doc:`/using_yosys/synthesis/opt` and | more detail in :doc:`/using_yosys/synthesis/opt` and | ||||||
| :doc:`/using_yosys/synthesis/fsm` respectively. | :doc:`/using_yosys/synthesis/fsm` respectively. | ||||||
| 
 | 
 | ||||||
| Up until now, the data path for ``rdata`` has remained the same since | Up until now, the data path for ``rdata`` has remained the same since | ||||||
| :ref:`rdata_flat`.  However the next call to :cmd:ref:`opt` does cause a change. | :ref:`rdata_flat`.  However the next call to `opt` does cause a change. | ||||||
| Specifically, the call to :cmd:ref:`opt_dff` without the ``-nodffe -nosdff`` | Specifically, the call to `opt_dff` without the ``-nodffe -nosdff`` options is | ||||||
| options is able to fold one of the ``$mux`` cells into the ``$adff`` to form an | able to fold one of the `$mux` cells into the `$adff` to form an `$adffe` cell; | ||||||
| ``$adffe`` cell; highlighted below: | highlighted below: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.out | .. literalinclude:: /code_examples/fifo/fifo.out | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> opt_dff |    :start-at: yosys> opt_dff | ||||||
|    :end-before: yosys> select |    :end-before: yosys> select | ||||||
|    :caption: output of :cmd:ref:`opt_dff` |    :caption: output of `opt_dff` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_adffe.* | .. figure:: /_images/code_examples/fifo/rdata_adffe.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_adffe |    :name: rdata_adffe | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`opt_dff` |    ``rdata`` output after `opt_dff` | ||||||
| 
 | 
 | ||||||
| .. seealso:: Advanced usage docs for | .. seealso:: Advanced usage docs for | ||||||
|     |     | ||||||
|  | @ -414,27 +409,27 @@ First up is :doc:`/cmd/wreduce`.  If we run this we get the following: | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> wreduce |    :start-at: yosys> wreduce | ||||||
|    :end-before: yosys> select |    :end-before: yosys> select | ||||||
|    :caption: output of :cmd:ref:`wreduce` |    :caption: output of `wreduce` | ||||||
| 
 | 
 | ||||||
| Looking at the data path for ``rdata``, the most relevant of these width | Looking at the data path for ``rdata``, the most relevant of these width | ||||||
| reductions are the ones affecting ``fifo.$flatten\fifo_reader.$add$fifo.v``. | reductions are the ones affecting ``fifo.$flatten\fifo_reader.$add$fifo.v``. | ||||||
| That is the ``$add`` cell incrementing the fifo_reader address.  We can look at | That is the `$add` cell incrementing the fifo_reader address.  We can look at | ||||||
| the schematic and see the output of that cell has now changed. | the schematic and see the output of that cell has now changed. | ||||||
| 
 | 
 | ||||||
| .. todo:: pending bugfix in :cmd:ref:`wreduce` and/or :cmd:ref:`opt_clean` | .. todo:: pending bugfix in `wreduce` and/or `opt_clean` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_wreduce.* | .. figure:: /_images/code_examples/fifo/rdata_wreduce.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_wreduce |    :name: rdata_wreduce | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`wreduce` |    ``rdata`` output after `wreduce` | ||||||
| 
 | 
 | ||||||
| The next two (new) commands are :doc:`/cmd/peepopt` and :doc:`/cmd/share`. | The next two (new) commands are :doc:`/cmd/peepopt` and :doc:`/cmd/share`. | ||||||
| Neither of these affect our design, and they're explored in more detail in | Neither of these affect our design, and they're explored in more detail in | ||||||
| :doc:`/using_yosys/synthesis/opt`, so let's skip over them.  :yoscrypt:`techmap | :doc:`/using_yosys/synthesis/opt`, so let's skip over them.  :yoscrypt:`techmap | ||||||
| -map +/cmp2lut.v -D LUT_WIDTH=4` optimizes certain comparison operators by | -map +/cmp2lut.v -D LUT_WIDTH=4` optimizes certain comparison operators by | ||||||
| converting them to LUTs instead.  The usage of :cmd:ref:`techmap` is explored | converting them to LUTs instead.  The usage of `techmap` is explored more in | ||||||
| more in :doc:`/using_yosys/synthesis/techmap_synth`. | :doc:`/using_yosys/synthesis/techmap_synth`. | ||||||
| 
 | 
 | ||||||
| Our next command to run is | Our next command to run is | ||||||
| :doc:`/cmd/memory_dff`. | :doc:`/cmd/memory_dff`. | ||||||
|  | @ -443,17 +438,17 @@ Our next command to run is | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> memory_dff |    :start-at: yosys> memory_dff | ||||||
|    :end-before: yosys> select |    :end-before: yosys> select | ||||||
|    :caption: output of :cmd:ref:`memory_dff` |    :caption: output of `memory_dff` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_memrdv2.* | .. figure:: /_images/code_examples/fifo/rdata_memrdv2.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_memrdv2 |    :name: rdata_memrdv2 | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`memory_dff` |    ``rdata`` output after `memory_dff` | ||||||
| 
 | 
 | ||||||
| As the title suggests, :cmd:ref:`memory_dff` has merged the output ``$dff`` into | As the title suggests, `memory_dff` has merged the output `$dff` into the | ||||||
| the ``$memrd`` cell and converted it to a ``$memrd_v2`` (highlighted).  This has | `$memrd` cell and converted it to a `$memrd_v2` (highlighted).  This has also | ||||||
| also connected the ``CLK`` port to the ``clk`` input as it is now a synchronous | connected the ``CLK`` port to the ``clk`` input as it is now a synchronous | ||||||
| memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and | memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and | ||||||
| ``SRST=1'0``) inputs. | ``SRST=1'0``) inputs. | ||||||
| 
 | 
 | ||||||
|  | @ -466,12 +461,11 @@ memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and | ||||||
| Part 3 | Part 3 | ||||||
| ^^^^^^ | ^^^^^^ | ||||||
| 
 | 
 | ||||||
| The third part of the :cmd:ref:`synth_ice40` flow is a series of commands for | The third part of the `synth_ice40` flow is a series of commands for mapping to | ||||||
| mapping to DSPs.  By default, the iCE40 flow will not map to the hardware DSP | DSPs.  By default, the iCE40 flow will not map to the hardware DSP blocks and | ||||||
| blocks and will only be performed if called with the ``-dsp`` flag: | will only be performed if called with the ``-dsp`` flag: :yoscrypt:`synth_ice40 | ||||||
| :yoscrypt:`synth_ice40 -dsp`.  While our example has nothing that could be | -dsp`.  While our example has nothing that could be mapped to DSPs we can still | ||||||
| mapped to DSPs we can still take a quick look at the commands here and describe | take a quick look at the commands here and describe what they do. | ||||||
| what they do. |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -482,29 +476,27 @@ what they do. | ||||||
|    :name: synth_coarse3 |    :name: synth_coarse3 | ||||||
| 
 | 
 | ||||||
| :yoscrypt:`wreduce t:$mul` performs width reduction again, this time targetting | :yoscrypt:`wreduce t:$mul` performs width reduction again, this time targetting | ||||||
| only cells of type ``$mul``.  :yoscrypt:`techmap -map +/mul2dsp.v -map | only cells of type `$mul`.  :yoscrypt:`techmap -map +/mul2dsp.v -map | ||||||
| +/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses :cmd:ref:`techmap` to map | +/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses `techmap` to map `$mul` | ||||||
| ``$mul`` cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40 | cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40 ``SB_MAC16``. | ||||||
| ``SB_MAC16``.  Any multipliers which aren't compatible with conversion to | Any multipliers which aren't compatible with conversion to ``$__MUL16X16`` are | ||||||
| ``$__MUL16X16`` are relabelled to ``$__soft_mul`` before :cmd:ref:`chtype` | relabelled to ``$__soft_mul`` before `chtype` changes them back to `$mul`. | ||||||
| changes them back to ``$mul``. |  | ||||||
| 
 | 
 | ||||||
| During the mul2dsp conversion, some of the intermediate signals are marked with | During the mul2dsp conversion, some of the intermediate signals are marked with | ||||||
| the attribute ``mul2dsp``.  By calling :yoscrypt:`select a:mul2dsp` we restrict | the attribute ``mul2dsp``.  By calling :yoscrypt:`select a:mul2dsp` we restrict | ||||||
| the following commands to only operate on the cells and wires used for these | the following commands to only operate on the cells and wires used for these | ||||||
| signals.  :cmd:ref:`setattr` removes the now unnecessary ``mul2dsp`` attribute. | signals.  `setattr` removes the now unnecessary ``mul2dsp`` attribute. | ||||||
| :cmd:ref:`opt_expr` we've already come across for const folding and simple | `opt_expr` we've already come across for const folding and simple expression | ||||||
| expression rewriting, the ``-fine`` option just enables more fine-grain | rewriting, the ``-fine`` option just enables more fine-grain optimizations. | ||||||
| optimizations.  Then we perform width reduction a final time and clear the | Then we perform width reduction a final time and clear the selection. | ||||||
| selection. |  | ||||||
| 
 | 
 | ||||||
| .. todo:: ``ice40_dsp`` is pmgen | .. todo:: ``ice40_dsp`` is pmgen | ||||||
| 
 | 
 | ||||||
| Finally we have :cmd:ref:`ice40_dsp`: similar to the :cmd:ref:`memory_dff` | Finally we have `ice40_dsp`: similar to the `memory_dff` command we saw in the | ||||||
| command we saw in the previous section, this merges any surrounding registers | previous section, this merges any surrounding registers into the ``SB_MAC16`` | ||||||
| into the ``SB_MAC16`` cell.  This includes not just the input/output registers, | cell.  This includes not just the input/output registers, but also pipeline | ||||||
| but also pipeline registers and even a post-adder where applicable: turning a | registers and even a post-adder where applicable: turning a multiply + add into | ||||||
| multiply + add into a single multiply-accumulate. | a single multiply-accumulate. | ||||||
| 
 | 
 | ||||||
| .. seealso:: Advanced usage docs for | .. seealso:: Advanced usage docs for | ||||||
|    :doc:`/using_yosys/synthesis/techmap_synth` |    :doc:`/using_yosys/synthesis/techmap_synth` | ||||||
|  | @ -522,44 +514,43 @@ That brings us to the fourth and final part for the iCE40 synthesis flow: | ||||||
|    :caption: ``coarse`` section (part 4) |    :caption: ``coarse`` section (part 4) | ||||||
|    :name: synth_coarse4 |    :name: synth_coarse4 | ||||||
| 
 | 
 | ||||||
| Where before each type of arithmetic operation had its own cell, e.g. ``$add``, | Where before each type of arithmetic operation had its own cell, e.g. `$add`, we | ||||||
| we now want to extract these into ``$alu`` and ``$macc`` cells which can help | now want to extract these into `$alu` and `$macc` cells which can help identify | ||||||
| identify opportunities for reusing logic.  We do this by running | opportunities for reusing logic.  We do this by running `alumacc`, which we can | ||||||
| :cmd:ref:`alumacc`, which we can see produce the following changes in our | see produce the following changes in our example design: | ||||||
| example design: |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.out | .. literalinclude:: /code_examples/fifo/fifo.out | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> alumacc |    :start-at: yosys> alumacc | ||||||
|    :end-before: yosys> select |    :end-before: yosys> select | ||||||
|    :caption: output of :cmd:ref:`alumacc` |    :caption: output of `alumacc` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_alumacc.* | .. figure:: /_images/code_examples/fifo/rdata_alumacc.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_alumacc |    :name: rdata_alumacc | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`alumacc` |    ``rdata`` output after `alumacc` | ||||||
| 
 | 
 | ||||||
| Once these cells have been inserted, the call to :cmd:ref:`opt` can combine | Once these cells have been inserted, the call to `opt` can combine cells which | ||||||
| cells which are now identical but may have been missed due to e.g. the | are now identical but may have been missed due to e.g. the difference between | ||||||
| difference between ``$add`` and ``$sub``. | `$add` and `$sub`. | ||||||
| 
 | 
 | ||||||
| The other new command in this part is :doc:`/cmd/memory`.  :cmd:ref:`memory` is | The other new command in this part is :doc:`/cmd/memory`.  `memory` is another | ||||||
| another macro command which we examine in more detail in | macro command which we examine in more detail in | ||||||
| :doc:`/using_yosys/synthesis/memory`.  For this document, let us focus just on | :doc:`/using_yosys/synthesis/memory`.  For this document, let us focus just on | ||||||
| the step most relevant to our example: :cmd:ref:`memory_collect`. Up until this | the step most relevant to our example: `memory_collect`. Up until this point, | ||||||
| point, our memory reads and our memory writes have been totally disjoint cells; | our memory reads and our memory writes have been totally disjoint cells; | ||||||
| operating on the same memory only in the abstract. :cmd:ref:`memory_collect` | operating on the same memory only in the abstract. `memory_collect` combines all | ||||||
| combines all of the reads and writes for a memory block into a single cell. | of the reads and writes for a memory block into a single cell. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/rdata_coarse.* | .. figure:: /_images/code_examples/fifo/rdata_coarse.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: rdata_coarse |    :name: rdata_coarse | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :cmd:ref:`memory_collect` |    ``rdata`` output after `memory_collect` | ||||||
| 
 | 
 | ||||||
| Looking at the schematic after running :cmd:ref:`memory_collect` we see that our | Looking at the schematic after running `memory_collect` we see that our | ||||||
| ``$memrd_v2`` cell has been replaced with a ``$mem_v2`` cell named ``data``, the | `$memrd_v2` cell has been replaced with a `$mem_v2` cell named ``data``, the | ||||||
| same name that we used in :ref:`fifo-v`. Where before we had a single set of | same name that we used in :ref:`fifo-v`. Where before we had a single set of | ||||||
| signals for address and enable, we now have one set for reading (``RD_*``) and | signals for address and enable, we now have one set for reading (``RD_*``) and | ||||||
| one for writing (``WR_*``), as well as both ``WR_DATA`` input and ``RD_DATA`` | one for writing (``WR_*``), as well as both ``WR_DATA`` input and ``RD_DATA`` | ||||||
|  | @ -592,8 +583,8 @@ If you skipped calling :yoscrypt:`read_verilog -D ICE40_HX -lib -specify | ||||||
| Memory blocks | Memory blocks | ||||||
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Mapping to hard memory blocks uses a combination of :cmd:ref:`memory_libmap` and | Mapping to hard memory blocks uses a combination of `memory_libmap` and | ||||||
| :cmd:ref:`techmap`. | `techmap`. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -609,28 +600,28 @@ Mapping to hard memory blocks uses a combination of :cmd:ref:`memory_libmap` and | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :ref:`map_ram` |    ``rdata`` output after :ref:`map_ram` | ||||||
| 
 | 
 | ||||||
| The :ref:`map_ram` converts the generic ``$mem_v2`` into the iCE40 | The :ref:`map_ram` converts the generic `$mem_v2` into the iCE40 ``SB_RAM40_4K`` | ||||||
| ``SB_RAM40_4K`` (highlighted). We can also see the memory address has been | (highlighted). We can also see the memory address has been remapped, and the | ||||||
| remapped, and the data bits have been reordered (or swizzled).  There is also | data bits have been reordered (or swizzled).  There is also now a `$mux` cell | ||||||
| now a ``$mux`` cell controlling the value of ``rdata``.  In :ref:`fifo-v` we | controlling the value of ``rdata``.  In :ref:`fifo-v` we wrote our memory as | ||||||
| wrote our memory as read-before-write, however the ``SB_RAM40_4K`` has undefined | read-before-write, however the ``SB_RAM40_4K`` has undefined behaviour when | ||||||
| behaviour when reading from and writing to the same address in the same cycle. | reading from and writing to the same address in the same cycle. As a result, | ||||||
| As a result, extra logic is added so that the generated circuit matches the | extra logic is added so that the generated circuit matches the behaviour of the | ||||||
| behaviour of the verilog.  :ref:`no_rw_check` describes how we could change our | verilog.  :ref:`no_rw_check` describes how we could change our verilog to match | ||||||
| verilog to match our hardware instead. | our hardware instead. | ||||||
| 
 | 
 | ||||||
| If we run :cmd:ref:`memory_libmap` under the :cmd:ref:`debug` command we can see | If we run `memory_libmap` under the `debug` command we can see candidates which | ||||||
| candidates which were identified for mapping, along with the costs of each and | were identified for mapping, along with the costs of each and what logic | ||||||
| what logic requires emulation. | requires emulation. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.libmap | .. literalinclude:: /code_examples/fifo/fifo.libmap | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :lines: 2, 6- |    :lines: 2, 6- | ||||||
| 
 | 
 | ||||||
| The ``$__ICE40_RAM4K_`` cell is defined in the file |techlibs/ice40/brams.txt|_, | The ``$__ICE40_RAM4K_`` cell is defined in the file |techlibs/ice40/brams.txt|_, | ||||||
| with the mapping to ``SB_RAM40_4K`` done by :cmd:ref:`techmap` using | with the mapping to ``SB_RAM40_4K`` done by `techmap` using | ||||||
| |techlibs/ice40/brams_map.v|_.  Any leftover memory cells are then converted | |techlibs/ice40/brams_map.v|_.  Any leftover memory cells are then converted | ||||||
| into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`. | into flip flops (the ``logic fallback``) with `memory_map`. | ||||||
| 
 | 
 | ||||||
| .. |techlibs/ice40/brams.txt| replace:: :file:`techlibs/ice40/brams.txt` | .. |techlibs/ice40/brams.txt| replace:: :file:`techlibs/ice40/brams.txt` | ||||||
| .. _techlibs/ice40/brams.txt: https://github.com/YosysHQ/yosys/tree/main/techlibs/ice40/brams.txt | .. _techlibs/ice40/brams.txt: https://github.com/YosysHQ/yosys/tree/main/techlibs/ice40/brams.txt | ||||||
|  | @ -654,8 +645,8 @@ into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`. | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    The visual clutter on the ``RDATA`` output port (highlighted) is an |    The visual clutter on the ``RDATA`` output port (highlighted) is an | ||||||
|    unfortunate side effect of :cmd:ref:`opt_clean` on the swizzled data bits. In |    unfortunate side effect of `opt_clean` on the swizzled data bits. In | ||||||
|    connecting the ``$mux`` input port directly to ``RDATA`` to reduce the number |    connecting the `$mux` input port directly to ``RDATA`` to reduce the number | ||||||
|    of wires, the ``$techmap579\data.0.0.RDATA`` wire becomes more visually |    of wires, the ``$techmap579\data.0.0.RDATA`` wire becomes more visually | ||||||
|    complex. |    complex. | ||||||
| 
 | 
 | ||||||
|  | @ -667,11 +658,10 @@ into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`. | ||||||
| Arithmetic | Arithmetic | ||||||
| ^^^^^^^^^^ | ^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Uses :cmd:ref:`techmap` to map basic arithmetic logic to hardware.  This sees | Uses `techmap` to map basic arithmetic logic to hardware.  This sees somewhat of | ||||||
| somewhat of an explosion in cells as multi-bit ``$mux`` and ``$adffe`` are | an explosion in cells as multi-bit `$mux` and `$adffe` are replaced with | ||||||
| replaced with single-bit ``$_MUX_`` and ``$_DFFE_PP0P_`` cells, while the | single-bit `$_MUX_` and `$_DFFE_PP0P_` cells, while the `$alu` is replaced with | ||||||
| ``$alu`` is replaced with primitive ``$_OR_`` and ``$_NOT_`` gates and a | primitive `$_OR_` and `$_NOT_` gates and a `$lut` cell. | ||||||
| ``$lut`` cell. |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -693,14 +683,14 @@ replaced with single-bit ``$_MUX_`` and ``$_DFFE_PP0P_`` cells, while the | ||||||
| Flip-flops | Flip-flops | ||||||
| ^^^^^^^^^^ | ^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Convert FFs to the types supported in hardware with :cmd:ref:`dfflegalize`, and | Convert FFs to the types supported in hardware with `dfflegalize`, and then use | ||||||
| then use :cmd:ref:`techmap` to map them.  In our example, this converts the | `techmap` to map them.  In our example, this converts the `$_DFFE_PP0P_` cells | ||||||
| ``$_DFFE_PP0P_`` cells to ``SB_DFFER``. | to ``SB_DFFER``. | ||||||
| 
 | 
 | ||||||
| We also run :cmd:ref:`simplemap` here to convert any remaining cells which could | We also run `simplemap` here to convert any remaining cells which could not be | ||||||
| not be mapped to hardware into gate-level primitives.  This includes optimizing | mapped to hardware into gate-level primitives.  This includes optimizing | ||||||
| ``$_MUX_`` cells where one of the inputs is a constant ``1'0``, replacing it | `$_MUX_` cells where one of the inputs is a constant ``1'0``, replacing it | ||||||
| instead with an ``$_AND_`` cell. | instead with an `$_AND_` cell. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -722,11 +712,10 @@ instead with an ``$_AND_`` cell. | ||||||
| LUTs | LUTs | ||||||
| ^^^^ | ^^^^ | ||||||
| 
 | 
 | ||||||
| :cmd:ref:`abc` and :cmd:ref:`techmap` are used to map LUTs; converting primitive | `abc` and `techmap` are used to map LUTs; converting primitive cell types to use | ||||||
| cell types to use ``$lut`` and ``SB_CARRY`` cells.  Note that the iCE40 flow | `$lut` and ``SB_CARRY`` cells.  Note that the iCE40 flow uses `abc9` rather than | ||||||
| uses :cmd:ref:`abc9` rather than :cmd:ref:`abc`. For more on what these do, and | `abc`. For more on what these do, and what the difference between these two | ||||||
| what the difference between these two commands are, refer to | commands are, refer to :doc:`/using_yosys/synthesis/abc`. | ||||||
| :doc:`/using_yosys/synthesis/abc`. |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -742,8 +731,8 @@ what the difference between these two commands are, refer to | ||||||
| 
 | 
 | ||||||
|    ``rdata`` output after :ref:`map_luts` |    ``rdata`` output after :ref:`map_luts` | ||||||
| 
 | 
 | ||||||
| Finally we use :cmd:ref:`techmap` to map the generic ``$lut`` cells to iCE40 | Finally we use `techmap` to map the generic `$lut` cells to iCE40 ``SB_LUT4`` | ||||||
| ``SB_LUT4`` cells. | cells. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/synth_ice40.rst | .. literalinclude:: /cmd/synth_ice40.rst | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -769,12 +758,12 @@ Other cells | ||||||
| 
 | 
 | ||||||
| The following commands may also be used for mapping other cells: | The following commands may also be used for mapping other cells: | ||||||
| 
 | 
 | ||||||
| :cmd:ref:`hilomap` | `hilomap` | ||||||
|     Some architectures require special driver cells for driving a constant hi or |     Some architectures require special driver cells for driving a constant hi or | ||||||
|     lo value. This command replaces simple constants with instances of such |     lo value. This command replaces simple constants with instances of such | ||||||
|     driver cells. |     driver cells. | ||||||
| 
 | 
 | ||||||
| :cmd:ref:`iopadmap` | `iopadmap` | ||||||
|     Top-level input/outputs must usually be implemented using special I/O-pad |     Top-level input/outputs must usually be implemented using special I/O-pad | ||||||
|     cells. This command inserts such cells to the design. |     cells. This command inserts such cells to the design. | ||||||
| 
 | 
 | ||||||
|  | @ -801,28 +790,27 @@ The new commands here are: | ||||||
| - :doc:`/cmd/stat`, and | - :doc:`/cmd/stat`, and | ||||||
| - :doc:`/cmd/blackbox`. | - :doc:`/cmd/blackbox`. | ||||||
| 
 | 
 | ||||||
| The output from :cmd:ref:`stat` is useful for checking resource utilization; | The output from `stat` is useful for checking resource utilization; providing a | ||||||
| providing a list of cells used in the design and the number of each, as well as | list of cells used in the design and the number of each, as well as the number | ||||||
| the number of other resources used such as wires and processes.  For this | of other resources used such as wires and processes.  For this design, the final | ||||||
| design, the final call to :cmd:ref:`stat` should look something like the | call to `stat` should look something like the following: | ||||||
| following: |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.stat | .. literalinclude:: /code_examples/fifo/fifo.stat | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> stat -top fifo |    :start-at: yosys> stat -top fifo | ||||||
| 
 | 
 | ||||||
| Note that the :yoscrypt:`-top fifo` here is optional.  :cmd:ref:`stat` will | Note that the :yoscrypt:`-top fifo` here is optional.  `stat` will automatically | ||||||
| automatically use the module with the ``top`` attribute set, which ``fifo`` was | use the module with the ``top`` attribute set, which ``fifo`` was when we called | ||||||
| when we called :cmd:ref:`hierarchy`.  If no module is marked ``top``, then stats | `hierarchy`.  If no module is marked ``top``, then stats will be shown for each | ||||||
| will be shown for each module selected. | module selected. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`stat` output is also useful as a kind of sanity-check: Since we | The `stat` output is also useful as a kind of sanity-check: Since we have | ||||||
| have already run :cmd:ref:`proc`, we wouldn't expect there to be any processes. | already run `proc`, we wouldn't expect there to be any processes. We also expect | ||||||
| We also expect ``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw | ``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw a high number | ||||||
| a high number of flip-flops being used we might suspect something was wrong. | of flip-flops being used we might suspect something was wrong. | ||||||
| 
 | 
 | ||||||
| If we instead called :cmd:ref:`stat` immediately after :yoscrypt:`read_verilog | If we instead called `stat` immediately after :yoscrypt:`read_verilog fifo.v` we | ||||||
| fifo.v` we would see something very different: | would see something very different: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.stat | .. literalinclude:: /code_examples/fifo/fifo.stat | ||||||
|    :language: doscon |    :language: doscon | ||||||
|  | @ -845,10 +833,10 @@ The iCE40 synthesis flow has the following output modes available: | ||||||
| 
 | 
 | ||||||
| As an example, if we called :yoscrypt:`synth_ice40 -top fifo -json fifo.json`, | As an example, if we called :yoscrypt:`synth_ice40 -top fifo -json fifo.json`, | ||||||
| our synthesized ``fifo`` design will be output as :file:`fifo.json`.  We can | our synthesized ``fifo`` design will be output as :file:`fifo.json`.  We can | ||||||
| then read the design back into Yosys with :cmd:ref:`read_json`, but make sure | then read the design back into Yosys with `read_json`, but make sure you use | ||||||
| you use :yoscrypt:`design -reset` or open a new interactive terminal first.  The | :yoscrypt:`design -reset` or open a new interactive terminal first.  The JSON | ||||||
| JSON output we get can also be loaded into `nextpnr`_ to do place and route; but | output we get can also be loaded into `nextpnr`_ to do place and route; but that | ||||||
| that is beyond the scope of this documentation. | is beyond the scope of this documentation. | ||||||
| 
 | 
 | ||||||
| .. _nextpnr: https://github.com/YosysHQ/nextpnr | .. _nextpnr: https://github.com/YosysHQ/nextpnr | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -88,7 +88,7 @@ A C++ compiler with C++17 support is required as well as some standard tools | ||||||
| such as GNU Flex, GNU Bison, Make and Python.  Some additional tools: readline, | such as GNU Flex, GNU Bison, Make and Python.  Some additional tools: readline, | ||||||
| libffi, Tcl and zlib; are optional but enabled by default (see | libffi, Tcl and zlib; are optional but enabled by default (see | ||||||
| :makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the | :makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the | ||||||
| :cmd:ref:`show` command to display schematics. | `show` command to display schematics. | ||||||
| 
 | 
 | ||||||
| Installing all prerequisites for Ubuntu 20.04: | Installing all prerequisites for Ubuntu 20.04: | ||||||
| 
 | 
 | ||||||
|  | @ -109,7 +109,7 @@ Installing all prerequisites for macOS 11 (with Homebrew): | ||||||
| Running the build system | Running the build system | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| From the root `yosys` directory, call the following commands: | From the root ``yosys`` directory, call the following commands: | ||||||
| 
 | 
 | ||||||
| .. code:: console | .. code:: console | ||||||
|     |     | ||||||
|  | @ -117,7 +117,7 @@ From the root `yosys` directory, call the following commands: | ||||||
|    sudo make install |    sudo make install | ||||||
| 
 | 
 | ||||||
| This will build and then install Yosys, making it available on the command line | This will build and then install Yosys, making it available on the command line | ||||||
| as `yosys`.  Note that this also downloads, builds, and installs `ABC`_ (using | as ``yosys``.  Note that this also downloads, builds, and installs `ABC`_ (using | ||||||
| :program:`yosys-abc` as the executable name). | :program:`yosys-abc` as the executable name). | ||||||
| 
 | 
 | ||||||
| .. _ABC: https://github.com/berkeley-abc/abc | .. _ABC: https://github.com/berkeley-abc/abc | ||||||
|  | @ -184,9 +184,8 @@ directories: | ||||||
| 
 | 
 | ||||||
| ``passes/`` | ``passes/`` | ||||||
|    This directory contains a subdirectory for each pass or group of passes. For |    This directory contains a subdirectory for each pass or group of passes. For | ||||||
|    example as of this writing the directory :file:`passes/hierarchy/` contains the |    example as of this writing the directory :file:`passes/hierarchy/` contains | ||||||
|    code for three passes: :cmd:ref:`hierarchy`, :cmd:ref:`submod`, and |    the code for three passes: `hierarchy`, `submod`, and `uniquify`. | ||||||
|    :cmd:ref:`uniquify`. |  | ||||||
| 
 | 
 | ||||||
| ``techlibs/`` | ``techlibs/`` | ||||||
|    This directory contains simulation models and standard implementations for |    This directory contains simulation models and standard implementations for | ||||||
|  |  | ||||||
|  | @ -7,8 +7,7 @@ file format and how you can make your own synthesis scripts. | ||||||
| 
 | 
 | ||||||
| Yosys script files typically use the :file:`.ys` extension and contain a set of | Yosys script files typically use the :file:`.ys` extension and contain a set of | ||||||
| commands for Yosys to run sequentially.  These commands are the same ones we | commands for Yosys to run sequentially.  These commands are the same ones we | ||||||
| were using on the previous page like :cmd:ref:`read_verilog` and | were using on the previous page like `read_verilog` and `hierarchy`. | ||||||
| :cmd:ref:`hierarchy`. |  | ||||||
| 
 | 
 | ||||||
| Script parsing | Script parsing | ||||||
| ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~ | ||||||
|  | @ -39,9 +38,9 @@ Another special character that can be used in Yosys scripts is the bang ``!``. | ||||||
| Anything after the bang will be executed as a shell command.  This can only be | Anything after the bang will be executed as a shell command.  This can only be | ||||||
| terminated with a new line.  Any semicolons, hashes, or other special characters | terminated with a new line.  Any semicolons, hashes, or other special characters | ||||||
| will be passed to the shell.  If an error code is returned from the shell it | will be passed to the shell.  If an error code is returned from the shell it | ||||||
| will be raised by Yosys.  :cmd:ref:`exec` provides a much more flexible way of | will be raised by Yosys.  `exec` provides a much more flexible way of executing | ||||||
| executing commands, allowing the output to be logged and more control over when | commands, allowing the output to be logged and more control over when to | ||||||
| to generate errors. | generate errors. | ||||||
| 
 | 
 | ||||||
| The synthesis starter script | The synthesis starter script | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -62,24 +61,23 @@ already, let's take a look at some of those script files now. | ||||||
|    :caption: A section of :file:`fifo.ys`, generating the images used for :ref:`addr_gen_example` |    :caption: A section of :file:`fifo.ys`, generating the images used for :ref:`addr_gen_example` | ||||||
|    :name: fifo-ys |    :name: fifo-ys | ||||||
| 
 | 
 | ||||||
| The first command there, :yoscrypt:`echo on`, uses :cmd:ref:`echo` to enable | The first command there, :yoscrypt:`echo on`, uses `echo` to enable command | ||||||
| command echoes on.  This is how we generated the code listing for | echoes on.  This is how we generated the code listing for | ||||||
| :ref:`hierarchy_output`.  Turning command echoes on prints the ``yosys> | :ref:`hierarchy_output`.  Turning command echoes on prints the ``yosys> | ||||||
| hierarchy -top addr_gen`` line, making the output look the same as if it were an | hierarchy -top addr_gen`` line, making the output look the same as if it were an | ||||||
| interactive terminal.  :yoscrypt:`hierarchy -top addr_gen` is of course the | interactive terminal.  :yoscrypt:`hierarchy -top addr_gen` is of course the | ||||||
| command we were demonstrating, including the output text and an image of the | command we were demonstrating, including the output text and an image of the | ||||||
| design schematic after running it. | design schematic after running it. | ||||||
| 
 | 
 | ||||||
| We briefly touched on :cmd:ref:`select` when it came up in | We briefly touched on `select` when it came up in `synth_ice40`, but let's look | ||||||
| :cmd:ref:`synth_ice40`, but let's look at it more now. | at it more now. | ||||||
| 
 | 
 | ||||||
| .. _select_intro: | .. _select_intro: | ||||||
| 
 | 
 | ||||||
| Selections intro | Selections intro | ||||||
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`select` command is used to modify and view the list of selected | The `select` command is used to modify and view the list of selected objects: | ||||||
| objects: |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/fifo/fifo.out | .. literalinclude:: /code_examples/fifo/fifo.out | ||||||
|    :language: doscon |    :language: doscon | ||||||
|  | @ -99,7 +97,7 @@ signifies we are matching on the *cell type*, and the ``*`` means to match | ||||||
| anything.  For this (very simple) selection, we are trying to find all of the | anything.  For this (very simple) selection, we are trying to find all of the | ||||||
| cells, regardless of their type.  The active selection is now shown as | cells, regardless of their type.  The active selection is now shown as | ||||||
| ``[addr_gen]*``, indicating some sub-selection of the ``addr_gen`` module.  This | ``[addr_gen]*``, indicating some sub-selection of the ``addr_gen`` module.  This | ||||||
| gives us the ``$add`` and ``$eq`` cells, which we want to highlight for the | gives us the `$add` and `$eq` cells, which we want to highlight for the | ||||||
| :ref:`addr_gen_hier` image. | :ref:`addr_gen_hier` image. | ||||||
| 
 | 
 | ||||||
| .. _select_new_cells: | .. _select_new_cells: | ||||||
|  | @ -111,15 +109,16 @@ by referring to it as ``@new_cells``, which we will see later.  Then we clear | ||||||
| the selection so that the following commands can operate on the full design. | the selection so that the following commands can operate on the full design. | ||||||
| While we split that out for this document, we could have done the same thing in | While we split that out for this document, we could have done the same thing in | ||||||
| a single line by calling :yoscrypt:`select -set new_cells addr_gen/t:*`.  If we | a single line by calling :yoscrypt:`select -set new_cells addr_gen/t:*`.  If we | ||||||
| know we only have the one module in our design, we can even skip the `addr_gen/` | know we only have the one module in our design, we can even skip the | ||||||
| part.  Looking further down :ref:`the fifo.ys code <fifo-ys>` we can see this | ``addr_gen/`` part.  Looking further down :ref:`the fifo.ys code <fifo-ys>` we | ||||||
| with :yoscrypt:`select -set new_cells t:$mux t:*dff`.  We can also see in that | can see this with :yoscrypt:`select -set new_cells t:$mux t:*dff`.  We can also | ||||||
| command that selections don't have to be limited to a single statement. | see in that command that selections don't have to be limited to a single | ||||||
|  | statement. | ||||||
| 
 | 
 | ||||||
| Many commands also support an optional ``[selection]`` argument which can be | Many commands also support an optional ``[selection]`` argument which can be | ||||||
| used to override the currently selected objects.  We could, for example, call | used to override the currently selected objects.  We could, for example, call | ||||||
| :yoscrypt:`clean addr_gen` to have :cmd:ref:`clean` operate on *just* the | :yoscrypt:`clean addr_gen` to have `clean` operate on *just* the ``addr_gen`` | ||||||
| ``addr_gen`` module. | module. | ||||||
| 
 | 
 | ||||||
| Detailed documentation of the select framework can be found under | Detailed documentation of the select framework can be found under | ||||||
| :doc:`/using_yosys/more_scripting/selections` or in the command reference at | :doc:`/using_yosys/more_scripting/selections` or in the command reference at | ||||||
|  | @ -130,23 +129,23 @@ Detailed documentation of the select framework can be found under | ||||||
| Displaying schematics | Displaying schematics | ||||||
| ^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| While the :cmd:ref:`select` command is very useful, sometimes nothing beats | While the `select` command is very useful, sometimes nothing beats being able to | ||||||
| being able to see a design for yourself.  This is where :cmd:ref:`show` comes | see a design for yourself.  This is where `show` comes in.  Note that this | ||||||
| in.  Note that this document is just an introduction to the :cmd:ref:`show` | document is just an introduction to the `show` command, only covering the | ||||||
| command, only covering the basics.  For more information, including a guide on | basics.  For more information, including a guide on what the different symbols | ||||||
| what the different symbols represent, see :ref:`interactive_show` and the | represent, see :ref:`interactive_show` and the | ||||||
| :doc:`/using_yosys/more_scripting/interactive_investigation` page. | :doc:`/using_yosys/more_scripting/interactive_investigation` page. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/addr_gen_show.* | .. figure:: /_images/code_examples/fifo/addr_gen_show.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: addr_gen_show |    :name: addr_gen_show | ||||||
| 
 | 
 | ||||||
|    Calling :yoscrypt:`show addr_gen` after :cmd:ref:`hierarchy` |    Calling :yoscrypt:`show addr_gen` after `hierarchy` | ||||||
| 
 | 
 | ||||||
| .. note::  | .. note::  | ||||||
| 
 | 
 | ||||||
|    The :cmd:ref:`show` command requires a working installation of `GraphViz`_ |    The `show` command requires a working installation of `GraphViz`_ and `xdot`_ | ||||||
|    and `xdot`_ for displaying the actual circuit diagrams. |    for displaying the actual circuit diagrams. | ||||||
|     |     | ||||||
| .. _GraphViz: http://www.graphviz.org/ | .. _GraphViz: http://www.graphviz.org/ | ||||||
| .. _xdot: https://github.com/jrfonseca/xdot.py | .. _xdot: https://github.com/jrfonseca/xdot.py | ||||||
|  | @ -160,8 +159,8 @@ we see the following: | ||||||
|    :start-at: -prefix addr_gen_show |    :start-at: -prefix addr_gen_show | ||||||
|    :end-before: yosys> show |    :end-before: yosys> show | ||||||
| 
 | 
 | ||||||
| Calling :cmd:ref:`show` with :yoscrypt:`-format dot` tells it we want to output | Calling `show` with :yoscrypt:`-format dot` tells it we want to output a | ||||||
| a :file:`.dot` file rather than opening it for display.  The :yoscrypt:`-prefix | :file:`.dot` file rather than opening it for display.  The :yoscrypt:`-prefix | ||||||
| addr_gen_show` option indicates we want the file to be called | addr_gen_show` option indicates we want the file to be called | ||||||
| :file:`addr_gen_show.{*}`. Remember, we do this in :file:`fifo.ys` because we | :file:`addr_gen_show.{*}`. Remember, we do this in :file:`fifo.ys` because we | ||||||
| need to store the image for displaying in the documentation you're reading.  But | need to store the image for displaying in the documentation you're reading.  But | ||||||
|  | @ -184,8 +183,8 @@ like when we called :yoscrypt:`select -module addr_gen` in :ref:`select_intro`. | ||||||
| That last parameter doesn't have to be a module name, it can be any valid | That last parameter doesn't have to be a module name, it can be any valid | ||||||
| selection string.  Remember when we :ref:`assigned a name to a | selection string.  Remember when we :ref:`assigned a name to a | ||||||
| selection<select_new_cells>` and called it ``new_cells``?  We saw in the | selection<select_new_cells>` and called it ``new_cells``?  We saw in the | ||||||
| :yoscrypt:`select -list` output that it contained two cells, an ``$add`` and an | :yoscrypt:`select -list` output that it contained two cells, an `$add` and an | ||||||
| ``$eq``.  We can call :cmd:ref:`show` on that selection just as easily: | `$eq`.  We can call `show` on that selection just as easily: | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/fifo/new_cells_show.* | .. figure:: /_images/code_examples/fifo/new_cells_show.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|  | @ -207,21 +206,20 @@ the two ``PROC`` blocks.  To achieve this highlight, we make use of the | ||||||
| 
 | 
 | ||||||
|    Calling :yoscrypt:`show -color maroon3 @new_cells -color cornflowerblue p:* -notitle` |    Calling :yoscrypt:`show -color maroon3 @new_cells -color cornflowerblue p:* -notitle` | ||||||
| 
 | 
 | ||||||
| As described in the the :cmd:ref:`help` output for :cmd:ref:`show` (or by | As described in the the `help` output for `show` (or by clicking on the `show` | ||||||
| clicking on the :cmd:ref:`show` link), colors are specified as :yoscrypt:`-color | link), colors are specified as :yoscrypt:`-color <color> <object>`.  Color names | ||||||
| <color> <object>`.  Color names for the ``<color>`` portion can be found on the | for the ``<color>`` portion can be found on the `GraphViz color docs`_.  Unlike | ||||||
| `GraphViz color docs`_.  Unlike the final :cmd:ref:`show` parameter which can | the final `show` parameter which can have be any selection string, the | ||||||
| have be any selection string, the ``<object>`` part must be a single selection | ``<object>`` part must be a single selection expression or named selection. | ||||||
| expression or named selection.  That means while we can use ``@new_cells``, we | That means while we can use ``@new_cells``, we couldn't use ``t:$eq t:$add``. | ||||||
| couldn't use ``t:$eq t:$add``.  In general, if a command lists ``[selection]`` | In general, if a command lists ``[selection]`` as its final parameter it can be | ||||||
| as its final parameter it can be any selection string.  Any selections that are | any selection string.  Any selections that are not the final parameter, such as | ||||||
| not the final parameter, such as those used in options, must be a single | those used in options, must be a single expression instead. | ||||||
| expression instead. |  | ||||||
| 
 | 
 | ||||||
| .. _GraphViz color docs: https://graphviz.org/doc/info/colors | .. _GraphViz color docs: https://graphviz.org/doc/info/colors | ||||||
| 
 | 
 | ||||||
| For all of the options available to :cmd:ref:`show`, check the command reference | For all of the options available to `show`, check the command reference at | ||||||
| at :doc:`/cmd/show`. | :doc:`/cmd/show`. | ||||||
| 
 | 
 | ||||||
| .. seealso:: :ref:`interactive_show` on the | .. seealso:: :ref:`interactive_show` on the | ||||||
|    :doc:`/using_yosys/more_scripting/interactive_investigation` page. |    :doc:`/using_yosys/more_scripting/interactive_investigation` page. | ||||||
|  |  | ||||||
|  | @ -27,18 +27,28 @@ available, go to :ref:`commandindex`. | ||||||
| 
 | 
 | ||||||
| .. todolist:: | .. todolist:: | ||||||
| 
 | 
 | ||||||
| .. only:: html |  | ||||||
| 
 |  | ||||||
|    Table of contents |  | ||||||
|    ----------------- |  | ||||||
| 
 |  | ||||||
| .. toctree:: | .. toctree:: | ||||||
|    :maxdepth: 3 |    :maxdepth: 3 | ||||||
|    :includehidden: |    :includehidden: | ||||||
| 
 | 
 | ||||||
|  |    Yosys (index) <self> | ||||||
|    introduction |    introduction | ||||||
|  | 
 | ||||||
|    getting_started/index |    getting_started/index | ||||||
|    using_yosys/index |    using_yosys/index | ||||||
|    yosys_internals/index |    yosys_internals/index | ||||||
| 
 | 
 | ||||||
|    appendix | .. toctree:: | ||||||
|  |    :caption: Appendix | ||||||
|  |    :titlesonly: | ||||||
|  |    :includehidden: | ||||||
|  | 
 | ||||||
|  |    appendix/primer | ||||||
|  |    appendix/rtlil_text | ||||||
|  |    appendix/auxlibs | ||||||
|  |    appendix/auxprogs | ||||||
|  | 
 | ||||||
|  |    bib | ||||||
|  | 
 | ||||||
|  |    cell_index | ||||||
|  |    cmd_ref | ||||||
|  |  | ||||||
|  | @ -161,9 +161,9 @@ Benefits of open source HDL synthesis | ||||||
| 
 | 
 | ||||||
| - Cost (also applies to ``free as in free beer`` solutions):  | - Cost (also applies to ``free as in free beer`` solutions):  | ||||||
|    |    | ||||||
|   Today the cost for a mask set in 180nm technology is far less than |   Today the cost for a mask set in 180nm technology is far less than the cost | ||||||
|   the cost for the design tools needed to design the mask layouts. Open Source |   for the design tools needed to design the mask layouts. Open Source ASIC flows | ||||||
|   ASIC flows are an important enabler for ASIC-level Open Source Hardware. |   are an important enabler for ASIC-level Open Source Hardware. | ||||||
| 
 | 
 | ||||||
| - Availability and Reproducibility:  | - Availability and Reproducibility:  | ||||||
|    |    | ||||||
|  | @ -171,21 +171,23 @@ Benefits of open source HDL synthesis | ||||||
|   else can also use. Even if most universities have access to all major |   else can also use. Even if most universities have access to all major | ||||||
|   commercial tools, you usually do not have easy access to the version that was |   commercial tools, you usually do not have easy access to the version that was | ||||||
|   used in a research project a couple of years ago. With Open Source tools you |   used in a research project a couple of years ago. With Open Source tools you | ||||||
|   can even release the source code of the tool you have used alongside your data. |   can even release the source code of the tool you have used alongside your | ||||||
|  |   data. | ||||||
| 
 | 
 | ||||||
| - Framework:  | - Framework:  | ||||||
|    |    | ||||||
|   Yosys is not only a tool. It is a framework that can be used as basis for other |   Yosys is not only a tool. It is a framework that can be used as basis for | ||||||
|   developments, so researchers and hackers alike do not need to re-invent the |   other developments, so researchers and hackers alike do not need to re-invent | ||||||
|   basic functionality. Extensibility was one of Yosys' design goals. |   the basic functionality. Extensibility was one of Yosys' design goals. | ||||||
| 
 | 
 | ||||||
| - All-in-one:  | - All-in-one:  | ||||||
|    |    | ||||||
|   Because of the framework characteristics of Yosys, an increasing number of features |   Because of the framework characteristics of Yosys, an increasing number of | ||||||
|   become available in one tool. Yosys not only can be used for circuit synthesis but |   features become available in one tool. Yosys not only can be used for circuit | ||||||
|   also for formal equivalence checking, SAT solving, and for circuit analysis, to |   synthesis but also for formal equivalence checking, SAT solving, and for | ||||||
|   name just a few other application domains. With proprietary software one needs to |   circuit analysis, to name just a few other application domains. With | ||||||
|   learn a new tool for each of these applications. |   proprietary software one needs to learn a new tool for each of these | ||||||
|  |   applications. | ||||||
| 
 | 
 | ||||||
| - Educational Tool:  | - Educational Tool:  | ||||||
|    |    | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| furo | furo-ys @ git+https://github.com/YosysHQ/furo-ys | ||||||
| sphinxcontrib-bibtex | sphinxcontrib-bibtex | ||||||
| rtds-action | rtds-action | ||||||
|  |  | ||||||
|  | @ -13,9 +13,9 @@ A look at the show command | ||||||
| 
 | 
 | ||||||
| .. TODO:: merge into :doc:`/getting_started/scripting_intro` show section | .. TODO:: merge into :doc:`/getting_started/scripting_intro` show section | ||||||
| 
 | 
 | ||||||
| This section explores the :cmd:ref:`show` command and explains the symbols used | This section explores the `show` command and explains the symbols used in the | ||||||
| in the circuit diagrams generated by it. The code used is included in the Yosys | circuit diagrams generated by it. The code used is included in the Yosys code | ||||||
| code base under |code_examples/show|_. | base under |code_examples/show|_. | ||||||
| 
 | 
 | ||||||
| .. |code_examples/show| replace:: :file:`docs/source/code_examples/show` | .. |code_examples/show| replace:: :file:`docs/source/code_examples/show` | ||||||
| .. _code_examples/show: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/show | .. _code_examples/show: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/show | ||||||
|  | @ -24,7 +24,7 @@ A simple circuit | ||||||
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| :ref:`example_v` below provides the Verilog code for a simple circuit which we | :ref:`example_v` below provides the Verilog code for a simple circuit which we | ||||||
| will use to demonstrate the usage of :cmd:ref:`show` in a simple setting. | will use to demonstrate the usage of `show` in a simple setting. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/example.v | .. literalinclude:: /code_examples/show/example.v | ||||||
|    :language: Verilog |    :language: Verilog | ||||||
|  | @ -32,11 +32,10 @@ will use to demonstrate the usage of :cmd:ref:`show` in a simple setting. | ||||||
|    :name: example_v |    :name: example_v | ||||||
| 
 | 
 | ||||||
| The Yosys synthesis script we will be running is included as | The Yosys synthesis script we will be running is included as | ||||||
| :numref:`example_ys`. Note that :cmd:ref:`show` is called with the ``-pause`` | :numref:`example_ys`. Note that `show` is called with the ``-pause`` option, | ||||||
| option, that halts execution of the Yosys script until the user presses the | that halts execution of the Yosys script until the user presses the Enter key. | ||||||
| Enter key. Using :yoscrypt:`show -pause` also allows the user to enter an | Using :yoscrypt:`show -pause` also allows the user to enter an interactive shell | ||||||
| interactive shell to further investigate the circuit before continuing | to further investigate the circuit before continuing synthesis. | ||||||
| synthesis. |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/example_show.ys | .. literalinclude:: /code_examples/show/example_show.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -58,7 +57,7 @@ is shown. | ||||||
| .. figure:: /_images/code_examples/show/example_first.* | .. figure:: /_images/code_examples/show/example_first.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|     |     | ||||||
|    Output of the first :cmd:ref:`show` command in :numref:`example_ys` |    Output of the first `show` command in :numref:`example_ys` | ||||||
| 
 | 
 | ||||||
| The first output shows the design directly after being read by the Verilog | The first output shows the design directly after being read by the Verilog | ||||||
| front-end. Input and output ports are displayed as octagonal shapes. Cells are | front-end. Input and output ports are displayed as octagonal shapes. Cells are | ||||||
|  | @ -66,7 +65,7 @@ displayed as rectangles with inputs on the left and outputs on the right side. | ||||||
| The cell labels are two lines long: The first line contains a unique identifier | The cell labels are two lines long: The first line contains a unique identifier | ||||||
| for the cell and the second line contains the cell type. Internal cell types are | for the cell and the second line contains the cell type. Internal cell types are | ||||||
| prefixed with a dollar sign. For more details on the internal cell library, see | prefixed with a dollar sign. For more details on the internal cell library, see | ||||||
| :doc:`/yosys_internals/formats/cell_library`. | :doc:`/cell_index`. | ||||||
| 
 | 
 | ||||||
| Constants are shown as ellipses with the constant value as label. The syntax | Constants are shown as ellipses with the constant value as label. The syntax | ||||||
| ``<bit_width>'<bits>`` is used for constants that are not 32-bit wide and/or | ``<bit_width>'<bits>`` is used for constants that are not 32-bit wide and/or | ||||||
|  | @ -81,43 +80,43 @@ internal representation of the decision-trees and synchronization events | ||||||
| modelled in a Verilog ``always``-block. The label reads ``PROC`` followed by a | modelled in a Verilog ``always``-block. The label reads ``PROC`` followed by a | ||||||
| unique identifier in the first line and contains the source code location of the | unique identifier in the first line and contains the source code location of the | ||||||
| original ``always``-block in the second line. Note how the multiplexer from the | original ``always``-block in the second line. Note how the multiplexer from the | ||||||
| ``?:``-expression is represented as a ``$mux`` cell but the multiplexer from the | ``?:``-expression is represented as a `$mux` cell but the multiplexer from the | ||||||
| ``if``-statement is yet still hidden within the process. | ``if``-statement is yet still hidden within the process. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`proc` command transforms the process from the first diagram into a | The `proc` command transforms the process from the first diagram into a | ||||||
| multiplexer and a d-type flip-flop, which brings us to the second diagram: | multiplexer and a d-type flip-flop, which brings us to the second diagram: | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/show/example_second.* | .. figure:: /_images/code_examples/show/example_second.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|     |     | ||||||
|    Output of the second :cmd:ref:`show` command in :numref:`example_ys` |    Output of the second `show` command in :numref:`example_ys` | ||||||
| 
 | 
 | ||||||
| The Rhombus shape to the right is a dangling wire. (Wire nodes are only shown if | The Rhombus shape to the right is a dangling wire. (Wire nodes are only shown if | ||||||
| they are dangling or have "public" names, for example names assigned from the | they are dangling or have "public" names, for example names assigned from the | ||||||
| Verilog input.) Also note that the design now contains two instances of a | Verilog input.) Also note that the design now contains two instances of a | ||||||
| ``BUF``-node. These are artefacts left behind by the :cmd:ref:`proc` command. It | ``BUF``-node. These are artefacts left behind by the `proc` command. It is quite | ||||||
| is quite usual to see such artefacts after calling commands that perform changes | usual to see such artefacts after calling commands that perform changes in the | ||||||
| in the design, as most commands only care about doing the transformation in the | design, as most commands only care about doing the transformation in the least | ||||||
| least complicated way, not about cleaning up after them. The next call to | complicated way, not about cleaning up after them. The next call to `clean` (or | ||||||
| :cmd:ref:`clean` (or :cmd:ref:`opt`, which includes :cmd:ref:`clean` as one of | `opt`, which includes `clean` as one of its operations) will clean up these | ||||||
| its operations) will clean up these artefacts. This operation is so common in | artefacts. This operation is so common in Yosys scripts that it can simply be | ||||||
| Yosys scripts that it can simply be abbreviated with the ``;;`` token, which | abbreviated with the ``;;`` token, which doubles as separator for commands. | ||||||
| doubles as separator for commands. Unless one wants to specifically analyze this | Unless one wants to specifically analyze this artefacts left behind some | ||||||
| artefacts left behind some operations, it is therefore recommended to always | operations, it is therefore recommended to always call `clean` before calling | ||||||
| call :cmd:ref:`clean` before calling :cmd:ref:`show`. | `show`. | ||||||
| 
 | 
 | ||||||
| In this script we directly call :cmd:ref:`opt` as the next step, which finally | In this script we directly call `opt` as the next step, which finally leads us | ||||||
| leads us to the third diagram:  | to the third diagram:  | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/show/example_third.* | .. figure:: /_images/code_examples/show/example_third.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: example_out |    :name: example_out | ||||||
|     |     | ||||||
|    Output of the third :cmd:ref:`show` command in :ref:`example_ys` |    Output of the third `show` command in :ref:`example_ys` | ||||||
|     |     | ||||||
| Here we see that the :cmd:ref:`opt` command not only has removed the artifacts | Here we see that the `opt` command not only has removed the artifacts left | ||||||
| left behind by :cmd:ref:`proc`, but also determined correctly that it can remove | behind by `proc`, but also determined correctly that it can remove the first | ||||||
| the first ``$mux`` cell without changing the behavior of the circuit. | `$mux` cell without changing the behavior of the circuit. | ||||||
| 
 | 
 | ||||||
| Break-out boxes for signal vectors | Break-out boxes for signal vectors | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
|  | @ -129,7 +128,7 @@ accesses. | ||||||
|    :caption: :file:`splice.v` |    :caption: :file:`splice.v` | ||||||
|    :name: splice_src |    :name: splice_src | ||||||
| 
 | 
 | ||||||
| Notice how the output for this circuit from the :cmd:ref:`show` command | Notice how the output for this circuit from the `show` command | ||||||
| (:numref:`splice_dia`) appears quite complex. This is an unfortunate side effect | (:numref:`splice_dia`) appears quite complex. This is an unfortunate side effect | ||||||
| of the way Yosys handles signal vectors (aka. multi-bit wires or buses) as | of the way Yosys handles signal vectors (aka. multi-bit wires or buses) as | ||||||
| native objects. While this provides great advantages when analyzing circuits | native objects. While this provides great advantages when analyzing circuits | ||||||
|  | @ -169,7 +168,7 @@ mapped to a cell library: | ||||||
|    :name: first_pitfall |    :name: first_pitfall | ||||||
| 
 | 
 | ||||||
|    A half-adder built from simple CMOS gates, demonstrating common pitfalls when  |    A half-adder built from simple CMOS gates, demonstrating common pitfalls when  | ||||||
|    using :cmd:ref:`show` |    using `show` | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/cmos.ys | .. literalinclude:: /code_examples/show/cmos.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -188,8 +187,8 @@ individual bits, resulting in an unnecessary complex diagram. | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: second_pitfall |    :name: second_pitfall | ||||||
| 
 | 
 | ||||||
|    Effects of :cmd:ref:`splitnets` command and of providing a cell library on  |    Effects of `splitnets` command and of providing a cell library on design in | ||||||
|    design in :numref:`first_pitfall` |    :numref:`first_pitfall` | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/cmos.ys | .. literalinclude:: /code_examples/show/cmos.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -201,11 +200,11 @@ individual bits, resulting in an unnecessary complex diagram. | ||||||
| For :numref:`second_pitfall`, Yosys has been given a description of the cell | For :numref:`second_pitfall`, Yosys has been given a description of the cell | ||||||
| library as Verilog file containing blackbox modules. There are two ways to load | library as Verilog file containing blackbox modules. There are two ways to load | ||||||
| cell descriptions into Yosys: First the Verilog file for the cell library can be | cell descriptions into Yosys: First the Verilog file for the cell library can be | ||||||
| passed directly to the :cmd:ref:`show` command using the ``-lib <filename>`` | passed directly to the `show` command using the ``-lib <filename>`` option. | ||||||
| option. Secondly it is possible to load cell libraries into the design with the | Secondly it is possible to load cell libraries into the design with the | ||||||
| :yoscrypt:`read_verilog -lib <filename>` command. The second method has the | :yoscrypt:`read_verilog -lib <filename>` command. The second method has the | ||||||
| great advantage that the library only needs to be loaded once and can then be | great advantage that the library only needs to be loaded once and can then be | ||||||
| used in all subsequent calls to the :cmd:ref:`show` command. | used in all subsequent calls to the `show` command. | ||||||
| 
 | 
 | ||||||
| In addition to that, :numref:`second_pitfall` was generated after | In addition to that, :numref:`second_pitfall` was generated after | ||||||
| :yoscrypt:`splitnet -ports` was run on the design. This command splits all | :yoscrypt:`splitnet -ports` was run on the design. This command splits all | ||||||
|  | @ -216,22 +215,22 @@ module ports. Per default the command only operates on interior signals. | ||||||
| Miscellaneous notes | Miscellaneous notes | ||||||
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Per default the :cmd:ref:`show` command outputs a temporary dot file and | Per default the `show` command outputs a temporary dot file and launches | ||||||
| launches ``xdot`` to display it. The options ``-format``, ``-viewer`` and | ``xdot`` to display it. The options ``-format``, ``-viewer`` and ``-prefix`` can | ||||||
| ``-prefix`` can be used to change format, viewer and filename prefix. Note that | be used to change format, viewer and filename prefix. Note that the ``pdf`` and | ||||||
| the ``pdf`` and ``ps`` format are the only formats that support plotting | ``ps`` format are the only formats that support plotting multiple modules in one | ||||||
| multiple modules in one run.  The ``dot`` format can be used to output multiple | run.  The ``dot`` format can be used to output multiple modules, however | ||||||
| modules, however ``xdot`` will raise an error when trying to read them. | ``xdot`` will raise an error when trying to read them. | ||||||
| 
 | 
 | ||||||
| In densely connected circuits it is sometimes hard to keep track of the | In densely connected circuits it is sometimes hard to keep track of the | ||||||
| individual signal wires. For these cases it can be useful to call | individual signal wires. For these cases it can be useful to call `show` with | ||||||
| :cmd:ref:`show` with the ``-colors <integer>`` argument, which randomly assigns | the ``-colors <integer>`` argument, which randomly assigns colors to the nets. | ||||||
| colors to the nets. The integer (> 0) is used as seed value for the random color | The integer (> 0) is used as seed value for the random color assignments. | ||||||
| assignments. Sometimes it is necessary it try some values to find an assignment | Sometimes it is necessary it try some values to find an assignment of colors | ||||||
| of colors that looks good. | that looks good. | ||||||
| 
 | 
 | ||||||
| The command :yoscrypt:`help show` prints a complete listing of all options | The command :yoscrypt:`help show` prints a complete listing of all options | ||||||
| supported by the :cmd:ref:`show` command. | supported by the `show` command. | ||||||
| 
 | 
 | ||||||
| Navigating the design | Navigating the design | ||||||
| ~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -244,10 +243,10 @@ relevant portions of the circuit. | ||||||
| In addition to *what* to display one also needs to carefully decide *when* to | In addition to *what* to display one also needs to carefully decide *when* to | ||||||
| display it, with respect to the synthesis flow. In general it is a good idea to | display it, with respect to the synthesis flow. In general it is a good idea to | ||||||
| troubleshoot a circuit in the earliest state in which a problem can be | troubleshoot a circuit in the earliest state in which a problem can be | ||||||
| reproduced. So if, for example, the internal state before calling the | reproduced. So if, for example, the internal state before calling the `techmap` | ||||||
| :cmd:ref:`techmap` command already fails to verify, it is better to troubleshoot | command already fails to verify, it is better to troubleshoot the coarse-grain | ||||||
| the coarse-grain version of the circuit before :cmd:ref:`techmap` than the | version of the circuit before `techmap` than the gate-level circuit after | ||||||
| gate-level circuit after :cmd:ref:`techmap`. | `techmap`. | ||||||
| 
 | 
 | ||||||
| .. Note::  | .. Note::  | ||||||
| 
 | 
 | ||||||
|  | @ -260,31 +259,29 @@ Interactive navigation | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Once the right state within the synthesis flow for debugging the circuit has | Once the right state within the synthesis flow for debugging the circuit has | ||||||
| been identified, it is recommended to simply add the :cmd:ref:`shell` command to | been identified, it is recommended to simply add the `shell` command to the | ||||||
| the matching place in the synthesis script. This command will stop the synthesis | matching place in the synthesis script. This command will stop the synthesis at | ||||||
| at the specified moment and go to shell mode, where the user can interactively | the specified moment and go to shell mode, where the user can interactively | ||||||
| enter commands. | enter commands. | ||||||
| 
 | 
 | ||||||
| For most cases, the shell will start with the whole design selected (i.e. when | For most cases, the shell will start with the whole design selected (i.e. when | ||||||
| the synthesis script does not already narrow the selection). The command | the synthesis script does not already narrow the selection). The command `ls` | ||||||
| :cmd:ref:`ls` can now be used to create a list of all modules. The command | can now be used to create a list of all modules. The command `cd` can be used to | ||||||
| :cmd:ref:`cd` can be used to switch to one of the modules (type ``cd ..`` to | switch to one of the modules (type ``cd ..`` to switch back). Now the `ls` | ||||||
| switch back). Now the :cmd:ref:`ls` command lists the objects within that | command lists the objects within that module. This is demonstrated below using | ||||||
| module. This is demonstrated below using :file:`example.v` from `A simple | :file:`example.v` from `A simple circuit`_: | ||||||
| circuit`_: |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/example.out | .. literalinclude:: /code_examples/show/example.out | ||||||
|    :language: doscon |    :language: doscon | ||||||
|    :start-at: yosys> ls |    :start-at: yosys> ls | ||||||
|    :end-before: yosys [example]> dump |    :end-before: yosys [example]> dump | ||||||
|    :caption: Output of :cmd:ref:`ls` and :cmd:ref:`cd` after running :file:`yosys example.v` |    :caption: Output of `ls` and `cd` after running :file:`yosys example.v` | ||||||
|    :name: lscd |    :name: lscd | ||||||
| 
 | 
 | ||||||
| When a module is selected using the :cmd:ref:`cd` command, all commands (with a | When a module is selected using the `cd` command, all commands (with a few | ||||||
| few exceptions, such as the ``read_`` and ``write_`` commands) operate only on | exceptions, such as the ``read_`` and ``write_`` commands) operate only on the | ||||||
| the selected module. This can also be useful for synthesis scripts where | selected module. This can also be useful for synthesis scripts where different | ||||||
| different synthesis strategies should be applied to different modules in the | synthesis strategies should be applied to different modules in the design. | ||||||
| design. |  | ||||||
| 
 | 
 | ||||||
| We can see that the cell names from :numref:`example_out` are just abbreviations | We can see that the cell names from :numref:`example_out` are just abbreviations | ||||||
| of the actual cell names, namely the part after the last dollar-sign. Most | of the actual cell names, namely the part after the last dollar-sign. Most | ||||||
|  | @ -292,15 +289,14 @@ auto-generated names (the ones starting with a dollar sign) are rather long and | ||||||
| contains some additional information on the origin of the named object. But in | contains some additional information on the origin of the named object. But in | ||||||
| most cases those names can simply be abbreviated using the last part. | most cases those names can simply be abbreviated using the last part. | ||||||
| 
 | 
 | ||||||
| Usually all interactive work is done with one module selected using the | Usually all interactive work is done with one module selected using the `cd` | ||||||
| :cmd:ref:`cd` command. But it is also possible to work from the design-context | command. But it is also possible to work from the design-context (``cd ..``). In | ||||||
| (``cd ..``). In this case all object names must be prefixed with | this case all object names must be prefixed with ``<module_name>/``. For example | ||||||
| ``<module_name>/``. For example ``a*/b*`` would refer to all objects whose names | ``a*/b*`` would refer to all objects whose names start with ``b`` from all | ||||||
| start with ``b`` from all modules whose names start with ``a``. | modules whose names start with ``a``. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`dump` command can be used to print all information about an | The `dump` command can be used to print all information about an object. For | ||||||
| object. For example, calling :yoscrypt:`dump $2` after the :yoscrypt:`cd | example, calling :yoscrypt:`dump $2` after the :yoscrypt:`cd example` above: | ||||||
| example` above: |  | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/show/example.out | .. literalinclude:: /code_examples/show/example.out | ||||||
|    :language: RTLIL |    :language: RTLIL | ||||||
|  | @ -323,11 +319,10 @@ tools). | ||||||
| 
 | 
 | ||||||
| - The selection mechanism, especially patterns such as ``%ci`` and ``%co``, can | - The selection mechanism, especially patterns such as ``%ci`` and ``%co``, can | ||||||
|   be used to figure out how parts of the design are connected. |   be used to figure out how parts of the design are connected. | ||||||
| - Commands such as :cmd:ref:`submod`, :cmd:ref:`expose`, and :cmd:ref:`splice` | - Commands such as `submod`, `expose`, and `splice` can be used to transform the | ||||||
|   can be used to transform the design into an equivalent design that is easier |   design into an equivalent design that is easier to analyse. | ||||||
|   to analyse. | - Commands such as `eval` and `sat` can be used to investigate the behavior of | ||||||
| - Commands such as :cmd:ref:`eval` and :cmd:ref:`sat` can be used to investigate |   the circuit. | ||||||
|   the behavior of the circuit. |  | ||||||
| - :doc:`/cmd/show`. | - :doc:`/cmd/show`. | ||||||
| - :doc:`/cmd/dump`. | - :doc:`/cmd/dump`. | ||||||
| - :doc:`/cmd/add` and :doc:`/cmd/delete` can be used to modify and reorganize a | - :doc:`/cmd/add` and :doc:`/cmd/delete` can be used to modify and reorganize a | ||||||
|  | @ -342,10 +337,10 @@ The code used is included in the Yosys code base under | ||||||
| Changing design hierarchy | Changing design hierarchy | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Commands such as :cmd:ref:`flatten` and :cmd:ref:`submod` can be used to change | Commands such as `flatten` and `submod` can be used to change the design | ||||||
| the design hierarchy, i.e. flatten the hierarchy or moving parts of a module to | hierarchy, i.e. flatten the hierarchy or moving parts of a module to a | ||||||
| a submodule. This has applications in synthesis scripts as well as in reverse | submodule. This has applications in synthesis scripts as well as in reverse | ||||||
| engineering and analysis.  An example using :cmd:ref:`submod` is shown below for | engineering and analysis.  An example using `submod` is shown below for | ||||||
| reorganizing a module in Yosys and checking the resulting circuit. | reorganizing a module in Yosys and checking the resulting circuit. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/scrambler/scrambler.v | .. literalinclude:: /code_examples/scrambler/scrambler.v | ||||||
|  | @ -388,10 +383,10 @@ Analyzing the resulting circuit with :doc:`/cmd/eval`: | ||||||
| Behavioral changes | Behavioral changes | ||||||
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Commands such as :cmd:ref:`techmap` can be used to make behavioral changes to | Commands such as `techmap` can be used to make behavioral changes to the design, | ||||||
| the design, for example changing asynchronous resets to synchronous resets. This | for example changing asynchronous resets to synchronous resets. This has | ||||||
| has applications in design space exploration (evaluation of various | applications in design space exploration (evaluation of various architectures | ||||||
| architectures for one circuit). | for one circuit). | ||||||
| 
 | 
 | ||||||
| The following techmap map file replaces all positive-edge async reset flip-flops | The following techmap map file replaces all positive-edge async reset flip-flops | ||||||
| with positive-edge sync reset flip-flops. The code is taken from the example | with positive-edge sync reset flip-flops. The code is taken from the example | ||||||
|  | @ -425,7 +420,7 @@ Yosys script for ASIC synthesis of the Amber ARMv2 CPU. | ||||||
| 
 | 
 | ||||||
|     endmodule |     endmodule | ||||||
| 
 | 
 | ||||||
| For more on the :cmd:ref:`techmap` command, see the page on | For more on the `techmap` command, see the page on | ||||||
| :doc:`/yosys_internals/techmap`. | :doc:`/yosys_internals/techmap`. | ||||||
| 
 | 
 | ||||||
| Advanced investigation techniques | Advanced investigation techniques | ||||||
|  | @ -448,12 +443,12 @@ Recall the ``memdemo`` design from :ref:`advanced_logic_cones`: | ||||||
| 
 | 
 | ||||||
| Because this produces a rather large circuit, it can be useful to split it into | Because this produces a rather large circuit, it can be useful to split it into | ||||||
| smaller parts for viewing and working with.  :numref:`submod` does exactly that, | smaller parts for viewing and working with.  :numref:`submod` does exactly that, | ||||||
| utilising the :cmd:ref:`submod` command to split the circuit into three | utilising the `submod` command to split the circuit into three sections: | ||||||
| sections: ``outstage``, ``selstage``, and ``scramble``. | ``outstage``, ``selstage``, and ``scramble``. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/selections/submod.ys | .. literalinclude:: /code_examples/selections/submod.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|    :caption: Using :cmd:ref:`submod` to break up the circuit from :file:`memdemo.v` |    :caption: Using `submod` to break up the circuit from :file:`memdemo.v` | ||||||
|    :start-after: cd memdemo |    :start-after: cd memdemo | ||||||
|    :end-before: cd .. |    :end-before: cd .. | ||||||
|    :name: submod |    :name: submod | ||||||
|  | @ -481,9 +476,9 @@ below. | ||||||
| Evaluation of combinatorial circuits | Evaluation of combinatorial circuits | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`eval` command can be used to evaluate combinatorial circuits. As | The `eval` command can be used to evaluate combinatorial circuits. As an | ||||||
| an example, we will use the ``selstage`` subnet of ``memdemo`` which we found | example, we will use the ``selstage`` subnet of ``memdemo`` which we found above | ||||||
| above and is shown in :numref:`selstage`. | and is shown in :numref:`selstage`. | ||||||
| 
 | 
 | ||||||
| .. todo:: replace inline code | .. todo:: replace inline code | ||||||
| 
 | 
 | ||||||
|  | @ -526,21 +521,21 @@ The ``-table`` option can be used to create a truth table. For example: | ||||||
| 
 | 
 | ||||||
|       Assumed undef (x) value for the following signals: \s2 |       Assumed undef (x) value for the following signals: \s2 | ||||||
| 
 | 
 | ||||||
| Note that the :cmd:ref:`eval` command (as well as the :cmd:ref:`sat` command | Note that the `eval` command (as well as the `sat` command discussed in the next | ||||||
| discussed in the next sections) does only operate on flattened modules. It can | sections) does only operate on flattened modules. It can not analyze signals | ||||||
| not analyze signals that are passed through design hierarchy levels. So the | that are passed through design hierarchy levels. So the `flatten` command must | ||||||
| :cmd:ref:`flatten` command must be used on modules that instantiate other | be used on modules that instantiate other modules before these commands can be | ||||||
| modules before these commands can be applied. | applied. | ||||||
| 
 | 
 | ||||||
| Solving combinatorial SAT problems | Solving combinatorial SAT problems | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Often the opposite of the :cmd:ref:`eval` command is needed, i.e. the circuits | Often the opposite of the `eval` command is needed, i.e. the circuits output is | ||||||
| output is given and we want to find the matching input signals. For small | given and we want to find the matching input signals. For small circuits with | ||||||
| circuits with only a few input bits this can be accomplished by trying all | only a few input bits this can be accomplished by trying all possible input | ||||||
| possible input combinations, as it is done by the ``eval -table`` command. For | combinations, as it is done by the ``eval -table`` command. For larger circuits | ||||||
| larger circuits however, Yosys provides the :cmd:ref:`sat` command that uses a | however, Yosys provides the `sat` command that uses a `SAT`_ solver, `MiniSAT`_, | ||||||
| `SAT`_ solver, `MiniSAT`_, to solve this kind of problems. | to solve this kind of problems. | ||||||
| 
 | 
 | ||||||
| .. _SAT: http://en.wikipedia.org/wiki/Circuit_satisfiability | .. _SAT: http://en.wikipedia.org/wiki/Circuit_satisfiability | ||||||
| 
 | 
 | ||||||
|  | @ -551,9 +546,9 @@ larger circuits however, Yosys provides the :cmd:ref:`sat` command that uses a | ||||||
|     While it is possible to perform model checking directly in Yosys, it  |     While it is possible to perform model checking directly in Yosys, it  | ||||||
|     is highly recommended to use SBY or EQY for formal hardware verification. |     is highly recommended to use SBY or EQY for formal hardware verification. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`sat` command works very similar to the :cmd:ref:`eval` command. | The `sat` command works very similar to the `eval` command. The main difference | ||||||
| The main difference is that it is now also possible to set output values and | is that it is now also possible to set output values and find the corresponding | ||||||
| find the corresponding input values. For Example: | input values. For Example: | ||||||
| 
 | 
 | ||||||
| .. todo:: replace inline code | .. todo:: replace inline code | ||||||
| 
 | 
 | ||||||
|  | @ -580,8 +575,8 @@ find the corresponding input values. For Example: | ||||||
|         \s1                           0          0              00 |         \s1                           0          0              00 | ||||||
|         \s2                           0          0              00 |         \s2                           0          0              00 | ||||||
| 
 | 
 | ||||||
| Note that the :cmd:ref:`sat` command supports signal names in both arguments to | Note that the `sat` command supports signal names in both arguments to the | ||||||
| the ``-set`` option. In the above example we used ``-set s1 s2`` to constraint | ``-set`` option. In the above example we used ``-set s1 s2`` to constraint | ||||||
| ``s1`` and ``s2`` to be equal. When more complex constraints are needed, a | ``s1`` and ``s2`` to be equal. When more complex constraints are needed, a | ||||||
| wrapper circuit must be constructed that checks the constraints and signals if | wrapper circuit must be constructed that checks the constraints and signals if | ||||||
| the constraint was met using an extra output port, which then can be forced to a | the constraint was met using an extra output port, which then can be forced to a | ||||||
|  | @ -642,8 +637,8 @@ of course be to perform the test in 32 bits, for example by replacing ``p != | ||||||
| a*b`` in the miter with ``p != {16'd0,a}b``, or by using a temporary variable | a*b`` in the miter with ``p != {16'd0,a}b``, or by using a temporary variable | ||||||
| for the 32 bit product ``a*b``. But as 31 fits well into 8 bits (and as the | for the 32 bit product ``a*b``. But as 31 fits well into 8 bits (and as the | ||||||
| purpose of this document is to show off Yosys features) we can also simply force | purpose of this document is to show off Yosys features) we can also simply force | ||||||
| the upper 8 bits of ``a`` and ``b`` to zero for the :cmd:ref:`sat` call, as is | the upper 8 bits of ``a`` and ``b`` to zero for the `sat` call, as is done | ||||||
| done below. | below. | ||||||
| 
 | 
 | ||||||
| .. todo:: replace inline code | .. todo:: replace inline code | ||||||
| 
 | 
 | ||||||
|  | @ -705,18 +700,18 @@ command: | ||||||
|       sat -seq 6 -show y -show d -set-init-undef \ |       sat -seq 6 -show y -show d -set-init-undef \ | ||||||
|         -max_undef -set-at 4 y 1 -set-at 5 y 2 -set-at 6 y 3 |         -max_undef -set-at 4 y 1 -set-at 5 y 2 -set-at 6 y 3 | ||||||
| 
 | 
 | ||||||
| The ``-seq 6`` option instructs the :cmd:ref:`sat` command to solve a sequential | The ``-seq 6`` option instructs the `sat` command to solve a sequential problem | ||||||
| problem in 6 time steps. (Experiments with lower number of steps have show that | in 6 time steps. (Experiments with lower number of steps have show that at least | ||||||
| at least 3 cycles are necessary to bring the circuit in a state from which the | 3 cycles are necessary to bring the circuit in a state from which the sequence | ||||||
| sequence 1, 2, 3 can be produced.) | 1, 2, 3 can be produced.) | ||||||
| 
 | 
 | ||||||
| The ``-set-init-undef`` option tells the :cmd:ref:`sat` command to initialize | The ``-set-init-undef`` option tells the `sat` command to initialize all | ||||||
| all registers to the undef (``x``) state. The way the ``x`` state is treated in | registers to the undef (``x``) state. The way the ``x`` state is treated in | ||||||
| Verilog will ensure that the solution will work for any initial state. | Verilog will ensure that the solution will work for any initial state. | ||||||
| 
 | 
 | ||||||
| The ``-max_undef`` option instructs the :cmd:ref:`sat` command to find a | The ``-max_undef`` option instructs the `sat` command to find a solution with a | ||||||
| solution with a maximum number of undefs. This way we can see clearly which | maximum number of undefs. This way we can see clearly which inputs bits are | ||||||
| inputs bits are relevant to the solution. | relevant to the solution. | ||||||
| 
 | 
 | ||||||
| Finally the three ``-set-at`` options add constraints for the ``y`` signal to | Finally the three ``-set-at`` options add constraints for the ``y`` signal to | ||||||
| play the 1, 2, 3 sequence, starting with time step 4. | play the 1, 2, 3 sequence, starting with time step 4. | ||||||
|  | @ -807,7 +802,7 @@ is the only way of setting the ``s1`` and ``s2`` registers to a known value. The | ||||||
| input values for the other steps are a bit harder to work out manually, but the | input values for the other steps are a bit harder to work out manually, but the | ||||||
| SAT solver finds the correct solution in an instant. | SAT solver finds the correct solution in an instant. | ||||||
| 
 | 
 | ||||||
| There is much more to write about the :cmd:ref:`sat` command. For example, there | There is much more to write about the `sat` command. For example, there is a set | ||||||
| is a set of options that can be used to performs sequential proofs using | of options that can be used to performs sequential proofs using temporal | ||||||
| temporal induction :cite:p:`een2003temporal`. The command ``help sat`` can be | induction :cite:p:`een2003temporal`. The command ``help sat`` can be used to | ||||||
| used to print a list of all options with short descriptions of their functions. | print a list of all options with short descriptions of their functions. | ||||||
|  |  | ||||||
|  | @ -17,8 +17,7 @@ passes in Yosys. | ||||||
| 
 | 
 | ||||||
| Other applications include checking if a module conforms to interface standards. | Other applications include checking if a module conforms to interface standards. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`sat` command in Yosys can be used to perform Symbolic Model | The `sat` command in Yosys can be used to perform Symbolic Model Checking. | ||||||
| Checking. |  | ||||||
| 
 | 
 | ||||||
| Checking techmap | Checking techmap | ||||||
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | @ -9,33 +9,33 @@ The selection framework | ||||||
| 
 | 
 | ||||||
| .. todo:: reduce overlap with :doc:`/getting_started/scripting_intro` select section | .. todo:: reduce overlap with :doc:`/getting_started/scripting_intro` select section | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`select` command can be used to create a selection for subsequent | The `select` command can be used to create a selection for subsequent commands. | ||||||
| commands. For example: | For example: | ||||||
| 
 | 
 | ||||||
| .. code:: yoscrypt | .. code:: yoscrypt | ||||||
| 
 | 
 | ||||||
|     select foobar         # select the module foobar |     select foobar         # select the module foobar | ||||||
|     delete                # delete selected objects |     delete                # delete selected objects | ||||||
| 
 | 
 | ||||||
| Normally the :cmd:ref:`select` command overwrites a previous selection. The | Normally the `select` command overwrites a previous selection. The commands | ||||||
| commands :yoscrypt:`select -add` and :yoscrypt:`select -del` can be used to add | :yoscrypt:`select -add` and :yoscrypt:`select -del` can be used to add or remove | ||||||
| or remove objects from the current selection. | objects from the current selection. | ||||||
| 
 | 
 | ||||||
| The command :yoscrypt:`select -clear` can be used to reset the selection to the | The command :yoscrypt:`select -clear` can be used to reset the selection to the | ||||||
| default, which is a complete selection of everything in the current module. | default, which is a complete selection of everything in the current module. | ||||||
| 
 | 
 | ||||||
| This selection framework can also be used directly in many other commands. | This selection framework can also be used directly in many other commands. | ||||||
| Whenever a command has ``[selection]`` as last argument in its usage help, this | Whenever a command has ``[selection]`` as last argument in its usage help, this | ||||||
| means that it will use the engine behind the :cmd:ref:`select` command to | means that it will use the engine behind the `select` command to evaluate | ||||||
| evaluate additional arguments and use the resulting selection instead of the | additional arguments and use the resulting selection instead of the selection | ||||||
| selection created by the last :cmd:ref:`select` command. | created by the last `select` command. | ||||||
| 
 | 
 | ||||||
| For example, the command :cmd:ref:`delete` will delete everything in the current | For example, the command `delete` will delete everything in the current | ||||||
| selection; while :yoscrypt:`delete foobar` will only delete the module foobar. | selection; while :yoscrypt:`delete foobar` will only delete the module foobar. | ||||||
| If no :cmd:ref:`select` command has been made, then the "current selection" will | If no `select` command has been made, then the "current selection" will be the | ||||||
| be the whole design. | whole design. | ||||||
| 
 | 
 | ||||||
| .. note:: Many of the examples on this page make use of the :cmd:ref:`show`  | .. note:: Many of the examples on this page make use of the `show`  | ||||||
|    command to visually demonstrate the effect of selections.  For a more  |    command to visually demonstrate the effect of selections.  For a more  | ||||||
|    detailed look at this command, refer to :ref:`interactive_show`. |    detailed look at this command, refer to :ref:`interactive_show`. | ||||||
| 
 | 
 | ||||||
|  | @ -59,8 +59,8 @@ Module and design context | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| Commands can be executed in *module/* or *design/* context. Until now, all | Commands can be executed in *module/* or *design/* context. Until now, all | ||||||
| commands have been executed in design context. The :cmd:ref:`cd` command can be | commands have been executed in design context. The `cd` command can be used to | ||||||
| used to switch to module context. | switch to module context. | ||||||
| 
 | 
 | ||||||
| In module context, all commands only effect the active module. Objects in the | In module context, all commands only effect the active module. Objects in the | ||||||
| module are selected without the ``<module_name>/`` prefix. For example: | module are selected without the ``<module_name>/`` prefix. For example: | ||||||
|  | @ -91,7 +91,7 @@ Special patterns can be used to select by object property or type. For example: | ||||||
|   a:foobar=42` |   a:foobar=42` | ||||||
| - select all modules with the attribute ``blabla`` set: :yoscrypt:`select | - select all modules with the attribute ``blabla`` set: :yoscrypt:`select | ||||||
|   A:blabla` |   A:blabla` | ||||||
| - select all $add cells from the module foo: :yoscrypt:`select foo/t:$add` | - select all `$add` cells from the module foo: :yoscrypt:`select foo/t:$add` | ||||||
| 
 | 
 | ||||||
| A complete list of pattern expressions can be found in :doc:`/cmd/select`. | A complete list of pattern expressions can be found in :doc:`/cmd/select`. | ||||||
| 
 | 
 | ||||||
|  | @ -101,12 +101,12 @@ Operations on selections | ||||||
| Combining selections | Combining selections | ||||||
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`select` command is actually much more powerful than it might seem | The `select` command is actually much more powerful than it might seem at first | ||||||
| at first glance. When it is called with multiple arguments, each argument is | glance. When it is called with multiple arguments, each argument is evaluated | ||||||
| evaluated and pushed separately on a stack. After all arguments have been | and pushed separately on a stack. After all arguments have been processed it | ||||||
| processed it simply creates the union of all elements on the stack. So | simply creates the union of all elements on the stack. So :yoscrypt:`select | ||||||
| :yoscrypt:`select t:$add a:foo` will select all ``$add`` cells and all objects | t:$add a:foo` will select all `$add` cells and all objects with the ``foo`` | ||||||
| with the ``foo`` attribute set:    | attribute set:    | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/selections/foobaraddsub.v | .. literalinclude:: /code_examples/selections/foobaraddsub.v | ||||||
|    :caption: Test module for operations on selections |    :caption: Test module for operations on selections | ||||||
|  | @ -126,7 +126,7 @@ ineffective way of selecting the interesting part of the design. Special | ||||||
| arguments can be used to combine the elements on the stack. For example the | arguments can be used to combine the elements on the stack. For example the | ||||||
| ``%i`` arguments pops the last two elements from the stack, intersects them, and | ``%i`` arguments pops the last two elements from the stack, intersects them, and | ||||||
| pushes the result back on the stack. So :yoscrypt:`select t:$add a:foo %i` will | pushes the result back on the stack. So :yoscrypt:`select t:$add a:foo %i` will | ||||||
| select all ``$add`` cells that have the ``foo`` attribute set: | select all `$add` cells that have the ``foo`` attribute set: | ||||||
| 
 | 
 | ||||||
| .. code-block:: | .. code-block:: | ||||||
|    :caption: Output for command ``select t:$add a:foo %i -list`` on :numref:`foobaraddsub` |    :caption: Output for command ``select t:$add a:foo %i -list`` on :numref:`foobaraddsub` | ||||||
|  | @ -190,7 +190,7 @@ Selecting logic cones | ||||||
| :numref:`sumprod_01` shows what is called the ``input cone`` of ``sum``, i.e. | :numref:`sumprod_01` shows what is called the ``input cone`` of ``sum``, i.e. | ||||||
| all cells and signals that are used to generate the signal ``sum``. The ``%ci`` | all cells and signals that are used to generate the signal ``sum``. The ``%ci`` | ||||||
| action can be used to select the input cones of all object in the top selection | action can be used to select the input cones of all object in the top selection | ||||||
| in the stack maintained by the :cmd:ref:`select` command. | in the stack maintained by the `select` command. | ||||||
| 
 | 
 | ||||||
| As with the ``%x`` action, these commands broaden the selection by one "step". | As with the ``%x`` action, these commands broaden the selection by one "step". | ||||||
| But this time the operation only works against the direction of data flow. That | But this time the operation only works against the direction of data flow. That | ||||||
|  | @ -220,11 +220,11 @@ The following sequence of diagrams demonstrates this step-wise expansion: | ||||||
|    Output of :yoscrypt:`show prod %ci %ci %ci` on :numref:`sumprod` |    Output of :yoscrypt:`show prod %ci %ci %ci` on :numref:`sumprod` | ||||||
| 
 | 
 | ||||||
| Notice the subtle difference between :yoscrypt:`show prod %ci` and | Notice the subtle difference between :yoscrypt:`show prod %ci` and | ||||||
| :yoscrypt:`show prod %ci %ci`.  Both images show the ``$mul`` cell driven by | :yoscrypt:`show prod %ci %ci`.  Both images show the `$mul` cell driven by some | ||||||
| some inputs ``$3_Y`` and ``c``.  However it is not until the second image, | inputs ``$3_Y`` and ``c``.  However it is not until the second image, having | ||||||
| having called ``%ci`` the second time, that :cmd:ref:`show` is able to | called ``%ci`` the second time, that `show` is able to distinguish between | ||||||
| distinguish between ``$3_Y`` being a wire and ``c`` being an input.  We can see | ``$3_Y`` being a wire and ``c`` being an input.  We can see this better with the | ||||||
| this better with the :cmd:ref:`dump` command instead: | `dump` command instead: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/selections/sumprod.out | .. literalinclude:: /code_examples/selections/sumprod.out | ||||||
|    :language: RTLIL |    :language: RTLIL | ||||||
|  | @ -241,8 +241,8 @@ 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 | appended to the action. So for example the action ``%ci3`` is identical to | ||||||
| performing the ``%ci`` action three times. | 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 | ||||||
| has no effect anymore. | no effect anymore. | ||||||
| 
 | 
 | ||||||
| .. _advanced_logic_cones: | .. _advanced_logic_cones: | ||||||
| 
 | 
 | ||||||
|  | @ -264,8 +264,8 @@ source repository. | ||||||
|    :name: memdemo_src |    :name: memdemo_src | ||||||
|    :language: verilog |    :language: verilog | ||||||
| 
 | 
 | ||||||
| The script :file:`memdemo.ys` is used to generate the images included here. Let's | The script :file:`memdemo.ys` is used to generate the images included here. | ||||||
| look at the first section: | Let's look at the first section: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/selections/memdemo.ys | .. literalinclude:: /code_examples/selections/memdemo.ys | ||||||
|    :caption: Synthesizing :ref:`memdemo_src` |    :caption: Synthesizing :ref:`memdemo_src` | ||||||
|  | @ -276,8 +276,8 @@ look at the first section: | ||||||
| This loads :numref:`memdemo_src` and synthesizes the included module. Note that | This loads :numref:`memdemo_src` and synthesizes the included module. Note that | ||||||
| this code can be copied and run directly in a Yosys command line session, | this code can be copied and run directly in a Yosys command line session, | ||||||
| provided :file:`memdemo.v` is in the same directory. We can now change to the | provided :file:`memdemo.v` is in the same directory. We can now change to the | ||||||
| ``memdemo`` module with ``cd memdemo``, and call :cmd:ref:`show` to see the | ``memdemo`` module with ``cd memdemo``, and call `show` to see the diagram in | ||||||
| diagram in :numref:`memdemo_00`. | :numref:`memdemo_00`. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/selections/memdemo_00.* | .. figure:: /_images/code_examples/selections/memdemo_00.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|  | @ -296,7 +296,7 @@ cones`_ from above, we can use :yoscrypt:`show y %ci2`: | ||||||
|     |     | ||||||
|    Output of :yoscrypt:`show y %ci2` |    Output of :yoscrypt:`show y %ci2` | ||||||
| 
 | 
 | ||||||
| From this we would learn that ``y`` is driven by a ``$dff cell``, that ``y`` is | From this we would learn that ``y`` is driven by a `$dff` cell, that ``y`` is | ||||||
| connected to the output port ``Q``, that the ``clk`` signal goes into the | connected to the output port ``Q``, that the ``clk`` signal goes into the | ||||||
| ``CLK`` input port of the cell, and that the data comes from an auto-generated | ``CLK`` input port of the cell, and that the data comes from an auto-generated | ||||||
| wire into the input ``D`` of the flip-flop cell (indicated by the ``$`` at the | wire into the input ``D`` of the flip-flop cell (indicated by the ``$`` at the | ||||||
|  | @ -313,7 +313,7 @@ inputs. To add a pattern we add a colon followed by the pattern to the ``%ci`` | ||||||
| action. The pattern itself starts with ``-`` or ``+``, indicating if it is an | action. The pattern itself starts with ``-`` or ``+``, indicating if it is an | ||||||
| include or exclude pattern, followed by an optional comma separated list of cell | include or exclude pattern, followed by an optional comma separated list of cell | ||||||
| types, followed by an optional comma separated list of port names in square | types, followed by an optional comma separated list of port names in square | ||||||
| brackets.  In this case, we want to exclude the ``S`` port of the ``$mux`` cell | brackets.  In this case, we want to exclude the ``S`` port of the `$mux` cell | ||||||
| type with :yoscrypt:`show y %ci5:-$mux[S]`: | type with :yoscrypt:`show y %ci5:-$mux[S]`: | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/selections/memdemo_03.* | .. figure:: /_images/code_examples/selections/memdemo_03.* | ||||||
|  | @ -334,7 +334,7 @@ multiplexer select inputs and flip-flop cells: | ||||||
|    Output of ``show y %ci2:+$dff[Q,D] %ci*:-$mux[S]:-$dff`` |    Output of ``show y %ci2:+$dff[Q,D] %ci*:-$mux[S]:-$dff`` | ||||||
| 
 | 
 | ||||||
| Or we could use :yoscrypt:`show y %ci*:-[CLK,S]:+$dff:+$mux` instead, following | Or we could use :yoscrypt:`show y %ci*:-[CLK,S]:+$dff:+$mux` instead, following | ||||||
| the input cone all the way but only following ``$dff`` and ``$mux`` cells, and | the input cone all the way but only following `$dff` and `$mux` cells, and | ||||||
| ignoring any ports named ``CLK`` or ``S``: | ignoring any ports named ``CLK`` or ``S``: | ||||||
| 
 | 
 | ||||||
| .. TODO:: pending discussion on whether rule ordering is a bug or a feature | .. TODO:: pending discussion on whether rule ordering is a bug or a feature | ||||||
|  | @ -371,8 +371,8 @@ selection instead of overwriting it. | ||||||
|     select -del reg_42      # but not this one |     select -del reg_42      # but not this one | ||||||
|     select -add state %ci   # and add more stuff |     select -add state %ci   # and add more stuff | ||||||
| 
 | 
 | ||||||
| Within a select expression the token ``%`` can be used to push the previous selection | Within a select expression the token ``%`` can be used to push the previous | ||||||
| on the stack. | selection on the stack. | ||||||
| 
 | 
 | ||||||
| .. code:: yoscrypt | .. code:: yoscrypt | ||||||
| 
 | 
 | ||||||
|  | @ -387,16 +387,16 @@ Storing and recalling selections | ||||||
| The current selection can be stored in memory with the command ``select -set | The current selection can be stored in memory with the command ``select -set | ||||||
| <name>``. It can later be recalled using ``select @<name>``. In fact, the | <name>``. It can later be recalled using ``select @<name>``. In fact, the | ||||||
| ``@<name>`` expression pushes the stored selection on the stack maintained by | ``@<name>`` expression pushes the stored selection on the stack maintained by | ||||||
| the :cmd:ref:`select` command. So for example :yoscrypt:`select @foo @bar %i` | the `select` command. So for example :yoscrypt:`select @foo @bar %i` will select | ||||||
| will select the intersection between the stored selections ``foo`` and ``bar``. | the intersection between the stored selections ``foo`` and ``bar``. | ||||||
| 
 | 
 | ||||||
| In larger investigation efforts it is highly recommended to maintain a script | In larger investigation efforts it is highly recommended to maintain a script | ||||||
| that sets up relevant selections, so they can easily be recalled, for example | that sets up relevant selections, so they can easily be recalled, for example | ||||||
| when Yosys needs to be re-run after a design or source code change. | when Yosys needs to be re-run after a design or source code change. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`history` command can be used to list all recent interactive | The `history` command can be used to list all recent interactive commands. This | ||||||
| commands. This feature can be useful for creating such a script from the | feature can be useful for creating such a script from the commands used in an | ||||||
| commands used in an interactive session. | interactive session. | ||||||
| 
 | 
 | ||||||
| Remember that select expressions can also be used directly as arguments to most | Remember that select expressions can also be used directly as arguments to most | ||||||
| commands. Some commands also accept a single select argument to some options. In | commands. Some commands also accept a single select argument to some options. In | ||||||
|  |  | ||||||
|  | @ -10,20 +10,19 @@ fine-grained optimisation and LUT mapping. | ||||||
| Yosys has two different commands, which both use this logic toolbox, but use it | Yosys has two different commands, which both use this logic toolbox, but use it | ||||||
| in different ways. | in different ways. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`abc` pass can be used for both ASIC (e.g. :yoscrypt:`abc | The `abc` pass can be used for both ASIC (e.g. :yoscrypt:`abc -liberty`) and | ||||||
| -liberty`) and FPGA (:yoscrypt:`abc -lut`) mapping, but this page will focus on | FPGA (:yoscrypt:`abc -lut`) mapping, but this page will focus on FPGA mapping. | ||||||
| FPGA mapping. |  | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`abc9` pass generally provides superior mapping quality due to | The `abc9` pass generally provides superior mapping quality due to being aware | ||||||
| being aware of combination boxes and DFF and LUT timings, giving it a more | of combination boxes and DFF and LUT timings, giving it a more global view of | ||||||
| global view of the mapping problem. | the mapping problem. | ||||||
| 
 | 
 | ||||||
| .. _ABC: https://github.com/berkeley-abc/abc | .. _ABC: https://github.com/berkeley-abc/abc | ||||||
| 
 | 
 | ||||||
| ABC: the unit delay model, simple and efficient | ABC: the unit delay model, simple and efficient | ||||||
| ----------------------------------------------- | ----------------------------------------------- | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`abc` pass uses a highly simplified view of an FPGA: | The `abc` pass uses a highly simplified view of an FPGA: | ||||||
| 
 | 
 | ||||||
| - An FPGA is made up of a network of inputs that connect through LUTs to a | - An FPGA is made up of a network of inputs that connect through LUTs to a | ||||||
|   network of outputs. These inputs may actually be I/O pins, D flip-flops, |   network of outputs. These inputs may actually be I/O pins, D flip-flops, | ||||||
|  | @ -126,7 +125,7 @@ guide to the syntax: | ||||||
| 
 | 
 | ||||||
| By convention, all delays in ``specify`` blocks are in integer picoseconds. | By convention, all delays in ``specify`` blocks are in integer picoseconds. | ||||||
| Files containing ``specify`` blocks should be read with the ``-specify`` option | Files containing ``specify`` blocks should be read with the ``-specify`` option | ||||||
| to :cmd:ref:`read_verilog` so that they aren't skipped. | to `read_verilog` so that they aren't skipped. | ||||||
| 
 | 
 | ||||||
| LUTs | LUTs | ||||||
| ^^^^ | ^^^^ | ||||||
|  | @ -145,9 +144,9 @@ DFFs | ||||||
| 
 | 
 | ||||||
| DFFs should be annotated with an ``(* abc9_flop *)`` attribute, however ABC9 has | DFFs should be annotated with an ``(* abc9_flop *)`` attribute, however ABC9 has | ||||||
| some specific requirements for this to be valid: - the DFF must initialise to | some specific requirements for this to be valid: - the DFF must initialise to | ||||||
| zero (consider using :cmd:ref:`dfflegalize` to ensure this). - the DFF cannot | zero (consider using `dfflegalize` to ensure this). - the DFF cannot have any | ||||||
| have any asynchronous resets/sets (see the simplification idiom and the Boxes | asynchronous resets/sets (see the simplification idiom and the Boxes section for | ||||||
| section for what to do here). | what to do here). | ||||||
| 
 | 
 | ||||||
| It is worth noting that in pure ``abc9`` mode, only the setup and arrival times | It is worth noting that in pure ``abc9`` mode, only the setup and arrival times | ||||||
| are passed to ABC9 (specifically, they are modelled as buffers with the given | are passed to ABC9 (specifically, they are modelled as buffers with the given | ||||||
|  | @ -158,9 +157,9 @@ Some vendors have universal DFF models which include async sets/resets even when | ||||||
| they're unused. Therefore *the simplification idiom* exists to handle this: by | they're unused. Therefore *the simplification idiom* exists to handle this: by | ||||||
| using a ``techmap`` file to discover flops which have a constant driver to those | using a ``techmap`` file to discover flops which have a constant driver to those | ||||||
| asynchronous controls, they can be mapped into an intermediate, simplified flop | asynchronous controls, they can be mapped into an intermediate, simplified flop | ||||||
| which qualifies as an ``(* abc9_flop *)``, ran through :cmd:ref:`abc9`, and then | which qualifies as an ``(* abc9_flop *)``, ran through `abc9`, and then mapped | ||||||
| mapped back to the original flop. This is used in :cmd:ref:`synth_intel_alm` and | back to the original flop. This is used in `synth_intel_alm` and | ||||||
| :cmd:ref:`synth_quicklogic` for the PolarPro3. | `synth_quicklogic` for the PolarPro3. | ||||||
| 
 | 
 | ||||||
| DFFs are usually specified to have setup constraints against the clock on the | DFFs are usually specified to have setup constraints against the clock on the | ||||||
| input signals, and an arrival time for the ``Q`` output. | input signals, and an arrival time for the ``Q`` output. | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ Our circuit now looks like this: | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
|    :name: counter-hierarchy |    :name: counter-hierarchy | ||||||
| 
 | 
 | ||||||
|    ``counter`` after :cmd:ref:`hierarchy` |    ``counter`` after `hierarchy` | ||||||
| 
 | 
 | ||||||
| Coarse-grain representation | Coarse-grain representation | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -82,7 +82,7 @@ Logic gate mapping | ||||||
| .. figure:: /_images/code_examples/intro/counter_02.* | .. figure:: /_images/code_examples/intro/counter_02.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
| 
 | 
 | ||||||
|    ``counter`` after :cmd:ref:`techmap` |    ``counter`` after `techmap` | ||||||
| 
 | 
 | ||||||
| Mapping to hardware | Mapping to hardware | ||||||
| ~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -98,11 +98,11 @@ our internal cell library will be mapped to: | ||||||
|    :name: mycells-lib |    :name: mycells-lib | ||||||
|    :caption: :file:`mycells.lib` |    :caption: :file:`mycells.lib` | ||||||
| 
 | 
 | ||||||
| Recall that the Yosys built-in logic gate types are ``$_NOT_``, ``$_AND_``, | Recall that the Yosys built-in logic gate types are `$_NOT_`, `$_AND_`, `$_OR_`, | ||||||
| ``$_OR_``, ``$_XOR_``, and ``$_MUX_`` with an assortment of dff memory types. | `$_XOR_`, and `$_MUX_` with an assortment of dff memory types. | ||||||
| :ref:`mycells-lib` defines our target cells as ``BUF``, ``NOT``, ``NAND``, | :ref:`mycells-lib` defines our target cells as ``BUF``, ``NOT``, ``NAND``, | ||||||
| ``NOR``, and ``DFF``.  Mapping between these is performed with the commands | ``NOR``, and ``DFF``.  Mapping between these is performed with the commands | ||||||
| :cmd:ref:`dfflibmap` and :cmd:ref:`abc` as follows: | `dfflibmap` and `abc` as follows: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/intro/counter.ys | .. literalinclude:: /code_examples/intro/counter.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  | @ -117,8 +117,8 @@ The final version of our ``counter`` module looks like this: | ||||||
| 
 | 
 | ||||||
|    ``counter`` after hardware cell mapping |    ``counter`` after hardware cell mapping | ||||||
| 
 | 
 | ||||||
| Before finally being output as a verilog file with :cmd:ref:`write_verilog`, | Before finally being output as a verilog file with `write_verilog`, which can | ||||||
| which can then be loaded into another tool: | then be loaded into another tool: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/intro/counter.ys | .. literalinclude:: /code_examples/intro/counter.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| The extract pass | The extract pass | ||||||
| ---------------- | ---------------- | ||||||
| 
 | 
 | ||||||
| - Like the :cmd:ref:`techmap` pass, the :cmd:ref:`extract` pass is called with a | - Like the `techmap` pass, the `extract` pass is called with a map file. It | ||||||
|   map file. It compares the circuits inside the modules of the map file with the |   compares the circuits inside the modules of the map file with the design and | ||||||
|   design and looks for sub-circuits in the design that match any of the modules |   looks for sub-circuits in the design that match any of the modules in the map | ||||||
|   in the map file. |   file. | ||||||
| - If a match is found, the :cmd:ref:`extract` pass will replace the matching | - If a match is found, the `extract` pass will replace the matching subcircuit | ||||||
|   subcircuit with an instance of the module from the map file. |   with an instance of the module from the map file. | ||||||
| - In a way the :cmd:ref:`extract` pass is the inverse of the techmap pass. | - In a way the `extract` pass is the inverse of the techmap pass. | ||||||
| 
 | 
 | ||||||
| .. todo:: add/expand supporting text, also mention custom pattern matching and | .. todo:: add/expand supporting text, also mention custom pattern matching and | ||||||
|    pmgen |    pmgen | ||||||
|  | @ -25,7 +25,7 @@ Example code can be found in |code_examples/macc|_. | ||||||
| .. figure:: /_images/code_examples/macc/macc_simple_test_00a.* | .. figure:: /_images/code_examples/macc/macc_simple_test_00a.* | ||||||
|     :class: width-helper invert-helper |     :class: width-helper invert-helper | ||||||
|      |      | ||||||
|     before :cmd:ref:`extract` |     before `extract` | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macc/macc_simple_test.ys | .. literalinclude:: /code_examples/macc/macc_simple_test.ys | ||||||
|     :language: yoscrypt |     :language: yoscrypt | ||||||
|  | @ -34,7 +34,7 @@ Example code can be found in |code_examples/macc|_. | ||||||
| .. figure:: /_images/code_examples/macc/macc_simple_test_00b.* | .. figure:: /_images/code_examples/macc/macc_simple_test_00b.* | ||||||
|     :class: width-helper invert-helper |     :class: width-helper invert-helper | ||||||
|      |      | ||||||
|     after :cmd:ref:`extract` |     after `extract` | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macc/macc_simple_test.v | .. literalinclude:: /code_examples/macc/macc_simple_test.v | ||||||
|    :language: verilog |    :language: verilog | ||||||
|  | @ -68,26 +68,26 @@ The wrap-extract-unwrap method | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| Often a coarse-grain element has a constant bit-width, but can be used to | Often a coarse-grain element has a constant bit-width, but can be used to | ||||||
| implement operations with a smaller bit-width. For example, a 18x25-bit multiplier | implement operations with a smaller bit-width. For example, a 18x25-bit | ||||||
| can also be used to implement 16x20-bit multiplication. | multiplier can also be used to implement 16x20-bit multiplication. | ||||||
| 
 | 
 | ||||||
| A way of mapping such elements in coarse grain synthesis is the | A way of mapping such elements in coarse grain synthesis is the | ||||||
| wrap-extract-unwrap method: | wrap-extract-unwrap method: | ||||||
| 
 | 
 | ||||||
| wrap | wrap | ||||||
|   Identify candidate-cells in the circuit and wrap them in a cell with a |   Identify candidate-cells in the circuit and wrap them in a cell with a | ||||||
|   constant wider bit-width using :cmd:ref:`techmap`. The wrappers use the same |   constant wider bit-width using `techmap`. The wrappers use the same parameters | ||||||
|   parameters as the original cell, so the information about the original width |   as the original cell, so the information about the original width of the ports | ||||||
|   of the ports is preserved. Then use the :cmd:ref:`connwrappers` command to |   is preserved. Then use the `connwrappers` command to connect up the | ||||||
|   connect up the bit-extended in- and outputs of the wrapper cells. |   bit-extended in- and outputs of the wrapper cells. | ||||||
| 
 | 
 | ||||||
| extract | extract | ||||||
|   Now all operations are encoded using the same bit-width as the coarse grain |   Now all operations are encoded using the same bit-width as the coarse grain | ||||||
|   element. The :cmd:ref:`extract` command can be used to replace circuits with |   element. The `extract` command can be used to replace circuits with cells of | ||||||
|   cells of the target architecture. |   the target architecture. | ||||||
| 
 | 
 | ||||||
| unwrap | unwrap | ||||||
|   The remaining wrapper cell can be unwrapped using :cmd:ref:`techmap`. |   The remaining wrapper cell can be unwrapped using `techmap`. | ||||||
| 
 | 
 | ||||||
| Example: DSP48_MACC | Example: DSP48_MACC | ||||||
| ~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -127,7 +127,7 @@ Extract: :file:`macc_xilinx_xmap.v` | ||||||
|    :caption: :file:`macc_xilinx_xmap.v` |    :caption: :file:`macc_xilinx_xmap.v` | ||||||
| 
 | 
 | ||||||
| ... simply use the same wrapping commands on this module as on the design to | ... simply use the same wrapping commands on this module as on the design to | ||||||
| create a template for the :cmd:ref:`extract` command. | create a template for the `extract` command. | ||||||
| 
 | 
 | ||||||
| Unwrapping multipliers: :file:`macc_xilinx_unwrap_map.v` | Unwrapping multipliers: :file:`macc_xilinx_unwrap_map.v` | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| FSM handling | FSM handling | ||||||
| ============ | ============ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm` command identifies, extracts, optimizes (re-encodes), and | The `fsm` command identifies, extracts, optimizes (re-encodes), and | ||||||
| re-synthesizes finite state machines. It again is a macro that calls a series of | re-synthesizes finite state machines. It again is a macro that calls a series of | ||||||
| other commands: | other commands: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macro_commands/fsm.ys | .. literalinclude:: /code_examples/macro_commands/fsm.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|    :start-after: #end: |    :start-after: #end: | ||||||
|    :caption: Passes called by :cmd:ref:`fsm` |    :caption: Passes called by `fsm` | ||||||
| 
 | 
 | ||||||
| See also :doc:`/cmd/fsm`. | See also :doc:`/cmd/fsm`. | ||||||
| 
 | 
 | ||||||
|  | @ -18,34 +18,33 @@ general reported technique :cite:p:`fsmextract`. | ||||||
| FSM detection | FSM detection | ||||||
| ~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_detect` pass identifies FSM state registers. It sets the | The `fsm_detect` pass identifies FSM state registers. It sets the | ||||||
| ``\fsm_encoding = "auto"`` attribute on any (multi-bit) wire that matches the | ``fsm_encoding = "auto"`` attribute on any (multi-bit) wire that matches the | ||||||
| following description: | following description: | ||||||
| 
 | 
 | ||||||
| -  Does not already have the ``\fsm_encoding`` attribute. | -  Does not already have the ``fsm_encoding`` attribute. | ||||||
| -  Is not an output of the containing module. | -  Is not an output of the containing module. | ||||||
| -  Is driven by single ``$dff`` or ``$adff`` cell. | -  Is driven by single `$dff` or `$adff` cell. | ||||||
| -  The ``\D``-Input of this ``$dff`` or ``$adff`` cell is driven by a | -  The ``D``-Input of this `$dff` or `$adff` cell is driven by a multiplexer | ||||||
|    multiplexer tree that only has constants or the old state value on its |    tree that only has constants or the old state value on its leaves. | ||||||
|    leaves. |  | ||||||
| -  The state value is only used in the said multiplexer tree or by simple | -  The state value is only used in the said multiplexer tree or by simple | ||||||
|    relational cells that compare the state value to a constant (usually ``$eq`` |    relational cells that compare the state value to a constant (usually `$eq` | ||||||
|    cells). |    cells). | ||||||
| 
 | 
 | ||||||
| This heuristic has proven to work very well. It is possible to overwrite it by | This heuristic has proven to work very well. It is possible to overwrite it by | ||||||
| setting ``\fsm_encoding = "auto"`` on registers that should be considered FSM | setting ``fsm_encoding = "auto"`` on registers that should be considered FSM | ||||||
| state registers and setting ``\fsm_encoding = "none"`` on registers that match | state registers and setting ``fsm_encoding = "none"`` on registers that match | ||||||
| the above criteria but should not be considered FSM state registers. | the above criteria but should not be considered FSM state registers. | ||||||
| 
 | 
 | ||||||
| Note however that marking state registers with ``\fsm_encoding`` that are not | Note however that marking state registers with ``fsm_encoding`` that are not | ||||||
| suitable for FSM recoding can cause synthesis to fail or produce invalid | suitable for FSM recoding can cause synthesis to fail or produce invalid | ||||||
| results. | results. | ||||||
| 
 | 
 | ||||||
| FSM extraction | FSM extraction | ||||||
| ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_extract` pass operates on all state signals marked with the | The `fsm_extract` pass operates on all state signals marked with the | ||||||
| (``\fsm_encoding != "none"``) attribute. For each state signal the following | (``fsm_encoding != "none"``) attribute. For each state signal the following | ||||||
| information is determined: | information is determined: | ||||||
| 
 | 
 | ||||||
| -  The state registers | -  The state registers | ||||||
|  | @ -64,10 +63,10 @@ information is determined: | ||||||
| The state registers (and asynchronous reset state, if applicable) is simply | The state registers (and asynchronous reset state, if applicable) is simply | ||||||
| determined by identifying the driver for the state signal. | determined by identifying the driver for the state signal. | ||||||
| 
 | 
 | ||||||
| From there the ``$mux-tree`` driving the state register inputs is recursively | From there the `$mux`\ -tree driving the state register inputs is recursively | ||||||
| traversed. All select inputs are control signals and the leaves of the | traversed. All select inputs are control signals and the leaves of the `$mux`\ | ||||||
| ``$mux-tree`` are the states. The algorithm fails if a non-constant leaf that is | -tree are the states. The algorithm fails if a non-constant leaf that is not the | ||||||
| not the state signal itself is found. | state signal itself is found. | ||||||
| 
 | 
 | ||||||
| The list of control outputs is initialized with the bits from the state signal. | The list of control outputs is initialized with the bits from the state signal. | ||||||
| It is then extended by adding all values that are calculated by cells that | It is then extended by adding all values that are calculated by cells that | ||||||
|  | @ -85,8 +84,8 @@ given set of result signals using a set of signal-value assignments. It can also | ||||||
| be passed a list of stop-signals that abort the ConstEval algorithm if the value | be passed a list of stop-signals that abort the ConstEval algorithm if the value | ||||||
| of a stop-signal is needed in order to calculate the result signals. | of a stop-signal is needed in order to calculate the result signals. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_extract` pass uses the ConstEval class in the following way to | The `fsm_extract` pass uses the ConstEval class in the following way to create a | ||||||
| create a transition table. For each state: | transition table. For each state: | ||||||
| 
 | 
 | ||||||
| 1. Create a ConstEval object for the module containing the FSM | 1. Create a ConstEval object for the module containing the FSM | ||||||
| 2. Add all control inputs to the list of stop signals | 2. Add all control inputs to the list of stop signals | ||||||
|  | @ -99,20 +98,19 @@ create a transition table. For each state: | ||||||
| 
 | 
 | ||||||
| 6. If step 4 was successful: Emit transition | 6. If step 4 was successful: Emit transition | ||||||
| 
 | 
 | ||||||
| Finally a ``$fsm`` cell is created with the generated transition table and added | Finally a `$fsm` cell is created with the generated transition table and added | ||||||
| to the module. This new cell is connected to the control signals and the old | to the module. This new cell is connected to the control signals and the old | ||||||
| drivers for the control outputs are disconnected. | drivers for the control outputs are disconnected. | ||||||
| 
 | 
 | ||||||
| FSM optimization | FSM optimization | ||||||
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_opt` pass performs basic optimizations on ``$fsm`` cells (not | The `fsm_opt` pass performs basic optimizations on `$fsm` cells (not including | ||||||
| including state recoding). The following optimizations are performed (in this | state recoding). The following optimizations are performed (in this order): | ||||||
| order): |  | ||||||
| 
 | 
 | ||||||
| -  Unused control outputs are removed from the ``$fsm`` cell. The attribute | -  Unused control outputs are removed from the `$fsm` cell. The attribute | ||||||
|    ``\unused_bits`` (that is usually set by the :cmd:ref:`opt_clean` pass) is |    ``unused_bits`` (that is usually set by the `opt_clean` pass) is used to | ||||||
|    used to determine which control outputs are unused. |    determine which control outputs are unused. | ||||||
| 
 | 
 | ||||||
| -  Control inputs that are connected to the same driver are merged. | -  Control inputs that are connected to the same driver are merged. | ||||||
| 
 | 
 | ||||||
|  | @ -132,11 +130,10 @@ order): | ||||||
| FSM recoding | FSM recoding | ||||||
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_recode` pass assigns new bit pattern to the states. Usually | The `fsm_recode` pass assigns new bit pattern to the states. Usually this also | ||||||
| this also implies a change in the width of the state signal. At the moment of | implies a change in the width of the state signal. At the moment of this writing | ||||||
| this writing only one-hot encoding with all-zero for the reset state is | only one-hot encoding with all-zero for the reset state is supported. | ||||||
| supported. |  | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`fsm_recode` pass can also write a text file with the changes | The `fsm_recode` pass can also write a text file with the changes performed by | ||||||
| performed by it that can be used when verifying designs synthesized by Yosys | it that can be used when verifying designs synthesized by Yosys using Synopsys | ||||||
| using Synopsys Formality. | Formality. | ||||||
|  |  | ||||||
|  | @ -8,17 +8,16 @@ coarse-grain optimizations before being mapped to hard blocks and fine-grain | ||||||
| cells.  Most commands in Yosys will target either coarse-grain representation or | cells.  Most commands in Yosys will target either coarse-grain representation or | ||||||
| fine-grain representation, with only a select few compatible with both states. | fine-grain representation, with only a select few compatible with both states. | ||||||
| 
 | 
 | ||||||
| Commands such as :cmd:ref:`proc`, :cmd:ref:`fsm`, and :cmd:ref:`memory` rely on | Commands such as `proc`, `fsm`, and `memory` rely on the additional information | ||||||
| the additional information in the coarse-grain representation, along with a | in the coarse-grain representation, along with a number of optimizations such as | ||||||
| number of optimizations such as :cmd:ref:`wreduce`, :cmd:ref:`share`, and | `wreduce`, `share`, and `alumacc`.  `opt` provides optimizations which are | ||||||
| :cmd:ref:`alumacc`.  :cmd:ref:`opt` provides optimizations which are useful in | useful in both states, while `techmap` is used to convert coarse-grain cells to | ||||||
| both states, while :cmd:ref:`techmap` is used to convert coarse-grain cells | the corresponding fine-grain representation. | ||||||
| to the corresponding fine-grain representation. |  | ||||||
| 
 | 
 | ||||||
| Single-bit cells (logic gates, FFs) as well as LUTs, half-adders, and | Single-bit cells (logic gates, FFs) as well as LUTs, half-adders, and | ||||||
| full-adders make up the bulk of the fine-grain representation and are necessary | full-adders make up the bulk of the fine-grain representation and are necessary | ||||||
| for commands such as :cmd:ref:`abc`\ /:cmd:ref:`abc9`, :cmd:ref:`simplemap`, | for commands such as `abc`\ /`abc9`, `simplemap`, `dfflegalize`, and | ||||||
| :cmd:ref:`dfflegalize`, and :cmd:ref:`memory_map`. | `memory_map`. | ||||||
| 
 | 
 | ||||||
| .. toctree:: | .. toctree:: | ||||||
|    :maxdepth: 3 |    :maxdepth: 3 | ||||||
|  |  | ||||||
|  | @ -1,32 +1,32 @@ | ||||||
| Memory handling | Memory handling | ||||||
| =============== | =============== | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`memory` command | The `memory` command | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
| 
 | 
 | ||||||
| In the RTL netlist, memory reads and writes are individual cells. This makes | In the RTL netlist, memory reads and writes are individual cells. This makes | ||||||
| consolidating the number of ports for a memory easier. The :cmd:ref:`memory` | consolidating the number of ports for a memory easier. The `memory` pass | ||||||
| pass transforms memories to an implementation. Per default that is logic for | transforms memories to an implementation. Per default that is logic for address | ||||||
| address decoders and registers. It also is a macro command that calls the other | decoders and registers. It also is a macro command that calls the other common | ||||||
| common ``memory_*`` passes in a sensible order: | ``memory_*`` passes in a sensible order: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macro_commands/memory.ys | .. literalinclude:: /code_examples/macro_commands/memory.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|    :start-after: #end: |    :start-after: #end: | ||||||
|    :caption: Passes called by :cmd:ref:`memory` |    :caption: Passes called by `memory` | ||||||
| 
 | 
 | ||||||
| .. todo:: Make ``memory_*`` notes less quick | .. todo:: Make ``memory_*`` notes less quick | ||||||
| 
 | 
 | ||||||
| Some quick notes: | Some quick notes: | ||||||
| 
 | 
 | ||||||
| -  :cmd:ref:`memory_dff` merges registers into the memory read- and write cells. | -  `memory_dff` merges registers into the memory read- and write cells. | ||||||
| -  :cmd:ref:`memory_collect` collects all read and write cells for a memory and | -  `memory_collect` collects all read and write cells for a memory and | ||||||
|    transforms them into one multi-port memory cell. |    transforms them into one multi-port memory cell. | ||||||
| -  :cmd:ref:`memory_map` takes the multi-port memory cell and transforms it to | -  `memory_map` takes the multi-port memory cell and transforms it to address | ||||||
|    address decoder logic and registers. |    decoder logic and registers. | ||||||
| 
 | 
 | ||||||
| For more information about :cmd:ref:`memory`, such as disabling certain sub | For more information about `memory`, such as disabling certain sub commands, see | ||||||
| commands, see :doc:`/cmd/memory`. | :doc:`/cmd/memory`. | ||||||
| 
 | 
 | ||||||
| Example | Example | ||||||
| ------- | ------- | ||||||
|  | @ -75,22 +75,22 @@ For example: | ||||||
|     techmap -map my_memory_map.v |     techmap -map my_memory_map.v | ||||||
|     memory_map |     memory_map | ||||||
| 
 | 
 | ||||||
| :cmd:ref:`memory_libmap` attempts to convert memory cells (``$mem_v2`` etc) into | `memory_libmap` attempts to convert memory cells (`$mem_v2` etc) into hardware | ||||||
| hardware supported memory using a provided library (:file:`my_memory_map.txt` in the | supported memory using a provided library (:file:`my_memory_map.txt` in the | ||||||
| example above).  Where necessary, emulation logic is added to ensure functional | example above).  Where necessary, emulation logic is added to ensure functional | ||||||
| equivalence before and after this conversion. :yoscrypt:`techmap -map | equivalence before and after this conversion. :yoscrypt:`techmap -map | ||||||
| my_memory_map.v` then uses :cmd:ref:`techmap` to map to hardware primitives. Any | my_memory_map.v` then uses `techmap` to map to hardware primitives. Any leftover | ||||||
| leftover memory cells unable to be converted are then picked up by | memory cells unable to be converted are then picked up by `memory_map` and | ||||||
| :cmd:ref:`memory_map` and mapped to DFFs and address decoders. | mapped to DFFs and address decoders. | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
| 
 | 
 | ||||||
|    More information about what mapping options are available and associated |    More information about what mapping options are available and associated | ||||||
|    costs of each can be found by enabling debug outputs.  This can be done with |    costs of each can be found by enabling debug outputs.  This can be done with | ||||||
|    the :cmd:ref:`debug` command, or by using the ``-g`` flag when calling Yosys |    the `debug` command, or by using the ``-g`` flag when calling Yosys to | ||||||
|    to globally enable debug messages. |    globally enable debug messages. | ||||||
| 
 | 
 | ||||||
| For more on the lib format for :cmd:ref:`memory_libmap`, see | For more on the lib format for `memory_libmap`, see | ||||||
| `passes/memory/memlib.md | `passes/memory/memlib.md | ||||||
| <https://github.com/YosysHQ/yosys/blob/main/passes/memory/memlib.md>`_ | <https://github.com/YosysHQ/yosys/blob/main/passes/memory/memlib.md>`_ | ||||||
| 
 | 
 | ||||||
|  | @ -110,13 +110,15 @@ Notes | ||||||
| Memory kind selection | Memory kind selection | ||||||
| ~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| The memory inference code will automatically pick target memory primitive based on memory geometry | The memory inference code will automatically pick target memory primitive based | ||||||
| and features used.  Depending on the target, there can be up to four memory primitive classes | on memory geometry and features used.  Depending on the target, there can be up | ||||||
| available for selection: | to four memory primitive classes available for selection: | ||||||
| 
 | 
 | ||||||
| - FF RAM (aka logic): no hardware primitive used, memory lowered to a bunch of FFs and multiplexers | - FF RAM (aka logic): no hardware primitive used, memory lowered to a bunch of | ||||||
|  |   FFs and multiplexers | ||||||
| 
 | 
 | ||||||
|   - Can handle arbitrary number of write ports, as long as all write ports are in the same clock domain |   - Can handle arbitrary number of write ports, as long as all write ports are | ||||||
|  |     in the same clock domain | ||||||
|   - Can handle arbitrary number and kind of read ports |   - Can handle arbitrary number and kind of read ports | ||||||
| 
 | 
 | ||||||
| - LUT RAM (aka distributed RAM): uses LUT storage as RAM | - LUT RAM (aka distributed RAM): uses LUT storage as RAM | ||||||
|  | @ -131,7 +133,8 @@ available for selection: | ||||||
|   - Supported on basically all FPGAs |   - Supported on basically all FPGAs | ||||||
|   - Supports only synchronous reads |   - Supports only synchronous reads | ||||||
|   - Two ports with separate clocks |   - Two ports with separate clocks | ||||||
|   - Usually supports true dual port (with notable exception of ice40 that only supports SDP) |   - Usually supports true dual port (with notable exception of ice40 that only | ||||||
|  |     supports SDP) | ||||||
|   - Usually supports asymmetric memories and per-byte write enables |   - Usually supports asymmetric memories and per-byte write enables | ||||||
|   - Several kilobits in size |   - Several kilobits in size | ||||||
| 
 | 
 | ||||||
|  | @ -155,38 +158,43 @@ available for selection: | ||||||
|       - Two ports, both with mutually exclusive synchronous read and write |       - Two ports, both with mutually exclusive synchronous read and write | ||||||
|       - Single clock |       - Single clock | ||||||
| 
 | 
 | ||||||
|   - Will not be automatically selected by memory inference code, needs explicit opt-in via |   - Will not be automatically selected by memory inference code, needs explicit | ||||||
|     ram_style attribute |     opt-in via ram_style attribute | ||||||
| 
 | 
 | ||||||
| In general, you can expect the automatic selection process to work roughly like this: | In general, you can expect the automatic selection process to work roughly like | ||||||
|  | this: | ||||||
| 
 | 
 | ||||||
| - If any read port is asynchronous, only LUT RAM (or FF RAM) can be used. | - If any read port is asynchronous, only LUT RAM (or FF RAM) can be used. | ||||||
| - If there is more than one write port, only block RAM can be used, and this needs to be a | - If there is more than one write port, only block RAM can be used, and this | ||||||
|   hardware-supported true dual port pattern |   needs to be a hardware-supported true dual port pattern | ||||||
| 
 | 
 | ||||||
|   - … unless all write ports are in the same clock domain, in which case FF RAM can also be used, |   - … unless all write ports are in the same clock domain, in which case FF RAM | ||||||
|     but this is generally not what you want for anything but really small memories |     can also be used, but this is generally not what you want for anything but | ||||||
|  |     really small memories | ||||||
| 
 | 
 | ||||||
| - Otherwise, either FF RAM, LUT RAM, or block RAM will be used, depending on memory size | - Otherwise, either FF RAM, LUT RAM, or block RAM will be used, depending on | ||||||
|  |   memory size | ||||||
| 
 | 
 | ||||||
| This process can be overridden by attaching a ram_style attribute to the memory: | This process can be overridden by attaching a ram_style attribute to the memory: | ||||||
| 
 | 
 | ||||||
| - `(* ram_style = "logic" *)` selects FF RAM | - ``(* ram_style = "logic" *)`` selects FF RAM | ||||||
| - `(* ram_style = "distributed" *)` selects LUT RAM | - ``(* ram_style = "distributed" *)`` selects LUT RAM | ||||||
| - `(* ram_style = "block" *)` selects block RAM | - ``(* ram_style = "block" *)`` selects block RAM | ||||||
| - `(* ram_style = "huge" *)` selects huge RAM | - ``(* ram_style = "huge" *)`` selects huge RAM | ||||||
| 
 | 
 | ||||||
| It is an error if this override cannot be realized for the given target. | It is an error if this override cannot be realized for the given target. | ||||||
| 
 | 
 | ||||||
| Many alternate spellings of the attribute are also accepted, for compatibility with other software. | Many alternate spellings of the attribute are also accepted, for compatibility | ||||||
|  | with other software. | ||||||
| 
 | 
 | ||||||
| Initial data | Initial data | ||||||
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| Most FPGA targets support initializing all kinds of memory to user-provided values.  If explicit | Most FPGA targets support initializing all kinds of memory to user-provided | ||||||
| initialization is not used the initial memory value is undefined.  Initial data can be provided by | values.  If explicit initialization is not used the initial memory value is | ||||||
| either initial statements writing memory cells one by one of ``$readmemh`` or ``$readmemb`` system | undefined.  Initial data can be provided by either initial statements writing | ||||||
| tasks.  For an example pattern, see `sr_init`_. | memory cells one by one of ``$readmemh`` or ``$readmemb`` system tasks.  For an | ||||||
|  | example pattern, see `sr_init`_. | ||||||
| 
 | 
 | ||||||
| .. _wbe: | .. _wbe: | ||||||
| 
 | 
 | ||||||
|  | @ -194,12 +202,13 @@ Write port with byte enables | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Byte enables can be used with any supported pattern | - Byte enables can be used with any supported pattern | ||||||
| - To ensure that multiple writes will be merged into one port, they need to have disjoint bit | - To ensure that multiple writes will be merged into one port, they need to have | ||||||
|   ranges, have the same address, and the same clock |   disjoint bit ranges, have the same address, and the same clock | ||||||
| - Any write enable granularity will be accepted (down to per-bit write enables), but using smaller | - Any write enable granularity will be accepted (down to per-bit write enables), | ||||||
|   granularity than natively supported by the target is very likely to be inefficient (eg. using |   but using smaller granularity than natively supported by the target is very | ||||||
|   4-bit bytes on ECP5 will result in either padding the bytes with 5 dummy bits to native 9-bit |   likely to be inefficient (eg. using 4-bit bytes on ECP5 will result in either | ||||||
|   units or splitting the RAM into two block RAMs) |   padding the bytes with 5 dummy bits to native 9-bit units or splitting the RAM | ||||||
|  |   into two block RAMs) | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -240,7 +249,8 @@ Synchronous SDP with clock domain crossing | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Will result in block RAM or LUT RAM depending on size | - Will result in block RAM or LUT RAM depending on size | ||||||
| - No behavior guarantees in case of simultaneous read and write to the same address | - No behavior guarantees in case of simultaneous read and write to the same | ||||||
|  |   address | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -261,9 +271,9 @@ Synchronous SDP read first | ||||||
| 
 | 
 | ||||||
| - The read and write parts can be in the same or different processes. | - The read and write parts can be in the same or different processes. | ||||||
| - Will result in block RAM or LUT RAM depending on size | - Will result in block RAM or LUT RAM depending on size | ||||||
| - As long as the same clock is used for both, yosys will ensure read-first behavior.  This may | - As long as the same clock is used for both, yosys will ensure read-first | ||||||
|   require extra circuitry on some targets for block RAM.  If this is not necessary, use one of the |   behavior.  This may require extra circuitry on some targets for block RAM.  If | ||||||
|   patterns below. |   this is not necessary, use one of the patterns below. | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -281,8 +291,8 @@ Synchronous SDP read first | ||||||
| Synchronous SDP with undefined collision behavior | Synchronous SDP with undefined collision behavior | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Like above, but the read value is undefined when read and write ports target the same address in | - Like above, but the read value is undefined when read and write ports target | ||||||
|   the same cycle |   the same address in the same cycle | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -322,8 +332,8 @@ Synchronous SDP with write-first behavior | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Will result in block RAM or LUT RAM depending on size | - Will result in block RAM or LUT RAM depending on size | ||||||
| - May use additional circuitry for block RAM if write-first is not natively supported. Will always | - May use additional circuitry for block RAM if write-first is not natively | ||||||
|   use additional circuitry for LUT RAM. |   supported. Will always use additional circuitry for LUT RAM. | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -343,7 +353,8 @@ Synchronous SDP with write-first behavior | ||||||
| Synchronous SDP with write-first behavior (alternate pattern) | Synchronous SDP with write-first behavior (alternate pattern) | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - This pattern is supported for compatibility, but is much less flexible than the above | - This pattern is supported for compatibility, but is much less flexible than | ||||||
|  |   the above | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -378,8 +389,10 @@ Synchronous single-port RAM with mutually exclusive read/write | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Will result in single-port block RAM or LUT RAM depending on size | - Will result in single-port block RAM or LUT RAM depending on size | ||||||
| - This is the correct pattern to infer ice40 SPRAM (with manual ram_style selection) | - This is the correct pattern to infer ice40 SPRAM (with manual ram_style | ||||||
| - On targets that don't support read/write block RAM ports (eg. ice40), will result in SDP block RAM instead |   selection) | ||||||
|  | - On targets that don't support read/write block RAM ports (eg. ice40), will | ||||||
|  |   result in SDP block RAM instead | ||||||
| - For block RAM, will use "NO_CHANGE" mode if available | - For block RAM, will use "NO_CHANGE" mode if available | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
|  | @ -396,12 +409,14 @@ Synchronous single-port RAM with mutually exclusive read/write | ||||||
| Synchronous single-port RAM with read-first behavior | Synchronous single-port RAM with read-first behavior | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Will only result in single-port block RAM when read-first behavior is natively supported; | - Will only result in single-port block RAM when read-first behavior is natively | ||||||
|   otherwise, SDP RAM with additional circuitry will be used |   supported; otherwise, SDP RAM with additional circuitry will be used | ||||||
| - Many targets (Xilinx, ECP5, …) can only natively support read-first/write-first single-port RAM | - Many targets (Xilinx, ECP5, …) can only natively support | ||||||
|   (or TDP RAM) where the write_enable signal implies the read_enable signal (ie. can never write |   read-first/write-first single-port RAM (or TDP RAM) where the write_enable | ||||||
|   without reading). The memory inference code will run a simple SAT solver on the control signals to |   signal implies the read_enable signal (ie. can never write without reading). | ||||||
|   determine if this is the case, and insert emulation circuitry if it cannot be easily proven. |   The memory inference code will run a simple SAT solver on the control signals | ||||||
|  |   to determine if this is the case, and insert emulation circuitry if it cannot | ||||||
|  |   be easily proven. | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -418,7 +433,8 @@ Synchronous single-port RAM with write-first behavior | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Will result in single-port block RAM or LUT RAM when supported | - Will result in single-port block RAM or LUT RAM when supported | ||||||
| - Block RAMs will require extra circuitry if write-first behavior not natively supported | - Block RAMs will require extra circuitry if write-first behavior not natively | ||||||
|  |   supported | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -440,8 +456,8 @@ Synchronous read port with initial value | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - Initial read port values can be combined with any other supported pattern | - Initial read port values can be combined with any other supported pattern | ||||||
| - If block RAM is used and initial read port values are not natively supported by the target, small | - If block RAM is used and initial read port values are not natively supported | ||||||
|   emulation circuit will be inserted |   by the target, small emulation circuit will be inserted | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -459,10 +475,11 @@ Synchronous read port with initial value | ||||||
| Read register reset patterns | Read register reset patterns | ||||||
| ---------------------------- | ---------------------------- | ||||||
| 
 | 
 | ||||||
| Resets can be combined with any other supported pattern (except that synchronous reset and | Resets can be combined with any other supported pattern (except that synchronous | ||||||
| asynchronous reset cannot both be used on a single read port).  If block RAM is used and the | reset and asynchronous reset cannot both be used on a single read port).  If | ||||||
| selected reset (synchronous or asynchronous) is used but not natively supported by the target, small | block RAM is used and the selected reset (synchronous or asynchronous) is used | ||||||
| emulation circuitry will be inserted. | but not natively supported by the target, small emulation circuitry will be | ||||||
|  | inserted. | ||||||
| 
 | 
 | ||||||
| Synchronous reset, reset priority over enable | Synchronous reset, reset priority over enable | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -520,22 +537,26 @@ Synchronous read port with asynchronous reset | ||||||
| Asymmetric memory patterns | Asymmetric memory patterns | ||||||
| -------------------------- | -------------------------- | ||||||
| 
 | 
 | ||||||
| To construct an asymmetric memory (memory with read/write ports of differing widths): | To construct an asymmetric memory (memory with read/write ports of differing | ||||||
|  | widths): | ||||||
| 
 | 
 | ||||||
| - Declare the memory with the width of the narrowest intended port | - Declare the memory with the width of the narrowest intended port | ||||||
| - Split all wide ports into multiple narrow ports | - Split all wide ports into multiple narrow ports | ||||||
| - To ensure the wide ports will be correctly merged: | - To ensure the wide ports will be correctly merged: | ||||||
| 
 | 
 | ||||||
|   - For the address, use a concatenation of actual address in the high bits and a constant in the |   - For the address, use a concatenation of actual address in the high bits and | ||||||
|     low bits |     a constant in the low bits | ||||||
|   - Ensure the actual address is identical for all ports belonging to the wide port |   - Ensure the actual address is identical for all ports belonging to the wide | ||||||
|  |     port | ||||||
|   - Ensure that clock is identical |   - Ensure that clock is identical | ||||||
|   - For read ports, ensure that enable/reset signals are identical (for write ports, the enable |   - For read ports, ensure that enable/reset signals are identical (for write | ||||||
|     signal may vary — this will result in using the byte enable functionality) |     ports, the enable signal may vary — this will result in using the byte | ||||||
|  |     enable functionality) | ||||||
| 
 | 
 | ||||||
| Asymmetric memory is supported on all targets, but may require emulation circuitry where not | Asymmetric memory is supported on all targets, but may require emulation | ||||||
| natively supported.  Note that when the memory is larger than the underlying block RAM primitive, | circuitry where not natively supported.  Note that when the memory is larger | ||||||
| hardware asymmetric memory support is likely not to be used even if present as it is more expensive. | than the underlying block RAM primitive, hardware asymmetric memory support is | ||||||
|  | likely not to be used even if present as it is more expensive. | ||||||
| 
 | 
 | ||||||
| .. _wide_sr: | .. _wide_sr: | ||||||
| 
 | 
 | ||||||
|  | @ -615,20 +636,25 @@ Wide write port | ||||||
| True dual port (TDP) patterns | True dual port (TDP) patterns | ||||||
| ----------------------------- | ----------------------------- | ||||||
| 
 | 
 | ||||||
| - Many different variations of true dual port memory can be created by combining two single-port RAM | - Many different variations of true dual port memory can be created by combining | ||||||
|   patterns on the same memory |   two single-port RAM patterns on the same memory | ||||||
| - When TDP memory is used, memory inference code has much less maneuver room to create requested | - When TDP memory is used, memory inference code has much less maneuver room to | ||||||
|   semantics compared to individual single-port patterns (which can end up lowered to SDP memory |   create requested semantics compared to individual single-port patterns (which | ||||||
|   where necessary) — supported patterns depend strongly on the target |   can end up lowered to SDP memory where necessary) — supported patterns depend | ||||||
| - In particular, when both ports have the same clock, it's likely that "undefined collision" mode |   strongly on the target | ||||||
|   needs to be manually selected to enable TDP memory inference | - In particular, when both ports have the same clock, it's likely that | ||||||
| - The examples below are non-exhaustive — many more combinations of port types are possible |   "undefined collision" mode needs to be manually selected to enable TDP memory | ||||||
| - Note: if two write ports are in the same process, this defines a priority relation between them |   inference | ||||||
|   (if both ports are active in the same clock, the later one wins). On almost all targets, this will | - The examples below are non-exhaustive — many more combinations of port types | ||||||
|   result in a bit of extra circuitry to ensure the priority semantics. If this is not what you want, |   are possible | ||||||
|   put them in separate processes. | - Note: if two write ports are in the same process, this defines a priority | ||||||
|  |   relation between them (if both ports are active in the same clock, the later | ||||||
|  |   one wins). On almost all targets, this will result in a bit of extra circuitry | ||||||
|  |   to ensure the priority semantics. If this is not what you want, put them in | ||||||
|  |   separate processes. | ||||||
| 
 | 
 | ||||||
|   - Priority is not supported when using the verific front end and any priority semantics are ignored. |   - Priority is not supported when using the verific front end and any priority | ||||||
|  |     semantics are ignored. | ||||||
| 
 | 
 | ||||||
| TDP with different clocks, exclusive read/write | TDP with different clocks, exclusive read/write | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -654,7 +680,8 @@ TDP with different clocks, exclusive read/write | ||||||
| TDP with same clock, read-first behavior | TDP with same clock, read-first behavior | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - This requires hardware inter-port read-first behavior, and will only work on some targets (Xilinx, Nexus) | - This requires hardware inter-port read-first behavior, and will only work on | ||||||
|  |   some targets (Xilinx, Nexus) | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  | @ -677,9 +704,10 @@ TDP with same clock, read-first behavior | ||||||
| TDP with multiple read ports | TDP with multiple read ports | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| - The combination of a single write port with an arbitrary amount of read ports is supported on all | - The combination of a single write port with an arbitrary amount of read ports | ||||||
|   targets — if a multi-read port primitive is available (like Xilinx RAM64M), it'll be used as |   is supported on all targets — if a multi-read port primitive is available | ||||||
|   appropriate.  Otherwise, the memory will be automatically split into multiple primitives. |   (like Xilinx RAM64M), it'll be used as appropriate.  Otherwise, the memory | ||||||
|  |   will be automatically split into multiple primitives. | ||||||
| 
 | 
 | ||||||
| .. code:: verilog | .. code:: verilog | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,32 +6,32 @@ This chapter outlines these optimizations. | ||||||
| 
 | 
 | ||||||
| .. todo:: "outlines these optimizations" or "outlines *some*.."? | .. todo:: "outlines these optimizations" or "outlines *some*.."? | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`opt` macro command | The `opt` macro command | ||||||
| -------------------------------- | -------------------------------- | ||||||
| 
 | 
 | ||||||
| The Yosys pass :cmd:ref:`opt` runs a number of simple optimizations. This | The Yosys pass `opt` runs a number of simple optimizations. This includes | ||||||
| includes removing unused signals and cells and const folding. It is recommended | removing unused signals and cells and const folding. It is recommended to run | ||||||
| to run this pass after each major step in the synthesis script.  As listed in | this pass after each major step in the synthesis script.  As listed in | ||||||
| :doc:`/cmd/opt`, this macro command calls the following ``opt_*`` commands: | :doc:`/cmd/opt`, this macro command calls the following ``opt_*`` commands: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macro_commands/opt.ys | .. literalinclude:: /code_examples/macro_commands/opt.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|    :start-after: #end: |    :start-after: #end: | ||||||
|    :caption: Passes called by :cmd:ref:`opt` |    :caption: Passes called by `opt` | ||||||
| 
 | 
 | ||||||
| .. _adv_opt_expr: | .. _adv_opt_expr: | ||||||
| 
 | 
 | ||||||
| Constant folding and simple expression rewriting - :cmd:ref:`opt_expr` | Constant folding and simple expression rewriting - `opt_expr` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| .. todo:: unsure if this is too much detail and should be in :doc:`/yosys_internals/index` | .. todo:: unsure if this is too much detail and should be in :doc:`/yosys_internals/index` | ||||||
| 
 | 
 | ||||||
| This pass performs constant folding on the internal combinational cell types | This pass performs constant folding on the internal combinational cell types | ||||||
| described in :doc:`/yosys_internals/formats/cell_library`. This means a cell | described in :doc:`/cell_index`. This means a cell with all | ||||||
| with all constant inputs is replaced with the constant value this cell drives. | constant inputs is replaced with the constant value this cell drives. In some | ||||||
| In some cases this pass can also optimize cells with some constant inputs. | cases this pass can also optimize cells with some constant inputs. | ||||||
| 
 | 
 | ||||||
| .. table:: Const folding rules for ``$_AND_`` cells as used in :cmd:ref:`opt_expr`. | .. table:: Const folding rules for `$_AND_` cells as used in `opt_expr`. | ||||||
|    :name: tab:opt_expr_and |    :name: tab:opt_expr_and | ||||||
|    :align: center |    :align: center | ||||||
| 
 | 
 | ||||||
|  | @ -54,7 +54,7 @@ In some cases this pass can also optimize cells with some constant inputs. | ||||||
|    ========= ========= =========== |    ========= ========= =========== | ||||||
| 
 | 
 | ||||||
| :numref:`Table %s <tab:opt_expr_and>` shows the replacement rules used for | :numref:`Table %s <tab:opt_expr_and>` shows the replacement rules used for | ||||||
| optimizing an ``$_AND_`` gate. The first three rules implement the obvious const | optimizing an `$_AND_` gate. The first three rules implement the obvious const | ||||||
| folding rules. Note that 'any' might include dynamic values calculated by other | folding rules. Note that 'any' might include dynamic values calculated by other | ||||||
| parts of the circuit. The following three lines propagate undef (X) states. | parts of the circuit. The following three lines propagate undef (X) states. | ||||||
| These are the only three cases in which it is allowed to propagate an undef | These are the only three cases in which it is allowed to propagate an undef | ||||||
|  | @ -66,33 +66,33 @@ substitutions are possible they are performed first, in the hope that the 'any' | ||||||
| will change to an undef value or a 1 and therefore the output can be set to | will change to an undef value or a 1 and therefore the output can be set to | ||||||
| undef. | undef. | ||||||
| 
 | 
 | ||||||
| The last two lines simply replace an ``$_AND_`` gate with one constant-1 input | The last two lines simply replace an `$_AND_` gate with one constant-1 input | ||||||
| with a buffer. | with a buffer. | ||||||
| 
 | 
 | ||||||
| Besides this basic const folding the :cmd:ref:`opt_expr` pass can replace 1-bit | Besides this basic const folding the `opt_expr` pass can replace 1-bit wide | ||||||
| wide ``$eq`` and ``$ne`` cells with buffers or not-gates if one input is | `$eq` and `$ne` cells with buffers or not-gates if one input is constant. | ||||||
| constant.  Equality checks may also be reduced in size if there are redundant | Equality checks may also be reduced in size if there are redundant bits in the | ||||||
| bits in the arguments (i.e. bits which are constant on both inputs).  This can, | arguments (i.e. bits which are constant on both inputs).  This can, for example, | ||||||
| for example, result in a 32-bit wide constant like ``255`` being reduced to the | result in a 32-bit wide constant like ``255`` being reduced to the 8-bit value | ||||||
| 8-bit value of ``8'11111111`` if the signal being compared is only 8-bit as in | of ``8'11111111`` if the signal being compared is only 8-bit as in | ||||||
| :ref:`addr_gen_clean` of :doc:`/getting_started/example_synth`. | :ref:`addr_gen_clean` of :doc:`/getting_started/example_synth`. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`opt_expr` pass is very conservative regarding optimizing ``$mux`` | The `opt_expr` pass is very conservative regarding optimizing `$mux` cells, as | ||||||
| cells, as these cells are often used to model decision-trees and breaking these | these cells are often used to model decision-trees and breaking these trees can | ||||||
| trees can interfere with other optimizations. | interfere with other optimizations. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/opt/opt_expr.ys | .. literalinclude:: /code_examples/opt/opt_expr.ys | ||||||
|    :language: Verilog |    :language: Verilog | ||||||
|    :start-after: read_verilog <<EOT |    :start-after: read_verilog <<EOT | ||||||
|    :end-before: EOT |    :end-before: EOT | ||||||
|    :caption: example verilog for demonstrating :cmd:ref:`opt_expr` |    :caption: example verilog for demonstrating `opt_expr` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/opt/opt_expr.* | .. figure:: /_images/code_examples/opt/opt_expr.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
| 
 | 
 | ||||||
|    Before and after :cmd:ref:`opt_expr` |    Before and after `opt_expr` | ||||||
| 
 | 
 | ||||||
| Merging identical cells - :cmd:ref:`opt_merge` | Merging identical cells - `opt_merge` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This pass performs trivial resource sharing. This means that this pass | This pass performs trivial resource sharing. This means that this pass | ||||||
|  | @ -100,22 +100,22 @@ identifies cells with identical inputs and replaces them with a single instance | ||||||
| of the cell. | of the cell. | ||||||
| 
 | 
 | ||||||
| The option ``-nomux`` can be used to disable resource sharing for multiplexer | 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 | ||||||
| trees to be merged, which might prevent :cmd:ref:`opt_muxtree` to identify | to be merged, which might prevent `opt_muxtree` to identify possible | ||||||
| possible optimizations. | optimizations. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/opt/opt_merge.ys | .. literalinclude:: /code_examples/opt/opt_merge.ys | ||||||
|    :language: Verilog |    :language: Verilog | ||||||
|    :start-after: read_verilog <<EOT |    :start-after: read_verilog <<EOT | ||||||
|    :end-before: EOT |    :end-before: EOT | ||||||
|    :caption: example verilog for demonstrating :cmd:ref:`opt_merge` |    :caption: example verilog for demonstrating `opt_merge` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/opt/opt_merge.* | .. figure:: /_images/code_examples/opt/opt_merge.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
| 
 | 
 | ||||||
|    Before and after :cmd:ref:`opt_merge` |    Before and after `opt_merge` | ||||||
| 
 | 
 | ||||||
| Removing never-active branches from multiplexer tree - :cmd:ref:`opt_muxtree` | Removing never-active branches from multiplexer tree - `opt_muxtree` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This pass optimizes trees of multiplexer cells by analyzing the select inputs. | This pass optimizes trees of multiplexer cells by analyzing the select inputs. | ||||||
|  | @ -125,95 +125,97 @@ Consider the following simple example: | ||||||
|    :language: Verilog |    :language: Verilog | ||||||
|    :start-after: read_verilog <<EOT |    :start-after: read_verilog <<EOT | ||||||
|    :end-before: EOT |    :end-before: EOT | ||||||
|    :caption: example verilog for demonstrating :cmd:ref:`opt_muxtree` |    :caption: example verilog for demonstrating `opt_muxtree` | ||||||
| 
 | 
 | ||||||
| The output can never be ``c``, as this would require ``a`` to be 1 for the outer | The output can never be ``c``, as this would require ``a`` to be 1 for the outer | ||||||
| multiplexer and 0 for the inner multiplexer. The :cmd:ref:`opt_muxtree` pass | multiplexer and 0 for the inner multiplexer. The `opt_muxtree` pass detects this | ||||||
| detects this contradiction and replaces the inner multiplexer with a constant 1, | contradiction and replaces the inner multiplexer with a constant 1, yielding the | ||||||
| yielding the logic for ``y = a ? b : d``. | logic for ``y = a ? b : d``. | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/opt/opt_muxtree.* | .. figure:: /_images/code_examples/opt/opt_muxtree.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
| 
 | 
 | ||||||
|    Before and after :cmd:ref:`opt_muxtree` |    Before and after `opt_muxtree` | ||||||
| 
 | 
 | ||||||
| Simplifying large MUXes and AND/OR gates - :cmd:ref:`opt_reduce` | Simplifying large MUXes and AND/OR gates - `opt_reduce` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This is a simple optimization pass that identifies and consolidates identical | This is a simple optimization pass that identifies and consolidates identical | ||||||
| input bits to ``$reduce_and`` and ``$reduce_or`` cells. It also sorts the input | input bits to `$reduce_and` and `$reduce_or` cells. It also sorts the input bits | ||||||
| bits to ease identification of shareable ``$reduce_and`` and ``$reduce_or`` | to ease identification of shareable `$reduce_and` and `$reduce_or` cells in | ||||||
| cells in other passes. | other passes. | ||||||
| 
 | 
 | ||||||
| This pass also identifies and consolidates identical inputs to multiplexer | This pass also identifies and consolidates identical inputs to multiplexer | ||||||
| cells. In this case the new shared select bit is driven using a ``$reduce_or`` | cells. In this case the new shared select bit is driven using a `$reduce_or` | ||||||
| cell that combines the original select bits. | cell that combines the original select bits. | ||||||
| 
 | 
 | ||||||
| Lastly this pass consolidates trees of ``$reduce_and`` cells and trees of | Lastly this pass consolidates trees of `$reduce_and` cells and trees of | ||||||
| ``$reduce_or`` cells to single large ``$reduce_and`` or ``$reduce_or`` cells. | `$reduce_or` cells to single large `$reduce_and` or `$reduce_or` cells. | ||||||
| 
 | 
 | ||||||
| These three simple optimizations are performed in a loop until a stable result | These three simple optimizations are performed in a loop until a stable result | ||||||
| is produced. | is produced. | ||||||
| 
 | 
 | ||||||
| Merging mutually exclusive cells with shared inputs - :cmd:ref:`opt_share` | Merging mutually exclusive cells with shared inputs - `opt_share` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This pass identifies mutually exclusive cells of the same type that: | This pass identifies mutually exclusive cells of the same type that: | ||||||
|    a. share an input signal, and |    a. share an input signal, and | ||||||
|    b. drive the same ``$mux``, ``$_MUX_``, or ``$pmux`` multiplexing cell, |    b. drive the same `$mux`, `$_MUX_`, or `$pmux` multiplexing cell, | ||||||
| 
 | 
 | ||||||
| allowing the cell to be merged and the multiplexer to be moved from | allowing the cell to be merged and the multiplexer to be moved from multiplexing | ||||||
| multiplexing its output to multiplexing the non-shared input signals. | its output to multiplexing the non-shared input signals. | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/opt/opt_share.ys | .. literalinclude:: /code_examples/opt/opt_share.ys | ||||||
|    :language: Verilog |    :language: Verilog | ||||||
|    :start-after: read_verilog <<EOT |    :start-after: read_verilog <<EOT | ||||||
|    :end-before: EOT |    :end-before: EOT | ||||||
|    :caption: example verilog for demonstrating :cmd:ref:`opt_share` |    :caption: example verilog for demonstrating `opt_share` | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/code_examples/opt/opt_share.* | .. figure:: /_images/code_examples/opt/opt_share.* | ||||||
|    :class: width-helper invert-helper |    :class: width-helper invert-helper | ||||||
| 
 | 
 | ||||||
|    Before and after :cmd:ref:`opt_share` |    Before and after `opt_share` | ||||||
| 
 | 
 | ||||||
| When running :cmd:ref:`opt` in full, the original ``$mux`` (labeled ``$3``) is | When running `opt` in full, the original `$mux` (labeled ``$3``) is optimized | ||||||
| optimized away by :cmd:ref:`opt_expr`. | away by `opt_expr`. | ||||||
| 
 | 
 | ||||||
| Performing DFF optimizations - :cmd:ref:`opt_dff` | Performing DFF optimizations - `opt_dff` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This pass identifies single-bit d-type flip-flops (``$_DFF_``, ``$dff``, and | .. todo:: ``$_DFF_`` isn't a valid cell | ||||||
| ``$adff`` cells) with a constant data input and replaces them with a constant | 
 | ||||||
| driver.  It can also merge clock enables and synchronous reset multiplexers, | This pass identifies single-bit d-type flip-flops (`$_DFF_`, `$dff`, and `$adff` | ||||||
| removing unused control inputs. | cells) with a constant data input and replaces them with a constant driver.  It | ||||||
|  | can also merge clock enables and synchronous reset multiplexers, removing unused | ||||||
|  | control inputs. | ||||||
| 
 | 
 | ||||||
| Called with ``-nodffe`` and ``-nosdff``, this pass is used to prepare a design | Called with ``-nodffe`` and ``-nosdff``, this pass is used to prepare a design | ||||||
| for :doc:`/using_yosys/synthesis/fsm`. | for :doc:`/using_yosys/synthesis/fsm`. | ||||||
| 
 | 
 | ||||||
| Removing unused cells and wires - :cmd:ref:`opt_clean` pass | Removing unused cells and wires - `opt_clean` pass | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| This pass identifies unused signals and cells and removes them from the design. | This pass identifies unused signals and cells and removes them from the design. | ||||||
| It also creates an ``\unused_bits`` attribute on wires with unused bits. This | It also creates an ``unused_bits`` attribute on wires with unused bits. This | ||||||
| attribute can be used for debugging or by other optimization passes. | attribute can be used for debugging or by other optimization passes. | ||||||
| 
 | 
 | ||||||
| When to use :cmd:ref:`opt` or :cmd:ref:`clean` | When to use `opt` or `clean` | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
| 
 | 
 | ||||||
| Usually it does not hurt to call :cmd:ref:`opt` after each regular command in | Usually it does not hurt to call `opt` after each regular command in the | ||||||
| the synthesis script. But it increases the synthesis time, so it is favourable | synthesis script. But it increases the synthesis time, so it is favourable to | ||||||
| to only call :cmd:ref:`opt` when an improvement can be achieved. | only call `opt` when an improvement can be achieved. | ||||||
| 
 | 
 | ||||||
| It is generally a good idea to call :cmd:ref:`opt` before inherently expensive | It is generally a good idea to call `opt` before inherently expensive commands | ||||||
| commands such as :cmd:ref:`sat` or :cmd:ref:`freduce`, as the possible gain is | such as `sat` or `freduce`, as the possible gain is much higher in these cases | ||||||
| much higher in these cases as the possible loss. | as the possible loss. | ||||||
| 
 | 
 | ||||||
| The :cmd:ref:`clean` command, which is an alias for :cmd:ref:`opt_clean` with | The `clean` command, which is an alias for `opt_clean` with fewer outputs, on | ||||||
| fewer outputs, on the other hand is very fast and many commands leave a mess | the other hand is very fast and many commands leave a mess (dangling signal | ||||||
| (dangling signal wires, etc). For example, most commands do not remove any wires | wires, etc). For example, most commands do not remove any wires or cells. They | ||||||
| or cells. They just change the connections and depend on a later call to clean | just change the connections and depend on a later call to clean to get rid of | ||||||
| to get rid of the now unused objects. So the occasional ``;;``, which itself is | the now unused objects. So the occasional ``;;``, which itself is an alias for | ||||||
| an alias for :cmd:ref:`clean`, is a good idea in every synthesis script, e.g: | `clean`, is a good idea in every synthesis script, e.g: | ||||||
| 
 | 
 | ||||||
| .. code-block:: yoscrypt | .. code-block:: yoscrypt | ||||||
| 
 | 
 | ||||||
|  | @ -227,4 +229,4 @@ Other optimizations | ||||||
| - :doc:`/cmd/wreduce` | - :doc:`/cmd/wreduce` | ||||||
| - :doc:`/cmd/peepopt` | - :doc:`/cmd/peepopt` | ||||||
| - :doc:`/cmd/share` | - :doc:`/cmd/share` | ||||||
| - :cmd:ref:`abc` and :cmd:ref:`abc9`, see also: :doc:`abc`. | - `abc` and `abc9`, see also: :doc:`abc`. | ||||||
|  |  | ||||||
|  | @ -5,23 +5,23 @@ Converting process blocks | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
| 
 | 
 | ||||||
| The Verilog frontend converts ``always``-blocks to RTL netlists for the | The Verilog frontend converts ``always``-blocks to RTL netlists for the | ||||||
| expressions and "processess" for the control- and memory elements. The | expressions and "processess" for the control- and memory elements. The `proc` | ||||||
| :cmd:ref:`proc` command then transforms these "processess" to netlists of RTL | command then transforms these "processess" to netlists of RTL multiplexer and | ||||||
| multiplexer and register cells. It also is a macro command that calls the other | register cells. It also is a macro command that calls the other ``proc_*`` | ||||||
| ``proc_*`` commands in a sensible order: | commands in a sensible order: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /code_examples/macro_commands/proc.ys | .. literalinclude:: /code_examples/macro_commands/proc.ys | ||||||
|    :language: yoscrypt |    :language: yoscrypt | ||||||
|    :start-after: #end: |    :start-after: #end: | ||||||
|    :caption: Passes called by :cmd:ref:`proc` |    :caption: Passes called by `proc` | ||||||
| 
 | 
 | ||||||
| After all the ``proc_*`` commands, :cmd:ref:`opt_expr` is called. This can be | After all the ``proc_*`` commands, `opt_expr` is called. This can be disabled by | ||||||
| disabled by calling :yoscrypt:`proc -noopt`.  For more information about | calling :yoscrypt:`proc -noopt`.  For more information about `proc`, such as | ||||||
| :cmd:ref:`proc`, such as disabling certain sub commands, see :doc:`/cmd/proc`. | disabling certain sub commands, see :doc:`/cmd/proc`. | ||||||
| 
 | 
 | ||||||
| Many commands can not operate on modules with "processess" in them. Usually a | Many commands can not operate on modules with "processess" in them. Usually a | ||||||
| call to :cmd:ref:`proc` is the first command in the actual synthesis procedure | call to `proc` is the first command in the actual synthesis procedure after | ||||||
| after design elaboration. | design elaboration. | ||||||
| 
 | 
 | ||||||
| Example | Example | ||||||
| ^^^^^^^ | ^^^^^^^ | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ In addition to the above hardware-specific synth commands, there is also | ||||||
| getting into any architecture-specific mappings or optimizations.  Among other | getting into any architecture-specific mappings or optimizations.  Among other | ||||||
| things, this is useful for design verification. | things, this is useful for design verification. | ||||||
| 
 | 
 | ||||||
| The following commands are executed by the :cmd:ref:`prep` command: | The following commands are executed by the `prep` command: | ||||||
| 
 | 
 | ||||||
| .. literalinclude:: /cmd/prep.rst | .. literalinclude:: /cmd/prep.rst | ||||||
|    :start-at: begin: |    :start-at: begin: | ||||||
|  |  | ||||||
|  | @ -29,8 +29,8 @@ provided implementation. | ||||||
| 
 | 
 | ||||||
| When no map file is provided, techmap uses a built-in map file that maps the | When no map file is provided, techmap uses a built-in map file that maps the | ||||||
| Yosys RTL cell types to the internal gate library used by Yosys. The curious | Yosys RTL cell types to the internal gate library used by Yosys. The curious | ||||||
| reader may find this map file as `techlibs/common/techmap.v` in the Yosys source | reader may find this map file as :file:`techlibs/common/techmap.v` in the Yosys | ||||||
| tree. | source tree. | ||||||
| 
 | 
 | ||||||
| Additional features have been added to techmap to allow for conditional mapping | Additional features have been added to techmap to allow for conditional mapping | ||||||
| of cells (see :doc:`/cmd/techmap`). This can for example be useful if the target | of cells (see :doc:`/cmd/techmap`). This can for example be useful if the target | ||||||
|  |  | ||||||
|  | @ -11,17 +11,17 @@ Writing extensions | ||||||
| This chapter contains some bits and pieces of information about programming | This chapter contains some bits and pieces of information about programming | ||||||
| yosys extensions. Don't be afraid to ask questions on the YosysHQ Slack. | yosys extensions. Don't be afraid to ask questions on the YosysHQ Slack. | ||||||
| 
 | 
 | ||||||
| The `guidelines/` directory of the Yosys source code contains notes on various | The :file:`guidelines/` directory of the Yosys source code contains notes on | ||||||
| aspects of Yosys development. In particular, the files GettingStarted and | various aspects of Yosys development. In particular, the files GettingStarted | ||||||
| CodingStyle may be of interest. | and CodingStyle may be of interest. | ||||||
| 
 | 
 | ||||||
| .. todo:: what's in guidelines/GettingStarted that's missing from the manual? | .. todo:: what's in guidelines/GettingStarted that's missing from the manual? | ||||||
| 
 | 
 | ||||||
| Quick guide | Quick guide | ||||||
| ----------- | ----------- | ||||||
| 
 | 
 | ||||||
| Code examples from this section are included in the | Code examples from this section are included in the |code_examples/extensions|_ | ||||||
| |code_examples/extensions|_ directory of the Yosys source code. | directory of the Yosys source code. | ||||||
| 
 | 
 | ||||||
| .. |code_examples/extensions| replace:: :file:`docs/source/code_examples/extensions` | .. |code_examples/extensions| replace:: :file:`docs/source/code_examples/extensions` | ||||||
| .. _code_examples/extensions: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/extensions | .. _code_examples/extensions: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/extensions | ||||||
|  | @ -35,7 +35,7 @@ about the internal data storage format used in Yosys and the classes that it | ||||||
| provides. | provides. | ||||||
| 
 | 
 | ||||||
| This document will focus on the much simpler version of RTLIL left after the | This document will focus on the much simpler version of RTLIL left after the | ||||||
| commands :cmd:ref:`proc` and :cmd:ref:`memory` (or :yoscrypt:`memory -nomap`): | commands `proc` and `memory` (or :yoscrypt:`memory -nomap`): | ||||||
| 
 | 
 | ||||||
| .. figure:: /_images/internals/simplified_rtlil.* | .. figure:: /_images/internals/simplified_rtlil.* | ||||||
|     :class: width-helper invert-helper |     :class: width-helper invert-helper | ||||||
|  | @ -56,10 +56,9 @@ It is possible to only work on this simpler version: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| When trying to understand what a command does, creating a small test case to | When trying to understand what a command does, creating a small test case to | ||||||
| look at the output of :cmd:ref:`dump` and :cmd:ref:`show` before and after the | look at the output of `dump` and `show` before and after the command has been | ||||||
| command has been executed can be helpful. | executed can be helpful. :doc:`/using_yosys/more_scripting/selections` has more | ||||||
| :doc:`/using_yosys/more_scripting/selections` has more information on using | information on using these commands. | ||||||
| these commands. |  | ||||||
| 
 | 
 | ||||||
| Creating a command | Creating a command | ||||||
| ~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~ | ||||||
|  | @ -151,8 +150,8 @@ Most commands modify existing modules, not create new ones. | ||||||
| 
 | 
 | ||||||
| When modifying existing modules, stick to the following DOs and DON'Ts: | When modifying existing modules, stick to the following DOs and DON'Ts: | ||||||
| 
 | 
 | ||||||
| - Do not remove wires. Simply disconnect them and let a successive | - Do not remove wires. Simply disconnect them and let a successive `clean` | ||||||
|   :cmd:ref:`clean` command worry about removing it. |   command worry about removing it. | ||||||
| - Use ``module->fixup_ports()`` after changing the ``port_*`` properties of | - Use ``module->fixup_ports()`` after changing the ``port_*`` properties of | ||||||
|   wires. |   wires. | ||||||
| - You can safely remove cells or change the ``connections`` property of a cell, | - You can safely remove cells or change the ``connections`` property of a cell, | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ given in :doc:`/yosys_internals/formats/rtlil_rep`. | ||||||
| 
 | 
 | ||||||
| There is also a text representation of the RTLIL data structure that can be | There is also a text representation of the RTLIL data structure that can be | ||||||
| parsed using the RTLIL Frontend which is described in | parsed using the RTLIL Frontend which is described in | ||||||
| :doc:`/yosys_internals/formats/rtlil_text`. | :doc:`/appendix/rtlil_text`. | ||||||
| 
 | 
 | ||||||
| The design data may then be transformed using a series of passes that all | The design data may then be transformed using a series of passes that all | ||||||
| operate on the RTLIL representation of the design. | operate on the RTLIL representation of the design. | ||||||
|  |  | ||||||
|  | @ -599,16 +599,16 @@ The proc pass | ||||||
| 
 | 
 | ||||||
| The ProcessGenerator converts a behavioural model in AST representation to a | The ProcessGenerator converts a behavioural model in AST representation to a | ||||||
| behavioural model in ``RTLIL::Process`` representation. The actual conversion | behavioural model in ``RTLIL::Process`` representation. The actual conversion | ||||||
| from a behavioural model to an RTL representation is performed by the | from a behavioural model to an RTL representation is performed by the `proc` | ||||||
| :cmd:ref:`proc` pass and the passes it launches: | pass and the passes it launches: | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_clean` and :cmd:ref:`proc_rmdead`  | -  | `proc_clean` and `proc_rmdead`  | ||||||
|    | These two passes just clean up the ``RTLIL::Process`` structure. The |    | These two passes just clean up the ``RTLIL::Process`` structure. The | ||||||
|      :cmd:ref:`proc_clean` pass removes empty parts (eg. empty assignments) from |      `proc_clean` pass removes empty parts (eg. empty assignments) from the | ||||||
|      the process and :cmd:ref:`proc_rmdead` detects and removes unreachable |      process and `proc_rmdead` detects and removes unreachable branches from the | ||||||
|      branches from the process's decision trees. |      process's decision trees. | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_arst`  | -  | `proc_arst`  | ||||||
|    | This pass detects processes that describe d-type flip-flops with |    | This pass detects processes that describe d-type flip-flops with | ||||||
|      asynchronous resets and rewrites the process to better reflect what they |      asynchronous resets and rewrites the process to better reflect what they | ||||||
|      are modelling: Before this pass, an asynchronous reset has two |      are modelling: Before this pass, an asynchronous reset has two | ||||||
|  | @ -616,22 +616,22 @@ from a behavioural model to an RTL representation is performed by the | ||||||
|      reset path. After this pass the sync rule for the reset is level-sensitive |      reset path. After this pass the sync rule for the reset is level-sensitive | ||||||
|      and the top-level ``RTLIL::SwitchRule`` has been removed. |      and the top-level ``RTLIL::SwitchRule`` has been removed. | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_mux`  | -  | `proc_mux`  | ||||||
|    | This pass converts the ``RTLIL::CaseRule``/\ ``RTLIL::SwitchRule``-tree to a |    | This pass converts the ``RTLIL::CaseRule``/\ ``RTLIL::SwitchRule``-tree to | ||||||
|      tree of multiplexers per written signal. After this, the ``RTLIL::Process`` |      a tree of multiplexers per written signal. After this, the | ||||||
|      structure only contains the ``RTLIL::SyncRule`` s that describe the output |      ``RTLIL::Process`` structure only contains the ``RTLIL::SyncRule`` s that | ||||||
|      registers. |      describe the output registers. | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_dff` | -  | `proc_dff` | ||||||
|    | This pass replaces the ``RTLIL::SyncRule``\ s to d-type flip-flops (with |    | This pass replaces the ``RTLIL::SyncRule``\ s to d-type flip-flops (with | ||||||
|      asynchronous resets if necessary). |      asynchronous resets if necessary). | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_dff` | -  | `proc_dff` | ||||||
|    | This pass replaces the ``RTLIL::MemWriteAction``\ s with ``$memwr`` cells. |    | This pass replaces the ``RTLIL::MemWriteAction``\ s with `$memwr` cells. | ||||||
| 
 | 
 | ||||||
| -  | :cmd:ref:`proc_clean` | -  | `proc_clean` | ||||||
|    | A final call to :cmd:ref:`proc_clean` removes the now empty |    | A final call to `proc_clean` removes the now empty ``RTLIL::Process`` | ||||||
|      ``RTLIL::Process`` objects. |      objects. | ||||||
| 
 | 
 | ||||||
| Performing these last processing steps in passes instead of in the Verilog | Performing these last processing steps in passes instead of in the Verilog | ||||||
| frontend has two important benefits: | frontend has two important benefits: | ||||||
|  | @ -646,8 +646,8 @@ to extend the actual Verilog frontend. | ||||||
| 
 | 
 | ||||||
| .. todo:: Synthesizing Verilog arrays | .. todo:: Synthesizing Verilog arrays | ||||||
| 
 | 
 | ||||||
|   Add some information on the generation of ``$memrd`` and ``$memwr`` cells and |   Add some information on the generation of `$memrd` and `$memwr` cells and how | ||||||
|   how they are processed in the memory pass. |   they are processed in the memory pass. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .. todo:: Synthesizing parametric designs | .. todo:: Synthesizing parametric designs | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,13 +1,59 @@ | ||||||
| Internal formats | Internal formats | ||||||
| ================ | ================ | ||||||
| 
 | 
 | ||||||
| .. todo:: brief overview for the internal formats index | Yosys uses two different internal formats. The first is used to store an | ||||||
|  | abstract syntax tree (AST) of a Verilog input file. This format is simply called | ||||||
|  | AST and is generated by the Verilog Frontend. This data structure is consumed by | ||||||
|  | a subsystem called AST Frontend [1]_. This AST Frontend then generates a design | ||||||
|  | in Yosys' main internal format, the | ||||||
|  | Register-Transfer-Level-Intermediate-Language (RTLIL) representation. It does | ||||||
|  | that by first performing a number of simplifications within the AST | ||||||
|  | representation and then generating RTLIL from the simplified AST data structure. | ||||||
|  | 
 | ||||||
|  | The RTLIL representation is used by all passes as input and outputs. This has | ||||||
|  | the following advantages over using different representational formats between | ||||||
|  | different passes: | ||||||
|  | 
 | ||||||
|  | -  The passes can be rearranged in a different order and passes can be removed | ||||||
|  |    or inserted. | ||||||
|  | 
 | ||||||
|  | -  Passes can simply pass-thru the parts of the design they don't change without | ||||||
|  |    the need to convert between formats. In fact Yosys passes output the same | ||||||
|  |    data structure they received as input and performs all changes in place. | ||||||
|  | 
 | ||||||
|  | -  All passes use the same interface, thus reducing the effort required to | ||||||
|  |    understand a pass when reading the Yosys source code, e.g. when adding | ||||||
|  |    additional features. | ||||||
|  | 
 | ||||||
|  | The RTLIL representation is basically a netlist representation with the | ||||||
|  | following additional features: | ||||||
|  | 
 | ||||||
|  | -  An internal cell library with fixed-function cells to represent RTL datapath | ||||||
|  |    and register cells as well as logical gate-level cells (single-bit gates and | ||||||
|  |    registers). | ||||||
|  | 
 | ||||||
|  | -  Support for multi-bit values that can use individual bits from wires as well | ||||||
|  |    as constant bits to represent coarse-grain netlists. | ||||||
|  | 
 | ||||||
|  | -  Support for basic behavioural constructs (if-then-else structures and | ||||||
|  |    multi-case switches with a sensitivity list for updating the outputs). | ||||||
|  | 
 | ||||||
|  | -  Support for multi-port memories. | ||||||
|  | 
 | ||||||
|  | The use of RTLIL also has the disadvantage of having a very powerful format | ||||||
|  | between all passes, even when doing gate-level synthesis where the more advanced | ||||||
|  | features are not needed. In order to reduce complexity for passes that operate | ||||||
|  | on a low-level representation, these passes check the features used in the input | ||||||
|  | RTLIL and fail to run when unsupported high-level constructs are used. In such | ||||||
|  | cases a pass that transforms the higher-level constructs to lower-level | ||||||
|  | constructs must be called from the synthesis script first. | ||||||
| 
 | 
 | ||||||
| .. toctree::  | .. toctree::  | ||||||
|    :maxdepth: 3 |    :maxdepth: 3 | ||||||
| 
 | 
 | ||||||
| 	overview |  | ||||||
|    rtlil_rep |    rtlil_rep | ||||||
| 	rtlil_text | 
 | ||||||
| 	cell_library | .. [1] | ||||||
|  |    In Yosys the term pass is only used to refer to commands that operate on the | ||||||
|  |    RTLIL data structure. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,53 +0,0 @@ | ||||||
| Format overview |  | ||||||
| =============== |  | ||||||
| 
 |  | ||||||
| Yosys uses two different internal formats. The first is used to store an |  | ||||||
| abstract syntax tree (AST) of a Verilog input file. This format is simply called |  | ||||||
| AST and is generated by the Verilog Frontend. This data structure is consumed by |  | ||||||
| a subsystem called AST Frontend [1]_. This AST Frontend then generates a design |  | ||||||
| in Yosys' main internal format, the |  | ||||||
| Register-Transfer-Level-Intermediate-Language (RTLIL) representation. It does |  | ||||||
| that by first performing a number of simplifications within the AST |  | ||||||
| representation and then generating RTLIL from the simplified AST data structure. |  | ||||||
| 
 |  | ||||||
| The RTLIL representation is used by all passes as input and outputs. This has |  | ||||||
| the following advantages over using different representational formats between |  | ||||||
| different passes: |  | ||||||
| 
 |  | ||||||
| -  The passes can be rearranged in a different order and passes can be removed |  | ||||||
|    or inserted. |  | ||||||
| 
 |  | ||||||
| -  Passes can simply pass-thru the parts of the design they don't change without |  | ||||||
|    the need to convert between formats. In fact Yosys passes output the same |  | ||||||
|    data structure they received as input and performs all changes in place. |  | ||||||
| 
 |  | ||||||
| -  All passes use the same interface, thus reducing the effort required to |  | ||||||
|    understand a pass when reading the Yosys source code, e.g. when adding |  | ||||||
|    additional features. |  | ||||||
| 
 |  | ||||||
| The RTLIL representation is basically a netlist representation with the |  | ||||||
| following additional features: |  | ||||||
| 
 |  | ||||||
| -  An internal cell library with fixed-function cells to represent RTL datapath |  | ||||||
|    and register cells as well as logical gate-level cells (single-bit gates and |  | ||||||
|    registers). |  | ||||||
| 
 |  | ||||||
| -  Support for multi-bit values that can use individual bits from wires as well |  | ||||||
|    as constant bits to represent coarse-grain netlists. |  | ||||||
| 
 |  | ||||||
| -  Support for basic behavioural constructs (if-then-else structures and |  | ||||||
|    multi-case switches with a sensitivity list for updating the outputs). |  | ||||||
| 
 |  | ||||||
| -  Support for multi-port memories. |  | ||||||
| 
 |  | ||||||
| The use of RTLIL also has the disadvantage of having a very powerful format |  | ||||||
| between all passes, even when doing gate-level synthesis where the more advanced |  | ||||||
| features are not needed. In order to reduce complexity for passes that operate |  | ||||||
| on a low-level representation, these passes check the features used in the input |  | ||||||
| RTLIL and fail to run when unsupported high-level constructs are used. In such |  | ||||||
| cases a pass that transforms the higher-level constructs to lower-level |  | ||||||
| constructs must be called from the synthesis script first. |  | ||||||
| 
 |  | ||||||
| .. [1] |  | ||||||
|    In Yosys the term pass is only used to refer to commands that operate on the |  | ||||||
|    RTLIL data structure. |  | ||||||
|  | @ -76,11 +76,10 @@ This has three advantages: | ||||||
| 
 | 
 | ||||||
| -  Second, the information about which identifiers were originally provided by | -  Second, the information about which identifiers were originally provided by | ||||||
|    the user is always available which can help guide some optimizations. For |    the user is always available which can help guide some optimizations. For | ||||||
|    example, :cmd:ref:`opt_clean` tries to preserve signals with a user-provided |    example, `opt_clean` tries to preserve signals with a user-provided name but | ||||||
|    name but doesn't hesitate to delete signals that have auto-generated names |    doesn't hesitate to delete signals that have auto-generated names when they | ||||||
|    when they just duplicate other signals.  Note that this can be overridden |    just duplicate other signals.  Note that this can be overridden with the | ||||||
|    with the `-purge` option to also delete internal nets with user-provided |    ``-purge`` option to also delete internal nets with user-provided names. | ||||||
|    names. |  | ||||||
| 
 | 
 | ||||||
| -  Third, the delicate job of finding suitable auto-generated public visible | -  Third, the delicate job of finding suitable auto-generated public visible | ||||||
|    names is deferred to one central location. Internally auto-generated names |    names is deferred to one central location. Internally auto-generated names | ||||||
|  | @ -204,8 +203,8 @@ A "signal" is everything that can be applied to a cell port. I.e. | ||||||
| -  | Concatenations of the above | -  | Concatenations of the above | ||||||
|    | 1em For example: ``{16'd1337, mywire[15:8]}`` |    | 1em For example: ``{16'd1337, mywire[15:8]}`` | ||||||
| 
 | 
 | ||||||
| The ``RTLIL::SigSpec`` data type is used to represent signals. The ``RTLIL::Cell`` | The ``RTLIL::SigSpec`` data type is used to represent signals. The | ||||||
| object contains one ``RTLIL::SigSpec`` for each cell port. | ``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port. | ||||||
| 
 | 
 | ||||||
| In addition, connections between wires are represented using a pair of | In addition, connections between wires are represented using a pair of | ||||||
| ``RTLIL::SigSpec`` objects. Such pairs are needed in different locations. | ``RTLIL::SigSpec`` objects. Such pairs are needed in different locations. | ||||||
|  | @ -234,9 +233,9 @@ control logic of the behavioural code. Let's consider a simple example: | ||||||
|            q <= d; |            q <= d; | ||||||
|    endmodule |    endmodule | ||||||
| 
 | 
 | ||||||
| In this example there is no data path and therefore the ``RTLIL::Module`` generated | In this example there is no data path and therefore the ``RTLIL::Module`` | ||||||
| by the frontend only contains a few ``RTLIL::Wire`` objects and an ``RTLIL::Process`` . | generated by the frontend only contains a few ``RTLIL::Wire`` objects and an | ||||||
| The ``RTLIL::Process`` in RTLIL syntax: | ``RTLIL::Process``. The ``RTLIL::Process`` in RTLIL syntax: | ||||||
| 
 | 
 | ||||||
| .. code:: RTLIL | .. code:: RTLIL | ||||||
|    :number-lines: |    :number-lines: | ||||||
|  | @ -320,8 +319,8 @@ trees before further processing them. | ||||||
| 
 | 
 | ||||||
| One of the first actions performed on a design in RTLIL representation in most | 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 | synthesis scripts is identifying asynchronous resets. This is usually done using | ||||||
| the :cmd:ref:`proc_arst` pass. This pass transforms the above example to the | the `proc_arst` pass. This pass transforms the above example to the following | ||||||
| following ``RTLIL::Process``: | ``RTLIL::Process``: | ||||||
| 
 | 
 | ||||||
| .. code:: RTLIL | .. code:: RTLIL | ||||||
|    :number-lines: |    :number-lines: | ||||||
|  | @ -340,9 +339,9 @@ following ``RTLIL::Process``: | ||||||
|    end |    end | ||||||
| 
 | 
 | ||||||
| This pass has transformed the outer ``RTLIL::SwitchRule`` into a modified | This pass has transformed the outer ``RTLIL::SwitchRule`` into a modified | ||||||
| ``RTLIL::SyncRule`` object for the ``\reset`` signal. Further processing converts the | ``RTLIL::SyncRule`` object for the ``\reset`` signal. Further processing | ||||||
| ``RTLIL::Process`` into e.g. a d-type flip-flop with asynchronous reset and a | converts the ``RTLIL::Process`` into e.g. a d-type flip-flop with asynchronous | ||||||
| multiplexer for the enable signal: | reset and a multiplexer for the enable signal: | ||||||
| 
 | 
 | ||||||
| .. code:: RTLIL | .. code:: RTLIL | ||||||
|    :number-lines: |    :number-lines: | ||||||
|  | @ -365,9 +364,9 @@ multiplexer for the enable signal: | ||||||
|        connect \Y $0\q[0:0] |        connect \Y $0\q[0:0] | ||||||
|    end |    end | ||||||
| 
 | 
 | ||||||
| Different combinations of passes may yield different results. Note that | Different combinations of passes may yield different results. Note that `$adff` | ||||||
| ``$adff`` and ``$mux`` are internal cell types that still need to be mapped to | and `$mux` are internal cell types that still need to be mapped to cell types | ||||||
| cell types from the target cell library. | 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. | objects as the presence of these objects in a module increases the complexity. | ||||||
|  | @ -389,25 +388,25 @@ A memory object has the following properties: | ||||||
| -  The width of an addressable word | -  The width of an addressable word | ||||||
| -  The size of the memory in number of words | -  The size of the memory in number of words | ||||||
| 
 | 
 | ||||||
| All read accesses to the memory are transformed to ``$memrd`` cells and all | All read accesses to the memory are transformed to `$memrd` cells and all write | ||||||
| write accesses to ``$memwr`` cells by the language frontend. These cells consist | accesses to `$memwr` cells by the language frontend. These cells consist of | ||||||
| of independent read- and write-ports to the memory. Memory initialization is | independent read- and write-ports to the memory. Memory initialization is | ||||||
| transformed to ``$meminit`` cells by the language frontend. The ``\MEMID`` | transformed to `$meminit` cells by the language frontend. The ``\MEMID`` | ||||||
| parameter on these cells is used to link them together and to the | parameter on these cells is used to link them together and to the | ||||||
| ``RTLIL::Memory`` object they belong to. | ``RTLIL::Memory`` object they belong to. | ||||||
| 
 | 
 | ||||||
| The rationale behind using separate cells for the individual ports versus | The rationale behind using separate cells for the individual ports versus | ||||||
| creating a large multiport memory cell right in the language frontend is that | creating a large multiport memory cell right in the language frontend is that | ||||||
| the separate ``$memrd`` and ``$memwr`` cells can be consolidated using resource | the separate `$memrd` and `$memwr` cells can be consolidated using resource | ||||||
| sharing. As resource sharing is a non-trivial optimization problem where | sharing. As resource sharing is a non-trivial optimization problem where | ||||||
| different synthesis tasks can have different requirements it lends itself to do | different synthesis tasks can have different requirements it lends itself to do | ||||||
| the optimisation in separate passes and merge the ``RTLIL::Memory`` objects and | the optimisation in separate passes and merge the ``RTLIL::Memory`` objects and | ||||||
| ``$memrd`` and ``$memwr`` cells to multiport memory blocks after resource | `$memrd` and `$memwr` cells to multiport memory blocks after resource sharing is | ||||||
| sharing is completed. | completed. | ||||||
| 
 | 
 | ||||||
| The memory pass performs this conversion and can (depending on the options | 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 | 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. | See :ref:`sec:memcells` for details about the memory cell types. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| Techmap by example | Techmap by example | ||||||
| ------------------ | ------------------ | ||||||
| 
 | 
 | ||||||
| As a quick recap, the :cmd:ref:`techmap` command replaces cells in the design | As a quick recap, the `techmap` command replaces cells in the design with | ||||||
| with implementations given as Verilog code (called "map files"). It can replace | implementations given as Verilog code (called "map files"). It can replace | ||||||
| Yosys' internal cell types (such as ``$or``) as well as user-defined cell types. | Yosys' internal cell types (such as `$or`) as well as user-defined cell types. | ||||||
| 
 | 
 | ||||||
| - Verilog parameters are used extensively to customize the internal cell types. | - Verilog parameters are used extensively to customize the internal cell types. | ||||||
| - Additional special parameters are used by techmap to communicate meta-data to | - Additional special parameters are used by techmap to communicate meta-data to | ||||||
|  | @ -87,15 +87,15 @@ Scripting in map modules | ||||||
| - You can even call techmap recursively! | - You can even call techmap recursively! | ||||||
| - Example use-cases: | - Example use-cases: | ||||||
| 
 | 
 | ||||||
|     - Using always blocks in map module: call :cmd:ref:`proc` |     - Using always blocks in map module: call `proc` | ||||||
|     - Perform expensive optimizations (such as :cmd:ref:`freduce`) on cells |     - Perform expensive optimizations (such as `freduce`) on cells | ||||||
|       where this is known to work well. |       where this is known to work well. | ||||||
|     - Interacting with custom commands. |     - Interacting with custom commands. | ||||||
| 
 | 
 | ||||||
| .. note:: PROTIP: | .. note:: PROTIP: | ||||||
| 
 | 
 | ||||||
|     Commands such as :cmd:ref:`shell`, ``show -pause``, and :cmd:ref:`dump` can |     Commands such as `shell`, ``show -pause``, and `dump` can be used in the | ||||||
|     be used in the ``_TECHMAP_DO_*`` scripts for debugging map modules. |     ``_TECHMAP_DO_*`` scripts for debugging map modules. | ||||||
| 
 | 
 | ||||||
| Example: | Example: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,73 +0,0 @@ | ||||||
| from pygments.lexer import RegexLexer, bygroups, include |  | ||||||
| from pygments.token import (Comment, Error, Keyword, Name, Number, Operator, |  | ||||||
|                             String, Whitespace) |  | ||||||
| 
 |  | ||||||
| __all__ = ['YoscryptLexer'] |  | ||||||
| 
 |  | ||||||
| class YoscryptLexer(RegexLexer): |  | ||||||
|     name = 'Yosys Script' |  | ||||||
|     aliases = ['yoscrypt'] |  | ||||||
|     filenames = ['*.ys'] |  | ||||||
|      |  | ||||||
|      |  | ||||||
|      |  | ||||||
|     tokens = { |  | ||||||
|         'common': [ |  | ||||||
|             (r'\s+', Whitespace), |  | ||||||
|             (r'#.*', Comment.Single), |  | ||||||
|             (r'"', String, 'string'), |  | ||||||
|             (r'(\d+)(\')([bdho]? ?\w+)', bygroups(Number, Operator, Number)), |  | ||||||
|             (r'(\d+\.\d+)', Number.Float), |  | ||||||
|             (r'(\d+)', Number), |  | ||||||
|             (r'(\$[A-Za-z_0-9]*)', Name.Builtin), |  | ||||||
|             (r'([A-Za-z_][A-Za-z_0-9\.\\/:-]*)', Name), |  | ||||||
|             (r'(\[)(-\S*)(\])', # optional command |  | ||||||
|              	bygroups(Operator, Name.Attribute, Operator)), |  | ||||||
|             (r'([\[<]\w*[\]>])', Name), # arguments |  | ||||||
|             (r'[\{\}\|=\[\],]', Operator), |  | ||||||
|             (r'.', Comment), |  | ||||||
|         ], |  | ||||||
|         'root': [ |  | ||||||
|             (r'([A-Za-z_][A-Za-z_0-9]*)', Keyword, 'command'), |  | ||||||
|             (r'(-[A-Za-z_][A-Za-z_0-9]*)', Name.Attribute, 'command'), # shortcut for options |  | ||||||
|             include('common'), |  | ||||||
|         ], |  | ||||||
|         'command': [ |  | ||||||
|             (r'(-[A-Za-z_][A-Za-z_0-9]*)', Name.Attribute), |  | ||||||
|             (r'\+/[^\s]+', Name.Class), |  | ||||||
|             (r'$', Whitespace, '#pop'), |  | ||||||
|             (r';(?=\s)', Operator, '#pop'), |  | ||||||
|             (r';{2,3}(?=\s)', Name.Class, '#pop'), |  | ||||||
|             (r';{1,3}', Error, '#pop'), |  | ||||||
|             (r'([ANwismctparn]:)', Keyword.Type, 'pattern'), |  | ||||||
|             (r'@', Keyword.Type), |  | ||||||
|             (r'%(x|ci|co)e?', Keyword.Type, 'expansion'), |  | ||||||
|             (r'%[%nuidDcasmMCR]?', Keyword.Type), |  | ||||||
|             (r'/', Operator), |  | ||||||
|             include('common'), |  | ||||||
|         ], |  | ||||||
|         'pattern': [ |  | ||||||
|             (r'<<', Name), # Not an operator |  | ||||||
|             (r'(=|<|<=|>|>=)', Operator), |  | ||||||
|             (r':', Keyword.Type), |  | ||||||
|             (r'$', Whitespace, '#pop:2'), |  | ||||||
|             (r'\s+', Whitespace, '#pop'), |  | ||||||
|             include('common'), |  | ||||||
|         ], |  | ||||||
|         'expansion': [ |  | ||||||
|             (r'$', Name.Class, '#pop:2'), |  | ||||||
|             (r';(?=\s)', Operator, '#pop:2'), |  | ||||||
|             (r';{2,3}(?=\s)', Name.Class, '#pop:2'), |  | ||||||
|             (r'\s', Whitespace, '#pop'), |  | ||||||
|             (r'[0-9\*]{1,3}', Number), |  | ||||||
|             (r'[:+-,\[\]]', Operator), |  | ||||||
|             include('common'), |  | ||||||
|         ], |  | ||||||
|         'string': [ |  | ||||||
|             (r'"', String, '#pop'), |  | ||||||
|             (r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|[0-7]{1,3})', String.Escape), |  | ||||||
|             (r'[^\\"\n]+', String),  # all other characters |  | ||||||
|             (r'(\\)(\n)', bygroups(String.Escape, Whitespace)),  # line continuation |  | ||||||
|             (r'\\', String),  # stray backslash |  | ||||||
|         ] |  | ||||||
|     } |  | ||||||
							
								
								
									
										415
									
								
								docs/util/cellref.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								docs/util/cellref.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,415 @@ | ||||||
|  | #!/usr/bin/env python3 | ||||||
|  | from __future__ import annotations | ||||||
|  | 
 | ||||||
|  | from dataclasses import dataclass | ||||||
|  | import json | ||||||
|  | from pathlib import Path, PosixPath, WindowsPath | ||||||
|  | import re | ||||||
|  | 
 | ||||||
|  | from typing import Any | ||||||
|  | from sphinx.application import Sphinx | ||||||
|  | from sphinx.ext import autodoc | ||||||
|  | from sphinx.ext.autodoc import Documenter | ||||||
|  | from sphinx.util import logging | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
|  | # cell signature | ||||||
|  | cell_ext_sig_re = re.compile( | ||||||
|  |     r'''^ ([^:\s]+::)?           # optional group or file name | ||||||
|  |           ([\w$._]+?)            # module name | ||||||
|  |           (?:\.([\w_]+))?        # optional: thing name | ||||||
|  |           (::[\w_]+)?            #           attribute | ||||||
|  |           \s* $                  # and nothing more | ||||||
|  |           ''', re.VERBOSE) | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class YosysCell: | ||||||
|  |     name: str | ||||||
|  |     title: str | ||||||
|  |     ports: str | ||||||
|  |     source: str | ||||||
|  |     desc: str | ||||||
|  |     code: str | ||||||
|  |     inputs: list[str] | ||||||
|  |     outputs: list[str] | ||||||
|  |     properties: list[str] | ||||||
|  |      | ||||||
|  | class YosysCellGroupDocumenter(Documenter): | ||||||
|  |     objtype = 'cellgroup' | ||||||
|  |     priority = 10 | ||||||
|  |     object: tuple[str, list[str]] | ||||||
|  |     lib_key = 'groups' | ||||||
|  | 
 | ||||||
|  |     option_spec = { | ||||||
|  |         'caption': autodoc.annotation_option, | ||||||
|  |         'members': autodoc.members_option, | ||||||
|  |         'source': autodoc.bool_option, | ||||||
|  |         'linenos': autodoc.bool_option, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     __cell_lib: dict[str, list[str] | dict[str]] | None = None | ||||||
|  |     @property | ||||||
|  |     def cell_lib(self) -> dict[str, list[str] | dict[str]]: | ||||||
|  |         if not self.__cell_lib: | ||||||
|  |             self.__cell_lib = {} | ||||||
|  |             cells_obj: dict[str, dict[str, list[str] | dict[str]]] | ||||||
|  |             try: | ||||||
|  |                 with open(self.config.cells_json, "r") as f: | ||||||
|  |                     cells_obj = json.loads(f.read()) | ||||||
|  |             except FileNotFoundError: | ||||||
|  |                 logger.warning( | ||||||
|  |                     f"unable to find cell lib at {self.config.cells_json}", | ||||||
|  |                     type = 'cellref', | ||||||
|  |                     subtype = 'cell_lib' | ||||||
|  |                 ) | ||||||
|  |             else: | ||||||
|  |                 for (name, obj) in cells_obj.get(self.lib_key, {}).items(): | ||||||
|  |                     self.__cell_lib[name] = obj | ||||||
|  |         return self.__cell_lib | ||||||
|  |      | ||||||
|  |     @classmethod | ||||||
|  |     def can_document_member( | ||||||
|  |         cls, | ||||||
|  |         member: Any, | ||||||
|  |         membername: str, | ||||||
|  |         isattr: bool, | ||||||
|  |         parent: Any | ||||||
|  |     ) -> bool: | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     def parse_name(self) -> bool: | ||||||
|  |         if not self.options.caption: | ||||||
|  |             self.content_indent = '' | ||||||
|  |         self.fullname = self.modname = self.name | ||||||
|  |         return True | ||||||
|  |      | ||||||
|  |     def import_object(self, raiseerror: bool = False) -> bool: | ||||||
|  |         # get cell | ||||||
|  |         try: | ||||||
|  |             self.object = (self.modname, self.cell_lib[self.modname]) | ||||||
|  |         except KeyError: | ||||||
|  |             if raiseerror: | ||||||
|  |                 raise | ||||||
|  |             return False | ||||||
|  | 
 | ||||||
|  |         self.real_modname = self.modname | ||||||
|  |         return True | ||||||
|  |      | ||||||
|  |     def get_sourcename(self) -> str: | ||||||
|  |         return self.env.doc2path(self.env.docname) | ||||||
|  |      | ||||||
|  |     def format_name(self) -> str: | ||||||
|  |         return self.options.caption or '' | ||||||
|  | 
 | ||||||
|  |     def format_signature(self, **kwargs: Any) -> str: | ||||||
|  |         return self.modname | ||||||
|  |      | ||||||
|  |     def add_directive_header(self, sig: str) -> None: | ||||||
|  |         domain = getattr(self, 'domain', 'cell') | ||||||
|  |         directive = getattr(self, 'directivetype', 'group') | ||||||
|  |         name = self.format_name() | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         cell_list = self.object | ||||||
|  | 
 | ||||||
|  |         # cell definition | ||||||
|  |         self.add_line(f'.. {domain}:{directive}:: {sig}', sourcename) | ||||||
|  |         self.add_line(f'   :caption: {name}', sourcename) | ||||||
|  | 
 | ||||||
|  |         if self.options.noindex: | ||||||
|  |             self.add_line('   :noindex:', sourcename) | ||||||
|  |      | ||||||
|  |     def add_content(self, more_content: Any | None) -> None: | ||||||
|  |         # groups have no native content | ||||||
|  |         # add additional content (e.g. from document), if present | ||||||
|  |         if more_content: | ||||||
|  |             for line, src in zip(more_content.data, more_content.items): | ||||||
|  |                 self.add_line(line, src[0], src[1]) | ||||||
|  | 
 | ||||||
|  |     def filter_members( | ||||||
|  |         self, | ||||||
|  |         members: list[tuple[str, Any]], | ||||||
|  |         want_all: bool | ||||||
|  |     ) -> list[tuple[str, Any, bool]]: | ||||||
|  |         return [(x[0], x[1], False) for x in members] | ||||||
|  | 
 | ||||||
|  |     def get_object_members( | ||||||
|  |         self, | ||||||
|  |         want_all: bool | ||||||
|  |     ) -> tuple[bool, list[tuple[str, Any]]]: | ||||||
|  |         ret: list[tuple[str, str]] = [] | ||||||
|  | 
 | ||||||
|  |         if want_all: | ||||||
|  |             for member in self.object[1]: | ||||||
|  |                 ret.append((member, self.modname)) | ||||||
|  |         else: | ||||||
|  |             memberlist = self.options.members or [] | ||||||
|  |             for name in memberlist: | ||||||
|  |                 if name in self.object: | ||||||
|  |                     ret.append((name, self.modname)) | ||||||
|  |                 else: | ||||||
|  |                     logger.warning(('unknown module mentioned in :members: option: ' | ||||||
|  |                                     f'group {self.modname}, module {name}'), | ||||||
|  |                                    type='cellref') | ||||||
|  | 
 | ||||||
|  |         return False, ret | ||||||
|  | 
 | ||||||
|  |     def document_members(self, all_members: bool = False) -> None: | ||||||
|  |         want_all = (all_members or | ||||||
|  |                     self.options.inherited_members or | ||||||
|  |                     self.options.members is autodoc.ALL) | ||||||
|  |         # find out which members are documentable | ||||||
|  |         members_check_module, members = self.get_object_members(want_all) | ||||||
|  | 
 | ||||||
|  |         # document non-skipped members | ||||||
|  |         memberdocumenters: list[tuple[Documenter, bool]] = [] | ||||||
|  |         for (mname, member, isattr) in self.filter_members(members, want_all): | ||||||
|  |             classes = [cls for cls in self.documenters.values() | ||||||
|  |                        if cls.can_document_member(member, mname, isattr, self)] | ||||||
|  |             if not classes: | ||||||
|  |                 # don't know how to document this member | ||||||
|  |                 continue | ||||||
|  |             # prefer the documenter with the highest priority | ||||||
|  |             classes.sort(key=lambda cls: cls.priority) | ||||||
|  |             # give explicitly separated module name, so that members | ||||||
|  |             # of inner classes can be documented | ||||||
|  |             full_mname = self.format_signature() + '::' + mname | ||||||
|  |             documenter = classes[-1](self.directive, full_mname, self.indent) | ||||||
|  |             memberdocumenters.append((documenter, isattr)) | ||||||
|  | 
 | ||||||
|  |         member_order = self.options.member_order or self.config.autodoc_member_order | ||||||
|  |         memberdocumenters = self.sort_members(memberdocumenters, member_order) | ||||||
|  | 
 | ||||||
|  |         for documenter, isattr in memberdocumenters: | ||||||
|  |             documenter.generate( | ||||||
|  |                 all_members=True, real_modname=self.real_modname, | ||||||
|  |                 check_module=members_check_module and not isattr) | ||||||
|  | 
 | ||||||
|  |     def generate( | ||||||
|  |         self, | ||||||
|  |         more_content: Any | None = None, | ||||||
|  |         real_modname: str | None = None, | ||||||
|  |         check_module: bool = False, | ||||||
|  |         all_members: bool = False | ||||||
|  |     ) -> None: | ||||||
|  |         if not self.parse_name(): | ||||||
|  |             # need a cell lib to import from | ||||||
|  |             logger.warning( | ||||||
|  |                 f"don't know which cell lib to import for autodocumenting {self.name}", | ||||||
|  |                 type = 'cellref' | ||||||
|  |             ) | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         if not self.import_object(): | ||||||
|  |             logger.warning( | ||||||
|  |                 f"unable to load {self.name}", | ||||||
|  |                 type = 'cellref' | ||||||
|  |             ) | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         # check __module__ of object (for members not given explicitly) | ||||||
|  |         # if check_module: | ||||||
|  |         #     if not self.check_module(): | ||||||
|  |         #         return | ||||||
|  | 
 | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         self.add_line('', sourcename) | ||||||
|  | 
 | ||||||
|  |         # format the object's signature, if any | ||||||
|  |         try: | ||||||
|  |             sig = self.format_signature() | ||||||
|  |         except Exception as exc: | ||||||
|  |             logger.warning(('error while formatting signature for %s: %s'), | ||||||
|  |                            self.fullname, exc, type='cellref') | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         # generate the directive header and options, if applicable | ||||||
|  |         self.add_directive_header(sig) | ||||||
|  |         self.add_line('', sourcename) | ||||||
|  | 
 | ||||||
|  |         # e.g. the module directive doesn't have content | ||||||
|  |         self.indent += self.content_indent | ||||||
|  | 
 | ||||||
|  |         # add all content (from docstrings, attribute docs etc.) | ||||||
|  |         self.add_content(more_content) | ||||||
|  | 
 | ||||||
|  |         # document members, if possible | ||||||
|  |         self.document_members(all_members) | ||||||
|  | 
 | ||||||
|  | class YosysCellDocumenter(YosysCellGroupDocumenter): | ||||||
|  |     objtype = 'cell' | ||||||
|  |     priority = 15 | ||||||
|  |     object: YosysCell | ||||||
|  |     lib_key = 'cells' | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def can_document_member( | ||||||
|  |         cls, | ||||||
|  |         member: Any, | ||||||
|  |         membername: str, | ||||||
|  |         isattr: bool, | ||||||
|  |         parent: Any | ||||||
|  |     ) -> bool: | ||||||
|  |         if membername == "__source": | ||||||
|  |             return False | ||||||
|  |         if not membername.startswith('$'): | ||||||
|  |             return False | ||||||
|  |         return isinstance(parent, YosysCellGroupDocumenter) | ||||||
|  | 
 | ||||||
|  |     def parse_name(self) -> bool: | ||||||
|  |         try: | ||||||
|  |             matched = cell_ext_sig_re.match(self.name) | ||||||
|  |             group, modname, thing, attribute = matched.groups() | ||||||
|  |         except AttributeError: | ||||||
|  |             logger.warning(('invalid signature for auto%s (%r)') % (self.objtype, self.name), | ||||||
|  |                            type='cellref') | ||||||
|  |             return False | ||||||
|  | 
 | ||||||
|  |         self.modname = modname | ||||||
|  |         self.groupname = group or '' | ||||||
|  |         self.attribute = attribute or '' | ||||||
|  |         self.fullname = ((self.modname) + (thing or '')) | ||||||
|  | 
 | ||||||
|  |         return True | ||||||
|  |      | ||||||
|  |     def import_object(self, raiseerror: bool = False) -> bool: | ||||||
|  |         if super().import_object(raiseerror): | ||||||
|  |             self.object = YosysCell(self.modname, **self.object[1]) | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  |      | ||||||
|  |     def get_sourcename(self) -> str: | ||||||
|  |         return self.object.source.split(":")[0] | ||||||
|  |      | ||||||
|  |     def format_name(self) -> str: | ||||||
|  |         return self.object.name | ||||||
|  | 
 | ||||||
|  |     def format_signature(self, **kwargs: Any) -> str: | ||||||
|  |         return self.groupname + self.fullname + self.attribute | ||||||
|  |      | ||||||
|  |     def add_directive_header(self, sig: str) -> None: | ||||||
|  |         domain = getattr(self, 'domain', self.objtype) | ||||||
|  |         directive = getattr(self, 'directivetype', 'def') | ||||||
|  |         name = self.format_name() | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         cell = self.object | ||||||
|  | 
 | ||||||
|  |         # cell definition | ||||||
|  |         self.add_line(f'.. {domain}:{directive}:: {sig}', sourcename) | ||||||
|  | 
 | ||||||
|  |         # options | ||||||
|  |         opt_attrs = ["title", "properties", ] | ||||||
|  |         for attr in opt_attrs: | ||||||
|  |             val = getattr(cell, attr, None) | ||||||
|  |             if isinstance(val, list): | ||||||
|  |                 val = ' '.join(val) | ||||||
|  |             if val: | ||||||
|  |                 self.add_line(f'   :{attr}: {val}', sourcename) | ||||||
|  | 
 | ||||||
|  |         self.add_line('\n', sourcename) | ||||||
|  | 
 | ||||||
|  |         if self.options.noindex: | ||||||
|  |             self.add_line('   :noindex:', sourcename) | ||||||
|  |      | ||||||
|  |     def add_content(self, more_content: Any | None) -> None: | ||||||
|  |         # set sourcename and add content from attribute documentation | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         startline = int(self.object.source.split(":")[1]) | ||||||
|  | 
 | ||||||
|  |         for i, line in enumerate(self.object.desc.splitlines(), startline): | ||||||
|  |             self.add_line(line, sourcename, i) | ||||||
|  | 
 | ||||||
|  |         # add additional content (e.g. from document), if present | ||||||
|  |         if more_content: | ||||||
|  |             for line, src in zip(more_content.data, more_content.items): | ||||||
|  |                 self.add_line(line, src[0], src[1]) | ||||||
|  | 
 | ||||||
|  |         # fields | ||||||
|  |         self.add_line('\n', sourcename) | ||||||
|  |         field_attrs = ["properties", ] | ||||||
|  |         for field in field_attrs: | ||||||
|  |             attr = getattr(self.object, field, []) | ||||||
|  |             for val in attr: | ||||||
|  |                 self.add_line(f':{field} {val}:', sourcename) | ||||||
|  | 
 | ||||||
|  |     def get_object_members( | ||||||
|  |         self, | ||||||
|  |         want_all: bool | ||||||
|  |     ) -> tuple[bool, list[tuple[str, Any]]]: | ||||||
|  |         ret: list[tuple[str, str]] = [] | ||||||
|  | 
 | ||||||
|  |         if self.options.source: | ||||||
|  |             ret.append(('__source', self.real_modname)) | ||||||
|  | 
 | ||||||
|  |         return False, ret | ||||||
|  | 
 | ||||||
|  | class YosysCellSourceDocumenter(YosysCellDocumenter): | ||||||
|  |     objtype = 'cellsource' | ||||||
|  |     priority = 20 | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def can_document_member( | ||||||
|  |         cls, | ||||||
|  |         member: Any, | ||||||
|  |         membername: str, | ||||||
|  |         isattr: bool, | ||||||
|  |         parent: Any | ||||||
|  |     ) -> bool: | ||||||
|  |         if membername != "__source": | ||||||
|  |             return False | ||||||
|  |         if isinstance(parent, YosysCellDocumenter): | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  |      | ||||||
|  |     def add_directive_header(self, sig: str) -> None: | ||||||
|  |         domain = getattr(self, 'domain', 'cell') | ||||||
|  |         directive = getattr(self, 'directivetype', 'source') | ||||||
|  |         name = self.format_name() | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         cell = self.object | ||||||
|  | 
 | ||||||
|  |         # cell definition | ||||||
|  |         self.add_line(f'.. {domain}:{directive}:: {sig}', sourcename) | ||||||
|  | 
 | ||||||
|  |         if self.options.linenos: | ||||||
|  |             self.add_line(f'   :source: {cell.source.split(":")[0]}', sourcename) | ||||||
|  |         else: | ||||||
|  |             self.add_line(f'   :source: {cell.source}', sourcename) | ||||||
|  |         self.add_line(f'   :language: verilog', sourcename) | ||||||
|  | 
 | ||||||
|  |         if self.options.linenos: | ||||||
|  |             startline = int(self.object.source.split(":")[1]) | ||||||
|  |             self.add_line(f'   :lineno-start: {startline}', sourcename) | ||||||
|  | 
 | ||||||
|  |         if self.options.noindex: | ||||||
|  |             self.add_line('   :noindex:', sourcename) | ||||||
|  |      | ||||||
|  |     def add_content(self, more_content: Any | None) -> None: | ||||||
|  |         # set sourcename and add content from attribute documentation | ||||||
|  |         sourcename = self.get_sourcename() | ||||||
|  |         startline = int(self.object.source.split(":")[1]) | ||||||
|  | 
 | ||||||
|  |         for i, line in enumerate(self.object.code.splitlines(), startline-1): | ||||||
|  |             self.add_line(line, sourcename, i) | ||||||
|  | 
 | ||||||
|  |         # add additional content (e.g. from document), if present | ||||||
|  |         if more_content: | ||||||
|  |             for line, src in zip(more_content.data, more_content.items): | ||||||
|  |                 self.add_line(line, src[0], src[1]) | ||||||
|  | 
 | ||||||
|  |     def get_object_members( | ||||||
|  |         self, | ||||||
|  |         want_all: bool | ||||||
|  |     ) -> tuple[bool, list[tuple[str, Any]]]: | ||||||
|  |         return False, [] | ||||||
|  | 
 | ||||||
|  | def setup(app: Sphinx) -> dict[str, Any]: | ||||||
|  |     app.add_config_value('cells_json', False, 'html', [Path, PosixPath, WindowsPath]) | ||||||
|  |     app.setup_extension('sphinx.ext.autodoc') | ||||||
|  |     app.add_autodocumenter(YosysCellDocumenter) | ||||||
|  |     app.add_autodocumenter(YosysCellSourceDocumenter) | ||||||
|  |     app.add_autodocumenter(YosysCellGroupDocumenter) | ||||||
|  |     return { | ||||||
|  |         'version': '1', | ||||||
|  |         'parallel_read_safe': True, | ||||||
|  |     } | ||||||
|  | @ -1,72 +1,344 @@ | ||||||
| # based on https://github.com/ofosos/sphinxrecipes/blob/master/sphinxrecipes/sphinxrecipes.py | # based on https://github.com/ofosos/sphinxrecipes/blob/master/sphinxrecipes/sphinxrecipes.py | ||||||
| # license: |  | ||||||
| # Copyright 2019 Mark Meyer |  | ||||||
| #  |  | ||||||
| # Permission is hereby granted, free of charge, to any person obtaining |  | ||||||
| # a copy of this software and associated documentation files (the |  | ||||||
| # "Software"), to deal in the Software without restriction, including |  | ||||||
| # without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
| # distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
| # permit persons to whom the Software is furnished to do so, subject to |  | ||||||
| # the following conditions: |  | ||||||
| #  |  | ||||||
| # The above copyright notice and this permission notice shall be |  | ||||||
| # included in all copies or substantial portions of the Software. |  | ||||||
| #  |  | ||||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |  | ||||||
| # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  | ||||||
| # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |  | ||||||
| # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |  | ||||||
| # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |  | ||||||
| # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |  | ||||||
| # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
| 
 | 
 | ||||||
| import docutils | from __future__ import annotations | ||||||
|  | 
 | ||||||
|  | import re | ||||||
|  | from typing import cast | ||||||
|  | 
 | ||||||
| from docutils import nodes | from docutils import nodes | ||||||
| import sphinx | from docutils.nodes import Node, Element, system_message | ||||||
| from docutils.parsers import rst |  | ||||||
| from docutils.parsers.rst import directives | from docutils.parsers.rst import directives | ||||||
|  | from docutils.parsers.rst.states import Inliner | ||||||
|  | from sphinx.application import Sphinx | ||||||
| from sphinx.domains import Domain, Index | from sphinx.domains import Domain, Index | ||||||
| from sphinx.domains.std import StandardDomain | from sphinx.domains.std import StandardDomain | ||||||
|  | from sphinx.environment import BuildEnvironment | ||||||
| from sphinx.roles import XRefRole | from sphinx.roles import XRefRole | ||||||
| from sphinx.directives import ObjectDescription | from sphinx.directives import ObjectDescription | ||||||
|  | from sphinx.directives.code import container_wrapper | ||||||
| from sphinx.util.nodes import make_refnode | from sphinx.util.nodes import make_refnode | ||||||
|  | from sphinx.util.docfields import Field | ||||||
| from sphinx import addnodes | from sphinx import addnodes | ||||||
| 
 | 
 | ||||||
| class CommandNode(ObjectDescription): | class TocNode(ObjectDescription):     | ||||||
|  |     def add_target_and_index( | ||||||
|  |         self, | ||||||
|  |         name: str, | ||||||
|  |         sig: str, | ||||||
|  |         signode: addnodes.desc_signature | ||||||
|  |     ) -> None: | ||||||
|  |         idx = ".".join(name.split("::")) | ||||||
|  |         signode['ids'].append(idx) | ||||||
|  | 
 | ||||||
|  |     def _object_hierarchy_parts(self, sig_node: addnodes.desc_signature) -> tuple[str, ...]: | ||||||
|  |         if 'fullname' not in sig_node: | ||||||
|  |             return () | ||||||
|  | 
 | ||||||
|  |         modname = sig_node.get('module') | ||||||
|  |         fullname = sig_node['fullname'] | ||||||
|  | 
 | ||||||
|  |         if modname: | ||||||
|  |             return (modname, *fullname.split('::')) | ||||||
|  |         else: | ||||||
|  |             return tuple(fullname.split('::')) | ||||||
|  | 
 | ||||||
|  |     def _toc_entry_name(self, sig_node: addnodes.desc_signature) -> str: | ||||||
|  |         if not sig_node.get('_toc_parts'): | ||||||
|  |             return '' | ||||||
|  | 
 | ||||||
|  |         config = self.env.app.config | ||||||
|  |         objtype = sig_node.parent.get('objtype') | ||||||
|  |         *parents, name = sig_node['_toc_parts'] | ||||||
|  |         if config.toc_object_entries_show_parents == 'domain': | ||||||
|  |             return sig_node.get('tocname', name) | ||||||
|  |         if config.toc_object_entries_show_parents == 'hide': | ||||||
|  |             return name | ||||||
|  |         if config.toc_object_entries_show_parents == 'all': | ||||||
|  |             return '.'.join(parents + [name]) | ||||||
|  |         return '' | ||||||
|  | 
 | ||||||
|  | class CommandNode(TocNode): | ||||||
|     """A custom node that describes a command.""" |     """A custom node that describes a command.""" | ||||||
| 
 | 
 | ||||||
|  |     name = 'cmd' | ||||||
|     required_arguments = 1 |     required_arguments = 1 | ||||||
| 
 | 
 | ||||||
|     option_spec = { |     option_spec = { | ||||||
|         'title': directives.unchanged_required, |         'title': directives.unchanged, | ||||||
|         'tags': directives.unchanged |         'tags': directives.unchanged | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     def handle_signature(self, sig, signode: addnodes.desc_signature): |     def handle_signature(self, sig, signode: addnodes.desc_signature): | ||||||
|  |         signode['fullname'] = sig | ||||||
|         signode += addnodes.desc_addname(text="yosys> help ") |         signode += addnodes.desc_addname(text="yosys> help ") | ||||||
|         signode += addnodes.desc_name(text=sig) |         signode += addnodes.desc_name(text=sig) | ||||||
|         return sig |         return signode['fullname'] | ||||||
| 
 | 
 | ||||||
|     def add_target_and_index(self, name_cls, sig, signode): |     def add_target_and_index(self, name_cls, sig, signode): | ||||||
|         signode['ids'].append('cmd' + '-' + sig) |         idx = type(self).name + '-' + sig | ||||||
|  |         signode['ids'].append(idx) | ||||||
|         if 'noindex' not in self.options: |         if 'noindex' not in self.options: | ||||||
|             name = "{}.{}.{}".format('cmd', type(self).__name__, sig) |             name = "{}.{}.{}".format(self.name, type(self).__name__, sig) | ||||||
|             tagmap = self.env.domaindata['cmd']['obj2tag'] |             tagmap = self.env.domaindata[type(self).name]['obj2tag'] | ||||||
|             tagmap[name] = list(self.options.get('tags', '').split(' ')) |             tagmap[name] = list(self.options.get('tags', '').split(' ')) | ||||||
|             title = self.options.get('title') |             title = self.options.get('title', sig) | ||||||
|             titlemap = self.env.domaindata['cmd']['obj2title'] |             titlemap = self.env.domaindata[type(self).name]['obj2title'] | ||||||
|             titlemap[name] = title |             titlemap[name] = title | ||||||
|             objs = self.env.domaindata['cmd']['objects'] |             objs = self.env.domaindata[type(self).name]['objects'] | ||||||
|  |             # (name, sig, typ, docname, anchor, prio) | ||||||
|             objs.append((name, |             objs.append((name, | ||||||
|                          sig, |                          sig, | ||||||
|                          title, |                          type(self).name, | ||||||
|                          self.env.docname, |                          self.env.docname, | ||||||
|                          'cmd' + '-' + sig, |                          idx, | ||||||
|                          0)) |                          0)) | ||||||
| 
 | 
 | ||||||
|  | class PropNode(TocNode): | ||||||
|  |     name = 'prop' | ||||||
|  |     fieldname = 'props' | ||||||
|  | 
 | ||||||
|  |     def handle_signature(self, sig: str, signode: addnodes.desc_signature): | ||||||
|  |         signode['fullname'] = sig | ||||||
|  |         signode['tocname'] = tocname = sig.split('::')[-1] | ||||||
|  |         signode += addnodes.desc_name(text=tocname) | ||||||
|  |         return signode['fullname'] | ||||||
|  | 
 | ||||||
|  |     def add_target_and_index( | ||||||
|  |         self, | ||||||
|  |         name: str, | ||||||
|  |         sig: str, | ||||||
|  |         signode: addnodes.desc_signature | ||||||
|  |     ) -> None: | ||||||
|  |         idx = ".".join(name.split("::")) | ||||||
|  |         signode['ids'].append(idx) | ||||||
|  |         if 'noindex' not in self.options: | ||||||
|  |             tocname: str = signode.get('tocname', name) | ||||||
|  |             objs = self.env.domaindata[self.domain]['objects'] | ||||||
|  |             # (name, sig, typ, docname, anchor, prio) | ||||||
|  |             objs.append((name, | ||||||
|  |                          tocname, | ||||||
|  |                          type(self).name, | ||||||
|  |                          self.env.docname, | ||||||
|  |                          idx, | ||||||
|  |                          1)) | ||||||
|  | 
 | ||||||
|  | class CellGroupedField(Field): | ||||||
|  |     """Custom version of GroupedField which doesn't require content.""" | ||||||
|  |     is_grouped = True | ||||||
|  |     list_type = nodes.bullet_list | ||||||
|  | 
 | ||||||
|  |     def __init__(self, name: str, names: tuple[str, ...] = (), label: str = None, | ||||||
|  |                  rolename: str = None, can_collapse: bool = False) -> None: | ||||||
|  |         super().__init__(name, names, label, True, rolename) | ||||||
|  |         self.can_collapse = can_collapse | ||||||
|  | 
 | ||||||
|  |     def make_field(self, types: dict[str, list[Node]], domain: str, | ||||||
|  |                    items: tuple, env: BuildEnvironment = None, | ||||||
|  |                    inliner: Inliner = None, location: Node = None) -> nodes.field: | ||||||
|  |         fieldname = nodes.field_name('', self.label) | ||||||
|  |         listnode = self.list_type() | ||||||
|  |         for fieldarg, content in items: | ||||||
|  |             par = nodes.paragraph() | ||||||
|  |             if fieldarg: | ||||||
|  |                 par.extend(self.make_xrefs(self.rolename, domain, | ||||||
|  |                                            fieldarg, nodes.Text, | ||||||
|  |                                            env=env, inliner=inliner, location=location)) | ||||||
|  | 
 | ||||||
|  |             if len(content) == 1 and ( | ||||||
|  |                     isinstance(content[0], nodes.Text) or | ||||||
|  |                     (isinstance(content[0], nodes.inline) and len(content[0]) == 1 and | ||||||
|  |                     isinstance(content[0][0], nodes.Text))): | ||||||
|  |                 par += nodes.Text(' -- ') | ||||||
|  |                 par += content | ||||||
|  |             listnode += nodes.list_item('', par) | ||||||
|  | 
 | ||||||
|  |         if len(items) == 1 and self.can_collapse: | ||||||
|  |             list_item = cast(nodes.list_item, listnode[0]) | ||||||
|  |             fieldbody = nodes.field_body('', list_item[0]) | ||||||
|  |             return nodes.field('', fieldname, fieldbody) | ||||||
|  | 
 | ||||||
|  |         fieldbody = nodes.field_body('', listnode) | ||||||
|  |         return nodes.field('', fieldname, fieldbody) | ||||||
|  | 
 | ||||||
|  | class CellNode(TocNode): | ||||||
|  |     """A custom node that describes an internal cell.""" | ||||||
|  | 
 | ||||||
|  |     name = 'cell' | ||||||
|  | 
 | ||||||
|  |     option_spec = { | ||||||
|  |         'title': directives.unchanged, | ||||||
|  |         'ports': directives.unchanged, | ||||||
|  |         'properties': directives.unchanged, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     doc_field_types = [ | ||||||
|  |         CellGroupedField('props', label='Properties', rolename='prop', | ||||||
|  |                        names=('properties', 'property', 'tag', 'tags'), | ||||||
|  |                        can_collapse=True), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     def handle_signature(self, sig: str, signode: addnodes.desc_signature): | ||||||
|  |         signode['fullname'] = sig | ||||||
|  |         signode['tocname'] = tocname = sig.split('::')[-1] | ||||||
|  |         signode += addnodes.desc_addname(text="yosys> help ") | ||||||
|  |         signode += addnodes.desc_name(text=tocname) | ||||||
|  |         return signode['fullname'] | ||||||
|  | 
 | ||||||
|  |     def add_target_and_index( | ||||||
|  |         self, | ||||||
|  |         name: str, | ||||||
|  |         sig: str, | ||||||
|  |         signode: addnodes.desc_signature | ||||||
|  |     ) -> None: | ||||||
|  |         idx = ".".join(name.split("::")) | ||||||
|  |         signode['ids'].append(idx) | ||||||
|  |         if 'noindex' not in self.options: | ||||||
|  |             tocname: str = signode.get('tocname', name) | ||||||
|  |             title: str = self.options.get('title', sig) | ||||||
|  |             titlemap = self.env.domaindata[self.domain]['obj2title'] | ||||||
|  |             titlemap[name] = title | ||||||
|  |             props = self.options.get('properties', '') | ||||||
|  |             if props: | ||||||
|  |                 propmap = self.env.domaindata[self.domain]['obj2prop'] | ||||||
|  |                 propmap[name] = props.split(' ') | ||||||
|  |             objs = self.env.domaindata[self.domain]['objects'] | ||||||
|  |             # (name, sig, typ, docname, anchor, prio) | ||||||
|  |             objs.append((name, | ||||||
|  |                          tocname, | ||||||
|  |                          type(self).name, | ||||||
|  |                          self.env.docname, | ||||||
|  |                          idx, | ||||||
|  |                          0)) | ||||||
|  |              | ||||||
|  |     def transform_content(self, contentnode: addnodes.desc_content) -> None: | ||||||
|  |         # Add the cell title to the body | ||||||
|  |         if 'title' in self.options: | ||||||
|  |             titlenode = nodes.paragraph() | ||||||
|  |             titlenode += nodes.strong() | ||||||
|  |             titlenode[-1] += nodes.Text(self.options['title']) | ||||||
|  |             contentnode.insert(0, titlenode) | ||||||
|  | 
 | ||||||
|  | class CellSourceNode(TocNode): | ||||||
|  |     """A custom code block for including cell source.""" | ||||||
|  | 
 | ||||||
|  |     name = 'cellsource' | ||||||
|  | 
 | ||||||
|  |     option_spec = { | ||||||
|  |         "source": directives.unchanged_required, | ||||||
|  |         "language": directives.unchanged_required, | ||||||
|  |         'lineno-start': int, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def handle_signature( | ||||||
|  |         self, | ||||||
|  |         sig, | ||||||
|  |         signode: addnodes.desc_signature | ||||||
|  |     ) -> str: | ||||||
|  |         language = self.options.get('language') | ||||||
|  |         signode['fullname'] = sig | ||||||
|  |         signode['tocname'] = f"{sig.split('::')[-2]} {language}" | ||||||
|  |         signode += addnodes.desc_name(text="Simulation model") | ||||||
|  |         signode += addnodes.desc_sig_space() | ||||||
|  |         signode += addnodes.desc_addname(text=f'({language})') | ||||||
|  |         return signode['fullname'] | ||||||
|  | 
 | ||||||
|  |     def run(self) -> list[Node]: | ||||||
|  |         """Override run to parse content as a code block""" | ||||||
|  |         if ':' in self.name: | ||||||
|  |             self.domain, self.objtype = self.name.split(':', 1) | ||||||
|  |         else: | ||||||
|  |             self.domain, self.objtype = '', self.name | ||||||
|  |         self.indexnode = addnodes.index(entries=[]) | ||||||
|  | 
 | ||||||
|  |         node = addnodes.desc() | ||||||
|  |         node.document = self.state.document | ||||||
|  |         source, line = self.get_source_info() | ||||||
|  |         if line is not None: | ||||||
|  |             line -= 1 | ||||||
|  |         self.state.document.note_source(source, line) | ||||||
|  |         node['domain'] = self.domain | ||||||
|  |         # 'desctype' is a backwards compatible attribute | ||||||
|  |         node['objtype'] = node['desctype'] = self.objtype | ||||||
|  |         node['noindex'] = noindex = ('noindex' in self.options) | ||||||
|  |         node['noindexentry'] = ('noindexentry' in self.options) | ||||||
|  |         node['nocontentsentry'] = ('nocontentsentry' in self.options) | ||||||
|  |         if self.domain: | ||||||
|  |             node['classes'].append(self.domain) | ||||||
|  |         node['classes'].append(node['objtype']) | ||||||
|  | 
 | ||||||
|  |         self.names = [] | ||||||
|  |         signatures = self.get_signatures() | ||||||
|  |         for sig in signatures: | ||||||
|  |             # add a signature node for each signature in the current unit | ||||||
|  |             # and add a reference target for it | ||||||
|  |             signode = addnodes.desc_signature(sig, '') | ||||||
|  |             self.set_source_info(signode) | ||||||
|  |             node.append(signode) | ||||||
|  |             try: | ||||||
|  |                 # name can also be a tuple, e.g. (classname, objname); | ||||||
|  |                 # this is strictly domain-specific (i.e. no assumptions may | ||||||
|  |                 # be made in this base class) | ||||||
|  |                 name = self.handle_signature(sig, signode) | ||||||
|  |             except ValueError: | ||||||
|  |                 # signature parsing failed | ||||||
|  |                 signode.clear() | ||||||
|  |                 signode += addnodes.desc_name(sig, sig) | ||||||
|  |                 continue  # we don't want an index entry here | ||||||
|  |             finally: | ||||||
|  |                 # Private attributes for ToC generation. Will be modified or removed | ||||||
|  |                 # without notice. | ||||||
|  |                 if self.env.app.config.toc_object_entries: | ||||||
|  |                     signode['_toc_parts'] = self._object_hierarchy_parts(signode) | ||||||
|  |                     signode['_toc_name'] = self._toc_entry_name(signode) | ||||||
|  |                 else: | ||||||
|  |                     signode['_toc_parts'] = () | ||||||
|  |                     signode['_toc_name'] = '' | ||||||
|  |             if name not in self.names: | ||||||
|  |                 self.names.append(name) | ||||||
|  |                 if not noindex: | ||||||
|  |                     # only add target and index entry if this is the first | ||||||
|  |                     # description of the object with this name in this desc block | ||||||
|  |                     self.add_target_and_index(name, sig, signode) | ||||||
|  |          | ||||||
|  |         # handle code | ||||||
|  |         code = '\n'.join(self.content) | ||||||
|  |         literal: Element = nodes.literal_block(code, code) | ||||||
|  |         if 'lineno-start' in self.options: | ||||||
|  |             literal['linenos'] = True | ||||||
|  |             literal['highlight_args'] = { | ||||||
|  |                 'linenostart': self.options['lineno-start'] | ||||||
|  |             } | ||||||
|  |         literal['classes'] += self.options.get('class', []) | ||||||
|  |         literal['language'] = self.options.get('language') | ||||||
|  |         literal = container_wrapper(self, literal, self.options.get('source')) | ||||||
|  | 
 | ||||||
|  |         return [self.indexnode, node, literal] | ||||||
|  | 
 | ||||||
|  | class CellGroupNode(TocNode): | ||||||
|  |     name = 'cellgroup' | ||||||
|  | 
 | ||||||
|  |     option_spec = { | ||||||
|  |         'caption': directives.unchanged, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def add_target_and_index(self, name: str, sig: str, signode: addnodes.desc_signature) -> None: | ||||||
|  |         if self.options.get('caption', ''): | ||||||
|  |             super().add_target_and_index(name, sig, signode) | ||||||
|  | 
 | ||||||
|  |     def handle_signature( | ||||||
|  |         self, | ||||||
|  |         sig, | ||||||
|  |         signode: addnodes.desc_signature | ||||||
|  |     ) -> str: | ||||||
|  |         signode['fullname'] = fullname = sig | ||||||
|  |         caption = self.options.get("caption", fullname) | ||||||
|  |         if caption: | ||||||
|  |             signode['tocname'] = caption | ||||||
|  |             signode += addnodes.desc_name(text=caption) | ||||||
|  |         return fullname | ||||||
|  | 
 | ||||||
| class TagIndex(Index): | class TagIndex(Index): | ||||||
|     """A custom directive that creates an tag matrix.""" |     """A custom directive that creates a tag matrix.""" | ||||||
|      |      | ||||||
|     name = 'tag' |     name = 'tag' | ||||||
|     localname = 'Tag Index' |     localname = 'Tag Index' | ||||||
|  | @ -107,7 +379,7 @@ class TagIndex(Index): | ||||||
|                 in self.domain.get_objects()} |                 in self.domain.get_objects()} | ||||||
|          |          | ||||||
|         tmap = {} |         tmap = {} | ||||||
|         tags = self.domain.data['obj2tag'] |         tags = self.domain.data[f'obj2{self.name}'] | ||||||
|         for name, tags in tags.items(): |         for name, tags in tags.items(): | ||||||
|             for tag in tags: |             for tag in tags: | ||||||
|                 tmap.setdefault(tag,[]) |                 tmap.setdefault(tag,[]) | ||||||
|  | @ -123,10 +395,9 @@ class TagIndex(Index): | ||||||
|                     anchor, |                     anchor, | ||||||
|                     docname, '', typ |                     docname, '', typ | ||||||
|                 )) |                 )) | ||||||
|         re = [(k, v) for k, v in sorted(content.items())] |         ret = [(k, v) for k, v in sorted(content.items())] | ||||||
| 
 |  | ||||||
|         return (re, True) |  | ||||||
| 
 | 
 | ||||||
|  |         return (ret, True) | ||||||
| 
 | 
 | ||||||
| class CommandIndex(Index):     | class CommandIndex(Index):     | ||||||
|     name = 'cmd' |     name = 'cmd' | ||||||
|  | @ -164,23 +435,81 @@ class CommandIndex(Index): | ||||||
|         content = {} |         content = {} | ||||||
|         items = ((name, dispname, typ, docname, anchor) |         items = ((name, dispname, typ, docname, anchor) | ||||||
|                  for name, dispname, typ, docname, anchor, prio |                  for name, dispname, typ, docname, anchor, prio | ||||||
|                  in self.domain.get_objects()) |                  in self.domain.get_objects() | ||||||
|  |                  if typ == self.name) | ||||||
|         items = sorted(items, key=lambda item: item[0]) |         items = sorted(items, key=lambda item: item[0]) | ||||||
|         for name, dispname, typ, docname, anchor in items: |         for name, dispname, typ, docname, anchor in items: | ||||||
|             lis = content.setdefault('Command', []) |             lis = content.setdefault(self.shortname, []) | ||||||
|             lis.append(( |             lis.append(( | ||||||
|                 dispname, 0, docname, |                 dispname, 0, docname, | ||||||
|                 anchor, |                 anchor, | ||||||
|                 '', '', typ |                 '', '', typ | ||||||
|             )) |             )) | ||||||
|         re = [(k, v) for k, v in sorted(content.items())] |         ret = [(k, v) for k, v in sorted(content.items())] | ||||||
| 
 | 
 | ||||||
|         return (re, True) |         return (ret, True) | ||||||
| 
 | 
 | ||||||
|  | class CellIndex(CommandIndex): | ||||||
|  |     name = 'cell' | ||||||
|  |     localname = 'Internal cell reference' | ||||||
|  |     shortname = 'Internal cell' | ||||||
|  | 
 | ||||||
|  | class PropIndex(TagIndex): | ||||||
|  |     """A custom directive that creates a properties matrix.""" | ||||||
|  |      | ||||||
|  |     name = 'prop' | ||||||
|  |     localname = 'Property Index' | ||||||
|  |     shortname = 'Prop' | ||||||
|  |     fieldname = 'props' | ||||||
|  | 
 | ||||||
|  |     def generate(self, docnames=None): | ||||||
|  |         content = {} | ||||||
|  | 
 | ||||||
|  |         cells = {name: (dispname, docname, anchor) | ||||||
|  |                 for name, dispname, typ, docname, anchor, _ | ||||||
|  |                 in self.domain.get_objects() | ||||||
|  |                 if typ == 'cell'} | ||||||
|  |         props = {name: (dispname, docname, anchor) | ||||||
|  |                 for name, dispname, typ, docname, anchor, _ | ||||||
|  |                 in self.domain.get_objects() | ||||||
|  |                 if typ == 'prop'} | ||||||
|  | 
 | ||||||
|  |         tmap: dict[str, list[str]] = {} | ||||||
|  |         tags: dict[str, list[str]] = self.domain.data[f'obj2{self.name}'] | ||||||
|  |         for name, tags in tags.items(): | ||||||
|  |             for tag in tags: | ||||||
|  |                 tmap.setdefault(tag,[]) | ||||||
|  |                 tmap[tag].append(name) | ||||||
|  | 
 | ||||||
|  |         for tag in sorted(tmap.keys()): | ||||||
|  |             test = re.match(r'^(\w+[_-])', tag) | ||||||
|  |             tag_prefix = test.group(1) | ||||||
|  |             lis = content.setdefault(tag_prefix, []) | ||||||
|  |             try: | ||||||
|  |                 dispname, docname, anchor = props[tag] | ||||||
|  |             except KeyError: | ||||||
|  |                 dispname = tag | ||||||
|  |                 docname = anchor = '' | ||||||
|  |             lis.append(( | ||||||
|  |                 dispname, 1, docname, | ||||||
|  |                 anchor, | ||||||
|  |                 '', '', docname or 'unavailable' | ||||||
|  |             )) | ||||||
|  |             objlis = tmap[tag] | ||||||
|  |             for objname in sorted(objlis): | ||||||
|  |                 dispname, docname, anchor = cells[objname] | ||||||
|  |                 lis.append(( | ||||||
|  |                     dispname, 2, docname, | ||||||
|  |                     anchor, | ||||||
|  |                     '', '', docname | ||||||
|  |                 )) | ||||||
|  |         ret = [(k, v) for k, v in sorted(content.items())] | ||||||
|  | 
 | ||||||
|  |         return (ret, True) | ||||||
| 
 | 
 | ||||||
| class CommandDomain(Domain): | class CommandDomain(Domain): | ||||||
|     name = 'cmd' |     name = 'cmd' | ||||||
|     label = 'Command Sample' |     label = 'Yosys commands' | ||||||
| 
 | 
 | ||||||
|     roles = { |     roles = { | ||||||
|         'ref': XRefRole() |         'ref': XRefRole() | ||||||
|  | @ -203,7 +532,7 @@ class CommandDomain(Domain): | ||||||
| 
 | 
 | ||||||
|     def get_full_qualified_name(self, node): |     def get_full_qualified_name(self, node): | ||||||
|         """Return full qualified name for a given node""" |         """Return full qualified name for a given node""" | ||||||
|         return "{}.{}.{}".format('cmd', |         return "{}.{}.{}".format(type(self).name, | ||||||
|                                  type(node).__name__, |                                  type(node).__name__, | ||||||
|                                  node.arguments[0]) |                                  node.arguments[0]) | ||||||
| 
 | 
 | ||||||
|  | @ -230,17 +559,67 @@ class CommandDomain(Domain): | ||||||
|             print(f"Missing ref for {target} in {fromdocname} ") |             print(f"Missing ref for {target} in {fromdocname} ") | ||||||
|             return None |             return None | ||||||
|          |          | ||||||
| def setup(app): | class CellDomain(CommandDomain): | ||||||
|  |     name = 'cell' | ||||||
|  |     label = 'Yosys internal cells' | ||||||
|  | 
 | ||||||
|  |     roles = CommandDomain.roles.copy() | ||||||
|  |     roles.update({ | ||||||
|  |         'prop': XRefRole() | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     directives = { | ||||||
|  |         'def': CellNode, | ||||||
|  |         'defprop': PropNode, | ||||||
|  |         'source': CellSourceNode, | ||||||
|  |         'group': CellGroupNode, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     indices = { | ||||||
|  |         CellIndex, | ||||||
|  |         PropIndex | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     initial_data = { | ||||||
|  |         'objects': [],      # object list | ||||||
|  |         'obj2prop': {},     # name -> properties | ||||||
|  |         'obj2title': {},    # name -> title | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def get_objects(self): | ||||||
|  |         for obj in self.data['objects']: | ||||||
|  |             yield(obj) | ||||||
|  | 
 | ||||||
|  | def autoref(name, rawtext: str, text: str, lineno, inliner: Inliner, | ||||||
|  |             options=None, content=None): | ||||||
|  |     role = 'cell:ref' if text[0] == '$' else 'cmd:ref' | ||||||
|  |     if text.startswith("help ") and text.count(' ') == 1: | ||||||
|  |         _, cmd = text.split(' ', 1) | ||||||
|  |         text = f'{text} <{cmd}>' | ||||||
|  |     return inliner.interpreted(rawtext, text, role, lineno) | ||||||
|  | 
 | ||||||
|  | def setup(app: Sphinx): | ||||||
|     app.add_domain(CommandDomain) |     app.add_domain(CommandDomain) | ||||||
|  |     app.add_domain(CellDomain) | ||||||
| 
 | 
 | ||||||
|     StandardDomain.initial_data['labels']['commandindex'] =\ |     StandardDomain.initial_data['labels']['commandindex'] =\ | ||||||
|         ('cmd-cmd', '', 'Command Reference') |         ('cmd-cmd', '', 'Command Reference') | ||||||
|     StandardDomain.initial_data['labels']['tagindex'] =\ |     StandardDomain.initial_data['labels']['tagindex'] =\ | ||||||
|         ('cmd-tag', '', 'Tag Index') |         ('cmd-tag', '', 'Tag Index') | ||||||
|  |     StandardDomain.initial_data['labels']['cellindex'] =\ | ||||||
|  |         ('cell-cell', '', 'Internal cell reference') | ||||||
|  |     StandardDomain.initial_data['labels']['propindex'] =\ | ||||||
|  |         ('cell-prop', '', 'Property Index') | ||||||
| 
 | 
 | ||||||
|     StandardDomain.initial_data['anonlabels']['commandindex'] =\ |     StandardDomain.initial_data['anonlabels']['commandindex'] =\ | ||||||
|         ('cmd-cmd', '') |         ('cmd-cmd', '') | ||||||
|     StandardDomain.initial_data['anonlabels']['tagindex'] =\ |     StandardDomain.initial_data['anonlabels']['tagindex'] =\ | ||||||
|         ('cmd-tag', '') |         ('cmd-tag', '') | ||||||
|  |     StandardDomain.initial_data['anonlabels']['cellindex'] =\ | ||||||
|  |         ('cell-cell', '') | ||||||
|  |     StandardDomain.initial_data['anonlabels']['propindex'] =\ | ||||||
|  |         ('cell-prop', '') | ||||||
| 
 | 
 | ||||||
|     return {'version': '0.1'} |     app.add_role('autoref', autoref) | ||||||
|  |      | ||||||
|  |     return {'version': '0.2'} | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ struct CellType | ||||||
| 	RTLIL::IdString type; | 	RTLIL::IdString type; | ||||||
| 	pool<RTLIL::IdString> inputs, outputs; | 	pool<RTLIL::IdString> inputs, outputs; | ||||||
| 	bool is_evaluable; | 	bool is_evaluable; | ||||||
|  | 	bool is_combinatorial; | ||||||
|  | 	bool is_synthesizable; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct CellTypes | struct CellTypes | ||||||
|  | @ -56,9 +58,9 @@ struct CellTypes | ||||||
| 		setup_stdcells_mem(); | 		setup_stdcells_mem(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false) | 	void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) | ||||||
| 	{ | 	{ | ||||||
| 		CellType ct = {type, inputs, outputs, is_evaluable}; | 		CellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable}; | ||||||
| 		cell_types[ct.type] = ct; | 		cell_types[ct.type] = ct; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "kernel/yosys.h" | #include "kernel/yosys.h" | ||||||
| #include "kernel/satgen.h" | #include "kernel/satgen.h" | ||||||
|  | #include "kernel/json.h" | ||||||
| 
 | 
 | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  | @ -747,14 +748,44 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f | ||||||
| 		design->selection_stack.pop_back(); | 		design->selection_stack.pop_back(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct SimHelper { | ||||||
|  | 	string name; | ||||||
|  | 	inline string filesafe_name() { | ||||||
|  | 		if (name.at(0) == '$') | ||||||
|  | 			if (name.at(1) == '_') | ||||||
|  | 				return "gate" + name.substr(1); | ||||||
|  | 			else | ||||||
|  | 				return "word_" + name.substr(1); | ||||||
|  | 		else | ||||||
|  | 			return name; | ||||||
|  | 	} | ||||||
|  | 	string title; | ||||||
|  | 	string ports; | ||||||
|  | 	string source; | ||||||
|  | 	string desc; | ||||||
|  | 	string code; | ||||||
|  | 	string group; | ||||||
|  | 	string ver; | ||||||
|  | 	string tags; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static bool is_code_getter(string name) { | ||||||
|  | 	return *(--(name.end())) == '+'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static string get_cell_name(string name) { | ||||||
|  | 	return is_code_getter(name) ? name.substr(0, name.length()-1) : name; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static struct CellHelpMessages { | static struct CellHelpMessages { | ||||||
| 	dict<string, string> cell_help, cell_code; | 	dict<string, SimHelper> cell_help; | ||||||
| 	CellHelpMessages() { | 	CellHelpMessages() { | ||||||
| #include "techlibs/common/simlib_help.inc" | #include "techlibs/common/simlib_help.inc" | ||||||
| #include "techlibs/common/simcells_help.inc" | #include "techlibs/common/simcells_help.inc" | ||||||
| 		cell_help.sort(); | 		cell_help.sort(); | ||||||
| 		cell_code.sort(); |  | ||||||
| 	} | 	} | ||||||
|  | 	bool contains(string name) { return cell_help.count(get_cell_name(name)) > 0; } | ||||||
|  | 	SimHelper get(string name) { return cell_help[get_cell_name(name)]; } | ||||||
| } cell_help_messages; | } cell_help_messages; | ||||||
| 
 | 
 | ||||||
| struct HelpPass : public Pass { | struct HelpPass : public Pass { | ||||||
|  | @ -771,7 +802,7 @@ struct HelpPass : public Pass { | ||||||
| 		log("    help <celltype>+  ....  print verilog code for given cell type\n"); | 		log("    help <celltype>+  ....  print verilog code for given cell type\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void write_rst(std::string cmd, std::string title, std::string text) | 	void write_cmd_rst(std::string cmd, std::string title, std::string text) | ||||||
| 	{ | 	{ | ||||||
| 		FILE *f = fopen(stringf("docs/source/cmd/%s.rst", cmd.c_str()).c_str(), "wt"); | 		FILE *f = fopen(stringf("docs/source/cmd/%s.rst", cmd.c_str()).c_str(), "wt"); | ||||||
| 		// make header
 | 		// make header
 | ||||||
|  | @ -864,6 +895,146 @@ struct HelpPass : public Pass { | ||||||
| 		} | 		} | ||||||
| 		fclose(f); | 		fclose(f); | ||||||
| 	} | 	} | ||||||
|  | 	void write_cell_rst(Yosys::SimHelper cell, Yosys::CellType ct) | ||||||
|  | 	{ | ||||||
|  | 		// open
 | ||||||
|  | 		FILE *f = fopen(stringf("docs/source/cell/%s.rst", cell.filesafe_name().c_str()).c_str(), "wt"); | ||||||
|  | 
 | ||||||
|  | 		// make header
 | ||||||
|  | 		string title_line; | ||||||
|  | 		if (cell.title.length()) | ||||||
|  | 			title_line = stringf("%s - %s", cell.name.c_str(), cell.title.c_str()); | ||||||
|  | 		else title_line = cell.name; | ||||||
|  | 		string underline = "\n"; | ||||||
|  | 		underline.insert(0, title_line.length(), '='); | ||||||
|  | 		fprintf(f, "%s\n", title_line.c_str()); | ||||||
|  | 		fprintf(f, "%s\n", underline.c_str()); | ||||||
|  | 
 | ||||||
|  | 		// help text, with cell def for links
 | ||||||
|  | 		fprintf(f, ".. cell:def:: %s\n", cell.name.c_str()); | ||||||
|  | 		if (cell.title.length()) | ||||||
|  | 			fprintf(f, "   :title: %s\n\n", cell.title.c_str()); | ||||||
|  | 		else | ||||||
|  | 			fprintf(f, "   :title: %s\n\n", cell.name.c_str()); | ||||||
|  | 		std::stringstream ss; | ||||||
|  | 		ss << cell.desc; | ||||||
|  | 		for (std::string line; std::getline(ss, line, '\n');) { | ||||||
|  | 			fprintf(f, "   %s\n", line.c_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// properties
 | ||||||
|  | 		fprintf(f, "\nProperties"); | ||||||
|  | 		fprintf(f, "\n----------\n\n"); | ||||||
|  | 		dict<string, bool> prop_dict = { | ||||||
|  | 			{"is_evaluable", ct.is_evaluable}, | ||||||
|  | 			{"is_combinatorial", ct.is_combinatorial}, | ||||||
|  | 			{"is_synthesizable", ct.is_synthesizable}, | ||||||
|  | 		}; | ||||||
|  | 		for (auto &it : prop_dict) { | ||||||
|  | 			fprintf(f, "- %s: %s\n", it.first.c_str(), it.second ? "true" : "false"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// source code
 | ||||||
|  | 		fprintf(f, "\nSimulation model (Verilog)"); | ||||||
|  | 		fprintf(f, "\n--------------------------\n\n"); | ||||||
|  | 		fprintf(f, ".. code-block:: verilog\n"); | ||||||
|  | 		fprintf(f, "   :caption: %s\n\n", cell.source.c_str()); | ||||||
|  | 		std::stringstream ss2; | ||||||
|  | 		ss2 << cell.code; | ||||||
|  | 		for (std::string line; std::getline(ss2, line, '\n');) { | ||||||
|  | 			fprintf(f, "   %s\n", line.c_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// footer
 | ||||||
|  | 		fprintf(f, "\n.. note::\n\n"); | ||||||
|  | 		fprintf(f, "   This page was auto-generated from the output of\n"); | ||||||
|  | 		fprintf(f, "   ``help %s``.\n", cell.name.c_str()); | ||||||
|  | 
 | ||||||
|  | 		// close
 | ||||||
|  | 		fclose(f); | ||||||
|  | 	} | ||||||
|  | 	bool dump_cells_json(PrettyJson &json) { | ||||||
|  | 		// init json
 | ||||||
|  | 		json.begin_object(); | ||||||
|  | 		json.entry("version", "Yosys internal cells"); | ||||||
|  | 		json.entry("generator", yosys_version_str); | ||||||
|  | 
 | ||||||
|  | 		dict<string, vector<string>> groups; | ||||||
|  | 		dict<string, pair<SimHelper, CellType>> cells; | ||||||
|  | 
 | ||||||
|  | 		// iterate over cells
 | ||||||
|  | 		bool raise_error = false; | ||||||
|  | 		for (auto &it : yosys_celltypes.cell_types) { | ||||||
|  | 			auto name = it.first.str(); | ||||||
|  | 			if (cell_help_messages.contains(name)) { | ||||||
|  | 				auto cell_help = cell_help_messages.get(name); | ||||||
|  | 				if (groups.count(cell_help.group) != 0) { | ||||||
|  | 					auto group_cells = &groups.at(cell_help.group); | ||||||
|  | 					group_cells->push_back(name); | ||||||
|  | 				} else { | ||||||
|  | 					auto group_cells = new vector<string>(1, name); | ||||||
|  | 					groups.emplace(cell_help.group, *group_cells); | ||||||
|  | 				} | ||||||
|  | 				auto cell_pair = pair<SimHelper, CellType>(cell_help, it.second); | ||||||
|  | 				cells.emplace(name, cell_pair); | ||||||
|  | 			} else { | ||||||
|  | 				log("ERROR: Missing cell help for cell '%s'.\n", name.c_str()); | ||||||
|  | 				raise_error |= true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		for (auto &it : cell_help_messages.cell_help) { | ||||||
|  | 			if (cells.count(it.first) == 0) { | ||||||
|  | 				log_warning("Found cell model '%s' without matching cell type.\n", it.first.c_str()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// write to json
 | ||||||
|  | 		json.name("groups"); json.begin_object(); | ||||||
|  | 		groups.sort(); | ||||||
|  | 		for (auto &it : groups) { | ||||||
|  | 			json.name(it.first.c_str()); json.value(it.second); | ||||||
|  | 		} | ||||||
|  | 		json.end_object(); | ||||||
|  | 
 | ||||||
|  | 		json.name("cells"); json.begin_object(); | ||||||
|  | 		cells.sort(); | ||||||
|  | 		for (auto &it : cells) { | ||||||
|  | 			auto ch = it.second.first; | ||||||
|  | 			auto ct = it.second.second; | ||||||
|  | 			json.name(ch.name.c_str()); json.begin_object(); | ||||||
|  | 			json.name("title"); json.value(ch.title); | ||||||
|  | 			json.name("ports"); json.value(ch.ports); | ||||||
|  | 			json.name("source"); json.value(ch.source); | ||||||
|  | 			json.name("desc"); json.value(ch.desc); | ||||||
|  | 			json.name("code"); json.value(ch.code); | ||||||
|  | 			vector<string> inputs, outputs; | ||||||
|  | 			for (auto &input : ct.inputs) | ||||||
|  | 				inputs.push_back(input.str()); | ||||||
|  | 			json.name("inputs"); json.value(inputs); | ||||||
|  | 			for (auto &output : ct.outputs) | ||||||
|  | 				outputs.push_back(output.str()); | ||||||
|  | 			json.name("outputs"); json.value(outputs); | ||||||
|  | 			vector<string> properties; | ||||||
|  | 			// CellType properties
 | ||||||
|  | 			if (ct.is_evaluable) properties.push_back("is_evaluable"); | ||||||
|  | 			if (ct.is_combinatorial) properties.push_back("is_combinatorial"); | ||||||
|  | 			if (ct.is_synthesizable) properties.push_back("is_synthesizable"); | ||||||
|  | 			// SimHelper properties
 | ||||||
|  | 			size_t last = 0; size_t next = 0; | ||||||
|  | 			while ((next = ch.tags.find(", ", last)) != string::npos) { | ||||||
|  | 				properties.push_back(ch.tags.substr(last, next-last)); | ||||||
|  | 				last = next + 2; | ||||||
|  | 			} | ||||||
|  | 			auto final_tag = ch.tags.substr(last); | ||||||
|  | 			if (final_tag.size()) properties.push_back(final_tag); | ||||||
|  | 			json.name("properties"); json.value(properties); | ||||||
|  | 			json.end_object(); | ||||||
|  | 		} | ||||||
|  | 		json.end_object(); | ||||||
|  | 
 | ||||||
|  | 		json.end_object(); | ||||||
|  | 		return raise_error; | ||||||
|  | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design*) override | 	void execute(std::vector<std::string> args, RTLIL::Design*) override | ||||||
| 	{ | 	{ | ||||||
| 		if (args.size() == 1) { | 		if (args.size() == 1) { | ||||||
|  | @ -896,9 +1067,8 @@ struct HelpPass : public Pass { | ||||||
| 			else if (args[1] == "-cells") { | 			else if (args[1] == "-cells") { | ||||||
| 				log("\n"); | 				log("\n"); | ||||||
| 				for (auto &it : cell_help_messages.cell_help) { | 				for (auto &it : cell_help_messages.cell_help) { | ||||||
| 					string line = split_tokens(it.second, "\n").at(0); | 					SimHelper help_cell = it.second; | ||||||
| 					string cell_name = next_token(line); | 					log("    %-15s %s\n", help_cell.name.c_str(), help_cell.ports.c_str()); | ||||||
| 					log("    %-15s %s\n", cell_name.c_str(), line.c_str()); |  | ||||||
| 				} | 				} | ||||||
| 				log("\n"); | 				log("\n"); | ||||||
| 				log("Type 'help <cell_type>' for more information on a cell type.\n"); | 				log("Type 'help <cell_type>' for more information on a cell type.\n"); | ||||||
|  | @ -917,7 +1087,23 @@ struct HelpPass : public Pass { | ||||||
| 						log("\n"); | 						log("\n"); | ||||||
| 					} | 					} | ||||||
| 					log_streams.pop_back(); | 					log_streams.pop_back(); | ||||||
| 					write_rst(it.first, it.second->short_help, buf.str()); | 					write_cmd_rst(it.first, it.second->short_help, buf.str()); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			// this option is also undocumented as it is for internal use only
 | ||||||
|  | 			else if (args[1] == "-write-rst-cells-manual") { | ||||||
|  | 				bool raise_error = false; | ||||||
|  | 				for (auto &it : yosys_celltypes.cell_types) { | ||||||
|  | 					auto name = it.first.str(); | ||||||
|  | 					if (cell_help_messages.contains(name)) { | ||||||
|  | 						write_cell_rst(cell_help_messages.get(name), it.second); | ||||||
|  | 					} else { | ||||||
|  | 						log("ERROR: Missing cell help for cell '%s'.\n", name.c_str()); | ||||||
|  | 						raise_error |= true; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				if (raise_error) { | ||||||
|  | 					log_error("One or more cells defined in celltypes.h are missing help documentation.\n"); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (pass_register.count(args[1])) { | 			else if (pass_register.count(args[1])) { | ||||||
|  | @ -928,18 +1114,42 @@ struct HelpPass : public Pass { | ||||||
| 					log("\n"); | 					log("\n"); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (cell_help_messages.cell_help.count(args[1])) { | 			else if (cell_help_messages.contains(args[1])) { | ||||||
| 				log("%s", cell_help_messages.cell_help.at(args[1]).c_str()); | 				auto help_cell = cell_help_messages.get(args[1]); | ||||||
| 				log("Run 'help %s+' to display the Verilog model for this cell type.\n", args[1].c_str()); | 				if (is_code_getter(args[1])) { | ||||||
|  | 						log("\n"); | ||||||
|  | 						log("%s\n", help_cell.code.c_str()); | ||||||
|  | 				} else { | ||||||
|  | 					log("\n    %s %s\n\n", help_cell.name.c_str(), help_cell.ports.c_str()); | ||||||
|  | 					if (help_cell.ver == "2" || help_cell.ver == "2a") { | ||||||
|  | 						if (help_cell.title != "") log("%s:\n", help_cell.title.c_str()); | ||||||
|  | 						std::stringstream ss; | ||||||
|  | 						ss << help_cell.desc; | ||||||
|  | 						for (std::string line; std::getline(ss, line, '\n');) { | ||||||
|  | 							if (line != "::") log("%s\n", line.c_str()); | ||||||
|  | 						} | ||||||
|  | 					} else if (help_cell.desc.length()) { | ||||||
|  | 						log("%s\n", help_cell.desc.c_str()); | ||||||
|  | 					} else { | ||||||
|  | 						log("No help message for this cell type found.\n"); | ||||||
|  | 					} | ||||||
|  | 					log("\nRun 'help %s+' to display the Verilog model for this cell type.\n", args[1].c_str()); | ||||||
| 					log("\n"); | 					log("\n"); | ||||||
| 				} | 				} | ||||||
| 			else if (cell_help_messages.cell_code.count(args[1])) { |  | ||||||
| 				log("\n"); |  | ||||||
| 				log("%s", cell_help_messages.cell_code.at(args[1]).c_str()); |  | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				log("No such command or cell type: %s\n", args[1].c_str()); | 				log("No such command or cell type: %s\n", args[1].c_str()); | ||||||
| 			return; | 			return; | ||||||
|  | 		} else if (args.size() == 3) { | ||||||
|  | 			if (args[1] == "-dump-cells-json") { | ||||||
|  | 				PrettyJson json; | ||||||
|  | 				if (!json.write_to_file(args[2])) | ||||||
|  | 					log_error("Can't open file `%s' for writing: %s\n", args[2].c_str(), strerror(errno)); | ||||||
|  | 				if (dump_cells_json(json)) { | ||||||
|  | 					log_error("One or more cells defined in celltypes.h are missing help documentation.\n"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		help(); | 		help(); | ||||||
|  |  | ||||||
|  | @ -1,34 +1,100 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| 
 | 
 | ||||||
|  | from __future__ import annotations | ||||||
| import fileinput | import fileinput | ||||||
| import json | import json | ||||||
|  | from pathlib import Path | ||||||
| 
 | 
 | ||||||
| current_help_msg = [] | class SimHelper: | ||||||
| current_module_code = [] |     name: str = "" | ||||||
| current_module_name = None |     title: str = "" | ||||||
| current_module_signature = None |     ports: str = "" | ||||||
|  |     source: str = "" | ||||||
|  |     desc: list[str] | ||||||
|  |     code: list[str] | ||||||
|  |     group: str = "" | ||||||
|  |     ver: str = "1" | ||||||
|  |     tags: list[str] | ||||||
| 
 | 
 | ||||||
| def print_current_cell(): |     def __init__(self) -> None: | ||||||
|     print("cell_help[\"%s\"] = %s;" % (current_module_name, "\n".join([json.dumps(line) for line in current_help_msg]))) |         self.desc = [] | ||||||
|     print("cell_code[\"%s+\"] = %s;" % (current_module_name, "\n".join([json.dumps(line) for line in current_module_code]))) |         self.tags = [] | ||||||
|  |      | ||||||
|  |     def __str__(self) -> str: | ||||||
|  |         printed_fields = [ | ||||||
|  |             "name", "title", "ports", "source", "desc", "code", "group", "ver", | ||||||
|  |             "tags", | ||||||
|  |         ] | ||||||
|  |         # generate C++ struct | ||||||
|  |         val = f"cell_help[{json.dumps(self.name)}] = " | ||||||
|  |         val += "{\n" | ||||||
|  |         for field in printed_fields: | ||||||
|  |             field_val = getattr(self, field) | ||||||
|  |             if isinstance(field_val, list): | ||||||
|  |                 field_val = "\n".join(field_val) | ||||||
|  |             field_val = field_val.strip() | ||||||
|  |             val += f'  {json.dumps(field_val)},\n' | ||||||
|  |         val += "};\n" | ||||||
|  |         return val | ||||||
|  | 
 | ||||||
|  | def simcells_reparse(cell: SimHelper): | ||||||
|  |     # cut manual signature | ||||||
|  |     cell.desc = cell.desc[3:] | ||||||
|  | 
 | ||||||
|  |     # code-block truth table | ||||||
|  |     new_desc = [] | ||||||
|  |     indent = "" | ||||||
|  |     for line in cell.desc: | ||||||
|  |         if line.startswith("Truth table:"): | ||||||
|  |             indent = "   " | ||||||
|  |             new_desc.pop() | ||||||
|  |             new_desc.extend(["::", ""]) | ||||||
|  |         new_desc.append(indent + line) | ||||||
|  |     cell.desc = new_desc | ||||||
|  | 
 | ||||||
|  |     # set version | ||||||
|  |     cell.ver = "2a" | ||||||
|  | 
 | ||||||
|  | simHelper = SimHelper() | ||||||
| 
 | 
 | ||||||
| for line in fileinput.input(): | for line in fileinput.input(): | ||||||
|  |     line = line.rstrip() | ||||||
|  |     # special comments | ||||||
|     if line.startswith("//-"): |     if line.startswith("//-"): | ||||||
|         current_help_msg.append(line[4:] if len(line) > 4 else "\n") |         simHelper.desc.append(line[4:] if len(line) > 4 else "") | ||||||
|  |     elif line.startswith("//* "): | ||||||
|  |         _, key, val = line.split(maxsplit=2) | ||||||
|  |         setattr(simHelper, key, val) | ||||||
|  |      | ||||||
|  |     # code parsing | ||||||
|     if line.startswith("module "): |     if line.startswith("module "): | ||||||
|         current_module_name = line.split()[1].strip("\\") |         clean_line = line[7:].replace("\\", "").replace(";", "") | ||||||
|         current_module_signature = " ".join(line.replace("\\", "").replace(";", "").split()[1:]) |         simHelper.name, simHelper.ports = clean_line.split(maxsplit=1) | ||||||
|         current_module_code = [] |         simHelper.code = [] | ||||||
|  |         short_filename = Path(fileinput.filename()).name | ||||||
|  |         simHelper.source = f'{short_filename}:{fileinput.filelineno()}' | ||||||
|     elif not line.startswith("endmodule"): |     elif not line.startswith("endmodule"): | ||||||
|         line = "    " + line |         line = "    " + line | ||||||
|     current_module_code.append(line.replace("\t", "    ")) |     try: | ||||||
|  |         simHelper.code.append(line.replace("\t", "    ")) | ||||||
|  |     except AttributeError: | ||||||
|  |         # no module definition, ignore line | ||||||
|  |         pass | ||||||
|     if line.startswith("endmodule"): |     if line.startswith("endmodule"): | ||||||
|         if len(current_help_msg) == 0: |         short_filename = Path(fileinput.filename()).name | ||||||
|             current_help_msg.append("\n") |         if simHelper.ver == "1" and short_filename == "simcells.v": | ||||||
|             current_help_msg.append("    %s\n" % current_module_signature) |             # default simcells parsing | ||||||
|             current_help_msg.append("\n") |             simcells_reparse(simHelper) | ||||||
|             current_help_msg.append("No help message for this cell type found.\n") | 
 | ||||||
|             current_help_msg.append("\n") |         # check help | ||||||
|         print_current_cell() |         if simHelper.desc and simHelper.ver == "1" and short_filename == "simlib.v" and simHelper.desc[1].startswith('    '): | ||||||
|         current_help_msg = [] |             simHelper.desc.pop(1) | ||||||
|  | 
 | ||||||
|  |         # check group | ||||||
|  |         assert simHelper.group, f"techlibs/common/{simHelper.source}: {simHelper.name} cell missing group" | ||||||
|  | 
 | ||||||
|  |         # dump | ||||||
|  |         print(simHelper) | ||||||
|  |         # new | ||||||
|  |         simHelper = SimHelper() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ TEMPLATES = [ | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_SR_{S:N|P}{R:N|P}_ (S, R, Q) | //-     $_SR_{S:N|P}{R:N|P}_ (S, R, Q) | ||||||
|  | //* group reg_latch | ||||||
| //- | //- | ||||||
| //- A set-reset latch with {S:negative|positive} polarity SET and {R:negative|positive} polarity RESET. | //- A set-reset latch with {S:negative|positive} polarity SET and {R:negative|positive} polarity RESET. | ||||||
| //- | //- | ||||||
|  | @ -28,6 +29,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_FF_ (D, Q) | //-     $_FF_ (D, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A D-type flip-flop that is clocked from the implicit global clock. (This cell | //- A D-type flip-flop that is clocked from the implicit global clock. (This cell | ||||||
| //- type is usually only used in netlists for formal verification.) | //- type is usually only used in netlists for formal verification.) | ||||||
|  | @ -45,6 +47,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFF_{C:N|P}_ (D, C, Q) | //-     $_DFF_{C:N|P}_ (D, C, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop. | //- A {C:negative|positive} edge D-type flip-flop. | ||||||
| //- | //- | ||||||
|  | @ -65,6 +68,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q) | //-     $_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {E:negative|positive} polarity enable. | //- A {C:negative|positive} edge D-type flip-flop with {E:negative|positive} polarity enable. | ||||||
| //- | //- | ||||||
|  | @ -85,6 +89,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) | //-     $_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set}. | //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set}. | ||||||
| //- | //- | ||||||
|  | @ -109,6 +114,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | //-     $_DFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set} and {E:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set} and {E:negative|positive} | ||||||
| //- polarity clock enable. | //- polarity clock enable. | ||||||
|  | @ -134,6 +140,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q) | //-     $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load. | //- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load. | ||||||
| //- | //- | ||||||
|  | @ -158,6 +165,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q) | //-     $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive} | ||||||
| //- polarity clock enable. | //- polarity clock enable. | ||||||
|  | @ -183,6 +191,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q) | //-     $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive} | ||||||
| //- polarity reset. | //- polarity reset. | ||||||
|  | @ -211,6 +220,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DFFSRE_{C:N|P}{S:N|P}{R:N|P}{E:N|P}_ (C, S, R, E, D, Q) | //-     $_DFFSRE_{C:N|P}{S:N|P}{R:N|P}{E:N|P}_ (C, S, R, E, D, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set, {R:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set, {R:negative|positive} | ||||||
| //- polarity reset and {E:negative|positive} polarity clock enable. | //- polarity reset and {E:negative|positive} polarity clock enable. | ||||||
|  | @ -239,6 +249,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_SDFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) | //-     $_SDFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set}. | //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set}. | ||||||
| //- | //- | ||||||
|  | @ -263,6 +274,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_SDFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | //-     $_SDFFE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} | ||||||
| //- polarity clock enable (with {V:reset|set} having priority). | //- polarity clock enable (with {V:reset|set} having priority). | ||||||
|  | @ -288,6 +300,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_SDFFCE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | //-     $_SDFFCE_{C:N|P}{R:N|P}{V:0|1}{E:N|P}_ (D, C, R, E, Q) | ||||||
|  | //* group reg_ff | ||||||
| //- | //- | ||||||
| //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} | //- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity synchronous {V:reset|set} and {E:negative|positive} | ||||||
| //- polarity clock enable (with clock enable having priority). | //- polarity clock enable (with clock enable having priority). | ||||||
|  | @ -315,6 +328,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DLATCH_{E:N|P}_ (E, D, Q) | //-     $_DLATCH_{E:N|P}_ (E, D, Q) | ||||||
|  | //* group reg_latch | ||||||
| //- | //- | ||||||
| //- A {E:negative|positive} enable D-type latch. | //- A {E:negative|positive} enable D-type latch. | ||||||
| //- | //- | ||||||
|  | @ -336,6 +350,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DLATCH_{E:N|P}{R:N|P}{V:0|1}_ (E, R, D, Q) | //-     $_DLATCH_{E:N|P}{R:N|P}{V:0|1}_ (E, R, D, Q) | ||||||
|  | //* group reg_latch | ||||||
| //- | //- | ||||||
| //- A {E:negative|positive} enable D-type latch with {R:negative|positive} polarity {V:reset|set}. | //- A {E:negative|positive} enable D-type latch with {R:negative|positive} polarity {V:reset|set}. | ||||||
| //- | //- | ||||||
|  | @ -360,6 +375,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | ||||||
| //- | //- | ||||||
| //-     $_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q) | //-     $_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q) | ||||||
|  | //* group reg_latch | ||||||
| //- | //- | ||||||
| //- A {E:negative|positive} enable D-type latch with {S:negative|positive} polarity set and {R:negative|positive} | //- A {E:negative|positive} enable D-type latch with {S:negative|positive} polarity set and {R:negative|positive} | ||||||
| //- polarity reset. | //- polarity reset. | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -32,12 +32,10 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Bit-wise inverter
 | ||||||
| //-
 | //* group unary
 | ||||||
| //-     $not (A, Y)
 | //- This corresponds to the Verilog unary prefix '~' operator.
 | ||||||
| //-
 |  | ||||||
| //- A bit-wise inverter. This corresponds to the Verilog unary prefix '~' operator.
 |  | ||||||
| //-
 | //-
 | ||||||
| module \$not (A, Y); | module \$not (A, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -63,6 +61,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $pos (A, Y)
 | //-     $pos (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- A buffer. This corresponds to the Verilog unary prefix '+' operator.
 | //- A buffer. This corresponds to the Verilog unary prefix '+' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -90,6 +89,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $buf (A, Y)
 | //-     $buf (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- A simple coarse-grain buffer cell type for the experimental buffered-normalized
 | //- A simple coarse-grain buffer cell type for the experimental buffered-normalized
 | ||||||
| //- mode. Note this cell does't get removed by 'opt_clean' and is not recommended
 | //- mode. Note this cell does't get removed by 'opt_clean' and is not recommended
 | ||||||
|  | @ -111,6 +111,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $neg (A, Y)
 | //-     $neg (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator.
 | //- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -138,6 +139,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $and (A, B, Y)
 | //-     $and (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A bit-wise AND. This corresponds to the Verilog '&' operator.
 | //- A bit-wise AND. This corresponds to the Verilog '&' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -168,6 +170,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $or (A, B, Y)
 | //-     $or (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A bit-wise OR. This corresponds to the Verilog '|' operator.
 | //- A bit-wise OR. This corresponds to the Verilog '|' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -198,6 +201,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $xor (A, B, Y)
 | //-     $xor (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A bit-wise XOR. This corresponds to the Verilog '^' operator.
 | //- A bit-wise XOR. This corresponds to the Verilog '^' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -228,6 +232,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $xnor (A, B, Y)
 | //-     $xnor (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A bit-wise XNOR. This corresponds to the Verilog '~^' operator.
 | //- A bit-wise XNOR. This corresponds to the Verilog '~^' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -258,6 +263,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $reduce_and (A, Y)
 | //-     $reduce_and (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
 | //- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -285,6 +291,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $reduce_or (A, Y)
 | //-     $reduce_or (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
 | //- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -312,6 +319,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $reduce_xor (A, Y)
 | //-     $reduce_xor (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
 | //- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -339,6 +347,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $reduce_xnor (A, Y)
 | //-     $reduce_xnor (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
 | //- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -366,6 +375,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $reduce_bool (A, Y)
 | //-     $reduce_bool (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- An OR reduction. This cell type is used instead of $reduce_or when a signal is
 | //- An OR reduction. This cell type is used instead of $reduce_or when a signal is
 | ||||||
| //- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
 | //- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
 | ||||||
|  | @ -394,6 +404,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $shl (A, B, Y)
 | //-     $shl (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A logical shift-left operation. This corresponds to the Verilog '<<' operator.
 | //- A logical shift-left operation. This corresponds to the Verilog '<<' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -424,6 +435,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $shr (A, B, Y)
 | //-     $shr (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A logical shift-right operation. This corresponds to the Verilog '>>' operator.
 | //- A logical shift-right operation. This corresponds to the Verilog '>>' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -454,6 +466,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $sshl (A, B, Y)
 | //-     $sshl (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- An arithmatic shift-left operation. 
 | //- An arithmatic shift-left operation. 
 | ||||||
| //- This corresponds to the Verilog '<<<' operator.
 | //- This corresponds to the Verilog '<<<' operator.
 | ||||||
|  | @ -485,6 +498,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $sshr (A, B, Y)
 | //-     $sshr (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- An arithmatic shift-right operation.
 | //- An arithmatic shift-right operation.
 | ||||||
| //- This corresponds to the Verilog '>>>' operator.
 | //- This corresponds to the Verilog '>>>' operator.
 | ||||||
|  | @ -512,7 +526,12 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Variable shifter
 | ||||||
|  | //* group binary
 | ||||||
|  | //- Performs a right logical shift if the second operand is positive (or
 | ||||||
|  | //- unsigned), and a left logical shift if it is negative.
 | ||||||
|  | //-
 | ||||||
| module \$shift (A, B, Y); | module \$shift (A, B, Y); | ||||||
| 
 | 
 | ||||||
| parameter A_SIGNED = 0; | parameter A_SIGNED = 0; | ||||||
|  | @ -544,7 +563,12 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Indexed part-select
 | ||||||
|  | //* group binary
 | ||||||
|  | //* tags x-output
 | ||||||
|  | //- Same as the `$shift` cell, but fills with 'x'.
 | ||||||
|  | //-
 | ||||||
| module \$shiftx (A, B, Y); | module \$shiftx (A, B, Y); | ||||||
| 
 | 
 | ||||||
| parameter A_SIGNED = 0; | parameter A_SIGNED = 0; | ||||||
|  | @ -569,7 +593,7 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group arith
 | ||||||
| module \$fa (A, B, C, X, Y); | module \$fa (A, B, C, X, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 1; | parameter WIDTH = 1; | ||||||
|  | @ -585,6 +609,7 @@ assign Y = t1 ^ C, X = (t2 | t3) ^ (Y ^ Y); | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group arith
 | ||||||
| 
 | 
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -620,17 +645,14 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Arithmetic logic unit
 | ||||||
| //-
 | //* group arith
 | ||||||
| //-     $alu (A, B, CI, BI, X, Y, CO)
 |  | ||||||
| //-
 |  | ||||||
| //- Arithmetic logic unit.
 |  | ||||||
| //- A building block supporting both binary addition/subtraction operations, and
 | //- A building block supporting both binary addition/subtraction operations, and
 | ||||||
| //- indirectly, comparison operations.
 | //- indirectly, comparison operations.
 | ||||||
| //- Typically created by the `alumacc` pass, which transforms:
 | //- Typically created by the `alumacc` pass, which transforms:
 | ||||||
| //-   $add, $sub, $lt, $le, $ge, $gt, $eq, $eqx, $ne, $nex
 | //- `$add`, `$sub`, `$lt`, `$le`, `$ge`, `$gt`, `$eq`, `$eqx`, `$ne`, `$nex`
 | ||||||
| //- cells into this $alu cell.
 | //- cells into this `$alu` cell.
 | ||||||
| //-
 | //-
 | ||||||
| module \$alu (A, B, CI, BI, X, Y, CO); | module \$alu (A, B, CI, BI, X, Y, CO); | ||||||
| 
 | 
 | ||||||
|  | @ -688,6 +710,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $lt (A, B, Y)
 | //-     $lt (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A less-than comparison between inputs 'A' and 'B'. 
 | //- A less-than comparison between inputs 'A' and 'B'. 
 | ||||||
| //- This corresponds to the Verilog '<' operator.
 | //- This corresponds to the Verilog '<' operator.
 | ||||||
|  | @ -719,6 +742,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $le (A, B, Y)
 | //-     $le (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A less-than-or-equal-to comparison between inputs 'A' and 'B'. 
 | //- A less-than-or-equal-to comparison between inputs 'A' and 'B'. 
 | ||||||
| //- This corresponds to the Verilog '<=' operator.
 | //- This corresponds to the Verilog '<=' operator.
 | ||||||
|  | @ -750,6 +774,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $eq (A, B, Y)
 | //-     $eq (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- An equality comparison between inputs 'A' and 'B'. 
 | //- An equality comparison between inputs 'A' and 'B'. 
 | ||||||
| //- This corresponds to the Verilog '==' operator.
 | //- This corresponds to the Verilog '==' operator.
 | ||||||
|  | @ -781,6 +806,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $ne (A, B, Y)
 | //-     $ne (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- An inequality comparison between inputs 'A' and 'B'. 
 | //- An inequality comparison between inputs 'A' and 'B'. 
 | ||||||
| //- This corresponds to the Verilog '!=' operator.
 | //- This corresponds to the Verilog '!=' operator.
 | ||||||
|  | @ -808,15 +834,15 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Case equality
 | ||||||
| //-
 | //* group binary
 | ||||||
| //-     $eqx (A, B, Y)
 | //* tags x-aware
 | ||||||
| //-
 | //- An exact equality comparison between inputs 'A' and 'B'. Also known as the
 | ||||||
| //- An exact equality comparison between inputs 'A' and 'B'. 
 | //- case equality operator. This corresponds to the Verilog '===' operator.
 | ||||||
| //- This corresponds to the Verilog '===' operator.
 | //- Unlike equality comparison that can give 'x' as output, an exact equality
 | ||||||
| //- Unlike equality comparison that can give 'x' as output, 
 | //- comparison will strictly give '0' or '1' as output, even if input includes
 | ||||||
| //- an exact equality comparison will strictly give '0' or '1' as output.
 | //- 'x' or 'z' values.
 | ||||||
| //-
 | //-
 | ||||||
| module \$eqx (A, B, Y); | module \$eqx (A, B, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -841,15 +867,13 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Case inequality
 | ||||||
| //-
 | //* group binary
 | ||||||
| //-     $nex (A, B, Y)
 | //* tags x-aware
 | ||||||
| //-
 |  | ||||||
| //- An exact inequality comparison between inputs 'A' and 'B'. 
 |  | ||||||
| //- This corresponds to the Verilog '!==' operator.
 | //- This corresponds to the Verilog '!==' operator.
 | ||||||
| //- Unlike inequality comparison that can give 'x' as output, 
 | //-
 | ||||||
| //- an exact inequality comparison will strictly give '0' or '1' as output.
 | //- Refer to `$eqx` for more details.
 | ||||||
| //-
 | //-
 | ||||||
| module \$nex (A, B, Y); | module \$nex (A, B, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -878,6 +902,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $ge (A, B, Y)
 | //-     $ge (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A greater-than-or-equal-to comparison between inputs 'A' and 'B'.
 | //- A greater-than-or-equal-to comparison between inputs 'A' and 'B'.
 | ||||||
| //- This corresponds to the Verilog '>=' operator.
 | //- This corresponds to the Verilog '>=' operator.
 | ||||||
|  | @ -909,6 +934,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $gt (A, B, Y)
 | //-     $gt (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A greater-than comparison between inputs 'A' and 'B'. 
 | //- A greater-than comparison between inputs 'A' and 'B'. 
 | ||||||
| //- This corresponds to the Verilog '>' operator.
 | //- This corresponds to the Verilog '>' operator.
 | ||||||
|  | @ -940,6 +966,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $add (A, B, Y)
 | //-     $add (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //-  Addition of inputs 'A' and 'B'. This corresponds to the Verilog '+' operator.
 | //-  Addition of inputs 'A' and 'B'. This corresponds to the Verilog '+' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -970,6 +997,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $sub (A, B, Y)
 | //-     $sub (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- Subtraction between inputs 'A' and 'B'.
 | //- Subtraction between inputs 'A' and 'B'.
 | ||||||
| //- This corresponds to the Verilog '-' operator.
 | //- This corresponds to the Verilog '-' operator.
 | ||||||
|  | @ -1001,6 +1029,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $mul (A, B, Y)
 | //-     $mul (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- Multiplication of inputs 'A' and 'B'.
 | //- Multiplication of inputs 'A' and 'B'.
 | ||||||
| //- This corresponds to the Verilog '*' operator.
 | //- This corresponds to the Verilog '*' operator.
 | ||||||
|  | @ -1031,6 +1060,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $macc (A, B, Y)
 | //-     $macc (A, B, Y)
 | ||||||
|  | //* group arith
 | ||||||
| //-
 | //-
 | ||||||
| //- Multiply and accumulate.
 | //- Multiply and accumulate.
 | ||||||
| //- A building block for summing any number of negated and unnegated signals
 | //- A building block for summing any number of negated and unnegated signals
 | ||||||
|  | @ -1178,12 +1208,12 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Divider
 | ||||||
| //-
 | //* group binary
 | ||||||
| //-     $div (A, B, Y)
 | //* tags x-output
 | ||||||
| //-
 | //- This corresponds to the Verilog '/' operator, performing division and
 | ||||||
| //- Division with truncated result (rounded towards 0).
 | //- truncating the result (rounding towards 0).
 | ||||||
| //-
 | //-
 | ||||||
| module \$div (A, B, Y); | module \$div (A, B, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1208,12 +1238,12 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //* title Modulo
 | ||||||
| //-
 | //* group binary
 | ||||||
| //-     $mod (A, B, Y)
 | //* tags x-output
 | ||||||
| //-
 | //- This corresponds to the Verilog '%' operator, giving the module (or
 | ||||||
| //- Modulo/remainder of division with truncated result (rounded towards 0).
 | //- remainder) of division and truncating the result (rounding towards 0).
 | ||||||
| //-
 | //-
 | ||||||
| //- Invariant: $div(A, B) * B + $mod(A, B) == A
 | //- Invariant: $div(A, B) * B + $mod(A, B) == A
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1244,6 +1274,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $divfloor (A, B, Y)
 | //-     $divfloor (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- Division with floored result (rounded towards negative infinity).
 | //- Division with floored result (rounded towards negative infinity).
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1281,6 +1312,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $modfloor (A, B, Y)
 | //-     $modfloor (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- Modulo/remainder of division with floored result (rounded towards negative infinity).
 | //- Modulo/remainder of division with floored result (rounded towards negative infinity).
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1321,6 +1353,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $pow (A, B, Y)
 | //-     $pow (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- Exponentiation of an input (Y = A ** B). 
 | //- Exponentiation of an input (Y = A ** B). 
 | ||||||
| //- This corresponds to the Verilog '**' operator.
 | //- This corresponds to the Verilog '**' operator.
 | ||||||
|  | @ -1359,6 +1392,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $logic_not (A, Y)
 | //-     $logic_not (A, Y)
 | ||||||
|  | //* group unary
 | ||||||
| //-
 | //-
 | ||||||
| //- A logical inverter. This corresponds to the Verilog unary prefix '!' operator.
 | //- A logical inverter. This corresponds to the Verilog unary prefix '!' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1386,6 +1420,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $logic_and (A, B, Y)
 | //-     $logic_and (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A logical AND. This corresponds to the Verilog '&&' operator.
 | //- A logical AND. This corresponds to the Verilog '&&' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1416,6 +1451,7 @@ endmodule | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $logic_or (A, B, Y)
 | //-     $logic_or (A, B, Y)
 | ||||||
|  | //* group binary
 | ||||||
| //-
 | //-
 | ||||||
| //- A logical OR. This corresponds to the Verilog '||' operator.
 | //- A logical OR. This corresponds to the Verilog '||' operator.
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1442,7 +1478,7 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group wire
 | ||||||
| module \$slice (A, Y); | module \$slice (A, Y); | ||||||
| 
 | 
 | ||||||
| parameter OFFSET = 0; | parameter OFFSET = 0; | ||||||
|  | @ -1457,10 +1493,10 @@ assign Y = A >> OFFSET; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 |  | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
| //-     $concat (A, B, Y)
 | //-     $concat (A, B, Y)
 | ||||||
|  | //* group wire
 | ||||||
| //-
 | //-
 | ||||||
| //- Concatenation of inputs into a single output ( Y = {B, A} ).
 | //- Concatenation of inputs into a single output ( Y = {B, A} ).
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1478,6 +1514,7 @@ assign Y = {B, A}; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mux
 | ||||||
| 
 | 
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1498,7 +1535,12 @@ assign Y = S ? B : A; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Binary-encoded multiplexer
 | ||||||
|  | //* group mux
 | ||||||
|  | //- Selects between 'slices' of A where each value of S corresponds to a unique
 | ||||||
|  | //- slice.
 | ||||||
|  | //-
 | ||||||
| module \$bmux (A, S, Y); | module \$bmux (A, S, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -1525,7 +1567,13 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Priority-encoded multiplexer
 | ||||||
|  | //* group mux
 | ||||||
|  | //* tags x-output
 | ||||||
|  | //- Selects between 'slices' of B where each slice corresponds to a single bit
 | ||||||
|  | //- of S. Outputs A when all bits of S are low.
 | ||||||
|  | //-
 | ||||||
| module \$pmux (A, B, S, Y); | module \$pmux (A, B, S, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -1559,6 +1607,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mux
 | ||||||
| 
 | 
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1587,6 +1636,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| `ifndef SIMLIB_NOLUT | `ifndef SIMLIB_NOLUT | ||||||
|  | //* group logic
 | ||||||
| 
 | 
 | ||||||
| module \$lut (A, Y); | module \$lut (A, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1602,6 +1652,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| `endif | `endif | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group logic
 | ||||||
| 
 | 
 | ||||||
| module \$sop (A, Y); | module \$sop (A, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1630,6 +1681,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mux
 | ||||||
| 
 | 
 | ||||||
| //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | //  |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| //-
 | //-
 | ||||||
|  | @ -1652,6 +1704,7 @@ assign Y = EN ? A : 'bz; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group spec
 | ||||||
| 
 | 
 | ||||||
| module \$specify2 (EN, SRC, DST); | module \$specify2 (EN, SRC, DST); | ||||||
| 
 | 
 | ||||||
|  | @ -1690,6 +1743,7 @@ endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group spec
 | ||||||
| 
 | 
 | ||||||
| module \$specify3 (EN, SRC, DST, DAT); | module \$specify3 (EN, SRC, DST, DAT); | ||||||
| 
 | 
 | ||||||
|  | @ -1798,6 +1852,7 @@ endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group spec
 | ||||||
| 
 | 
 | ||||||
| module \$specrule (EN_SRC, EN_DST, SRC, DST); | module \$specrule (EN_SRC, EN_DST, SRC, DST); | ||||||
| 
 | 
 | ||||||
|  | @ -1827,7 +1882,12 @@ endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Bit-wise case equality
 | ||||||
|  | //* group binary
 | ||||||
|  | //* tags x-aware
 | ||||||
|  | //- A bit-wise version of `$eqx`.
 | ||||||
|  | //-
 | ||||||
| module \$bweqx (A, B, Y); | module \$bweqx (A, B, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -1845,7 +1905,11 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* ver 2
 | ||||||
|  | //* title Bit-wise multiplexer
 | ||||||
|  | //* group mux
 | ||||||
|  | //- Equivalent to a series of 1-bit wide `$mux` cells.
 | ||||||
|  | //-
 | ||||||
| module \$bwmux (A, B, S, Y); | module \$bwmux (A, B, S, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -1864,6 +1928,7 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$assert (A, EN); | module \$assert (A, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -1881,6 +1946,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$assume (A, EN); | module \$assume (A, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -1898,6 +1964,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$live (A, EN); | module \$live (A, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -1906,6 +1973,7 @@ input A, EN; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$fair (A, EN); | module \$fair (A, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -1914,6 +1982,7 @@ input A, EN; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$cover (A, EN); | module \$cover (A, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -1922,6 +1991,7 @@ input A, EN; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$initstate (Y); | module \$initstate (Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1939,6 +2009,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$anyconst (Y); | module \$anyconst (Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1951,6 +2022,7 @@ assign Y = 'bx; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$anyseq (Y); | module \$anyseq (Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1967,6 +2039,7 @@ endmodule | ||||||
| `ifndef SIMLIB_GLOBAL_CLOCK | `ifndef SIMLIB_GLOBAL_CLOCK | ||||||
| `define SIMLIB_GLOBAL_CLOCK $global_clk | `define SIMLIB_GLOBAL_CLOCK $global_clk | ||||||
| `endif | `endif | ||||||
|  | //* group formal
 | ||||||
| module \$anyinit (D, Q); | module \$anyinit (D, Q); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -1983,6 +2056,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| `endif | `endif | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$allconst (Y); | module \$allconst (Y); | ||||||
| 
 | 
 | ||||||
|  | @ -1995,6 +2069,7 @@ assign Y = 'bx; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$allseq (Y); | module \$allseq (Y); | ||||||
| 
 | 
 | ||||||
|  | @ -2007,6 +2082,7 @@ assign Y = 'bx; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$equiv (A, B, Y); | module \$equiv (A, B, Y); | ||||||
| 
 | 
 | ||||||
|  | @ -2027,6 +2103,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group debug
 | ||||||
| 
 | 
 | ||||||
| module \$print (EN, TRG, ARGS); | module \$print (EN, TRG, ARGS); | ||||||
| 
 | 
 | ||||||
|  | @ -2046,6 +2123,7 @@ input [ARGS_WIDTH-1:0] ARGS; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group debug
 | ||||||
| 
 | 
 | ||||||
| module \$check (A, EN, TRG, ARGS); | module \$check (A, EN, TRG, ARGS); | ||||||
| 
 | 
 | ||||||
|  | @ -2068,6 +2146,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| `ifndef SIMLIB_NOSR | `ifndef SIMLIB_NOSR | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$sr (SET, CLR, Q); | module \$sr (SET, CLR, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2100,6 +2179,7 @@ endmodule | ||||||
| `ifndef SIMLIB_GLOBAL_CLOCK | `ifndef SIMLIB_GLOBAL_CLOCK | ||||||
| `define SIMLIB_GLOBAL_CLOCK $global_clk | `define SIMLIB_GLOBAL_CLOCK $global_clk | ||||||
| `endif | `endif | ||||||
|  | //* group formal
 | ||||||
| 
 | 
 | ||||||
| module \$ff (D, Q); | module \$ff (D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2116,6 +2196,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| `endif | `endif | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dff (CLK, D, Q); | module \$dff (CLK, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2134,6 +2215,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dffe (CLK, EN, D, Q); | module \$dffe (CLK, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2154,6 +2236,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| `ifndef SIMLIB_NOSR | `ifndef SIMLIB_NOSR | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dffsr (CLK, SET, CLR, D, Q); | module \$dffsr (CLK, SET, CLR, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2186,6 +2269,7 @@ endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dffsre (CLK, SET, CLR, EN, D, Q); | module \$dffsre (CLK, SET, CLR, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2220,6 +2304,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| `endif | `endif | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$adff (CLK, ARST, D, Q); | module \$adff (CLK, ARST, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2244,6 +2329,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$aldff (CLK, ALOAD, AD, D, Q); | module \$aldff (CLK, ALOAD, AD, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2268,6 +2354,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$sdff (CLK, SRST, D, Q); | module \$sdff (CLK, SRST, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2292,6 +2379,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$adffe (CLK, ARST, EN, D, Q); | module \$adffe (CLK, ARST, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2317,6 +2405,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$aldffe (CLK, ALOAD, AD, EN, D, Q); | module \$aldffe (CLK, ALOAD, AD, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2342,6 +2431,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$sdffe (CLK, SRST, EN, D, Q); | module \$sdffe (CLK, SRST, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2367,6 +2457,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$sdffce (CLK, SRST, EN, D, Q); | module \$sdffce (CLK, SRST, EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2394,6 +2485,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dlatch (EN, D, Q); | module \$dlatch (EN, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2412,6 +2504,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$adlatch (EN, ARST, D, Q); | module \$adlatch (EN, ARST, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2435,6 +2528,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| `ifndef SIMLIB_NOSR | `ifndef SIMLIB_NOSR | ||||||
|  | //* group reg
 | ||||||
| 
 | 
 | ||||||
| module \$dlatchsr (EN, SET, CLR, D, Q); | module \$dlatchsr (EN, SET, CLR, D, Q); | ||||||
| 
 | 
 | ||||||
|  | @ -2468,6 +2562,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| `endif | `endif | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group fsm
 | ||||||
| 
 | 
 | ||||||
| module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); | module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); | ||||||
| 
 | 
 | ||||||
|  | @ -2562,6 +2657,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| `ifndef SIMLIB_NOMEM | `ifndef SIMLIB_NOMEM | ||||||
|  | //* group mem
 | ||||||
| 
 | 
 | ||||||
| module \$memrd (CLK, EN, ADDR, DATA); | module \$memrd (CLK, EN, ADDR, DATA); | ||||||
| 
 | 
 | ||||||
|  | @ -2586,6 +2682,8 @@ end | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | //* group mem
 | ||||||
|  | 
 | ||||||
| module \$memrd_v2 (CLK, EN, ARST, SRST, ADDR, DATA); | module \$memrd_v2 (CLK, EN, ARST, SRST, ADDR, DATA); | ||||||
| 
 | 
 | ||||||
| parameter MEMID = ""; | parameter MEMID = ""; | ||||||
|  | @ -2615,6 +2713,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mem
 | ||||||
| 
 | 
 | ||||||
| module \$memwr (CLK, EN, ADDR, DATA); | module \$memwr (CLK, EN, ADDR, DATA); | ||||||
| 
 | 
 | ||||||
|  | @ -2640,6 +2739,7 @@ end | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | //* group mem
 | ||||||
| module \$memwr_v2 (CLK, EN, ADDR, DATA); | module \$memwr_v2 (CLK, EN, ADDR, DATA); | ||||||
| 
 | 
 | ||||||
| parameter MEMID = ""; | parameter MEMID = ""; | ||||||
|  | @ -2666,6 +2766,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mem
 | ||||||
| 
 | 
 | ||||||
| module \$meminit (ADDR, DATA); | module \$meminit (ADDR, DATA); | ||||||
| 
 | 
 | ||||||
|  | @ -2689,6 +2790,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mem
 | ||||||
| 
 | 
 | ||||||
| module \$meminit_v2 (ADDR, DATA, EN); | module \$meminit_v2 (ADDR, DATA, EN); | ||||||
| 
 | 
 | ||||||
|  | @ -2713,6 +2815,7 @@ end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
|  | //* group mem
 | ||||||
| 
 | 
 | ||||||
| module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); | module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); | ||||||
| 
 | 
 | ||||||
|  | @ -2801,6 +2904,8 @@ end | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | //* group mem
 | ||||||
|  | 
 | ||||||
| module \$mem_v2 (RD_CLK, RD_EN, RD_ARST, RD_SRST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); | module \$mem_v2 (RD_CLK, RD_EN, RD_ARST, RD_SRST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); | ||||||
| 
 | 
 | ||||||
| parameter MEMID = ""; | parameter MEMID = ""; | ||||||
|  | @ -2920,7 +3025,7 @@ endmodule | ||||||
| `endif | `endif | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group formal_tag
 | ||||||
| module \$set_tag (A, SET, CLR, Y); | module \$set_tag (A, SET, CLR, Y); | ||||||
| 
 | 
 | ||||||
| parameter TAG = ""; | parameter TAG = ""; | ||||||
|  | @ -2936,7 +3041,7 @@ assign Y = A; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group formal_tag
 | ||||||
| module \$get_tag (A, Y); | module \$get_tag (A, Y); | ||||||
| 
 | 
 | ||||||
| parameter TAG = ""; | parameter TAG = ""; | ||||||
|  | @ -2950,7 +3055,7 @@ assign Y = A; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group formal_tag
 | ||||||
| module \$overwrite_tag (A, SET, CLR); | module \$overwrite_tag (A, SET, CLR); | ||||||
| 
 | 
 | ||||||
| parameter TAG = ""; | parameter TAG = ""; | ||||||
|  | @ -2963,7 +3068,7 @@ input [WIDTH-1:0] CLR; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group formal_tag
 | ||||||
| module \$original_tag (A, Y); | module \$original_tag (A, Y); | ||||||
| 
 | 
 | ||||||
| parameter TAG = ""; | parameter TAG = ""; | ||||||
|  | @ -2977,7 +3082,7 @@ assign Y = A; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group formal_tag
 | ||||||
| module \$future_ff (A, Y); | module \$future_ff (A, Y); | ||||||
| 
 | 
 | ||||||
| parameter WIDTH = 0; | parameter WIDTH = 0; | ||||||
|  | @ -2990,7 +3095,7 @@ assign Y = A; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------------------------
 | // --------------------------------------------------------
 | ||||||
| 
 | //* group debug
 | ||||||
| (* noblackbox *) | (* noblackbox *) | ||||||
| module \$scopeinfo (); | module \$scopeinfo (); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue