From 449135a9d4c1817611bbf3edf8e887bc9ae6b485 Mon Sep 17 00:00:00 2001
From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com>
Date: Wed, 24 Jan 2024 10:29:40 +1300
Subject: [PATCH] Docs: adding other macro command lists

Also updates `macro_commands.py` to skip empty lines, and moves comment
stripping earlier in parsing.
---
 .../code_examples/macro_commands/fsm.ys       | 27 ++++++
 .../code_examples/macro_commands/memory.ys    | 15 +++
 .../code_examples/macro_commands/proc.ys      | 14 +++
 docs/source/using_yosys/synthesis/fsm.rst     | 95 ++++---------------
 docs/source/using_yosys/synthesis/memory.rst  | 23 +++--
 docs/source/using_yosys/synthesis/proc.rst    | 21 ++--
 docs/source/using_yosys/synthesis/synth.rst   |  3 +-
 docs/tests/macro_commands.py                  | 15 ++-
 8 files changed, 111 insertions(+), 102 deletions(-)
 create mode 100644 docs/source/code_examples/macro_commands/fsm.ys
 create mode 100644 docs/source/code_examples/macro_commands/memory.ys
 create mode 100644 docs/source/code_examples/macro_commands/proc.ys

diff --git a/docs/source/code_examples/macro_commands/fsm.ys b/docs/source/code_examples/macro_commands/fsm.ys
new file mode 100644
index 000000000..627df1209
--- /dev/null
+++ b/docs/source/code_examples/macro_commands/fsm.ys
@@ -0,0 +1,27 @@
+#start:It also calls opt_clean as needed:
+#end:Options:
+# Identify and extract FSMs:
+fsm_detect
+fsm_extract
+
+# Basic optimizations:
+fsm_opt
+opt_clean
+fsm_opt
+
+# Expanding to nearby gate-logic (if called with -expand):
+fsm_expand
+opt_clean
+fsm_opt
+
+# Re-code FSM states (unless called with -norecode):
+fsm_recode
+
+# Print information about FSMs:
+fsm_info
+
+# Export FSMs in KISS2 file format (if called with -export):
+fsm_export
+
+# Map FSMs to RTL cells (unless called with -nomap):
+fsm_map
diff --git a/docs/source/code_examples/macro_commands/memory.ys b/docs/source/code_examples/macro_commands/memory.ys
new file mode 100644
index 000000000..ea4800a1c
--- /dev/null
+++ b/docs/source/code_examples/macro_commands/memory.ys
@@ -0,0 +1,15 @@
+#start:passes in a useful order:
+#end:This converts memories to word-wide DFFs and address decoders
+opt_mem
+opt_mem_priority
+opt_mem_feedback
+memory_bmux2rom
+memory_dff
+opt_clean
+memory_share
+opt_mem_widen
+memory_memx                         (when called with -memx)
+opt_clean
+memory_collect
+memory_bram -rules <bram_rules>     (when called with -bram)
+memory_map                          (skipped if called with -nomap)
diff --git a/docs/source/code_examples/macro_commands/proc.ys b/docs/source/code_examples/macro_commands/proc.ys
new file mode 100644
index 000000000..7a78ce0c6
--- /dev/null
+++ b/docs/source/code_examples/macro_commands/proc.ys
@@ -0,0 +1,14 @@
+#start: passes in the most common order.
+#end: This replaces the processes
+proc_clean # removes empty branches and processes
+proc_rmdead # removes unreachable branches
+proc_prune
+proc_init # special handling of “initial” blocks
+proc_arst # identifies modeling of async resets
+proc_rom
+proc_mux # converts decision trees to multiplexer networks
+proc_dlatch
+proc_dff # extracts registers from processes
+proc_memwr
+proc_clean # this should remove all the processes, provided all went fine
+opt_expr -keepdc
diff --git a/docs/source/using_yosys/synthesis/fsm.rst b/docs/source/using_yosys/synthesis/fsm.rst
index 11da17eba..e1ed55133 100644
--- a/docs/source/using_yosys/synthesis/fsm.rst
+++ b/docs/source/using_yosys/synthesis/fsm.rst
@@ -5,79 +5,22 @@ The :cmd:ref:`fsm` command identifies, extracts, optimizes (re-encodes), and
 re-synthesizes finite state machines. It again is a macro that calls a series of
 other commands:
 
-#. :cmd:ref:`fsm_detect` identifies FSM state registers and marks them
-   with the ``(* fsm_encoding = "auto" *)`` attribute, if they do not have the
-   ``fsm_encoding`` set already. Mark registers with ``(* fsm_encoding = "none"
-   *)`` to disable FSM optimization for a register.
-#. :cmd:ref:`fsm_extract` replaces the entire FSM (logic and state registers)
-   with a ``$fsm`` cell.
-#. :cmd:ref:`fsm_opt` optimizes the FSM. Called multiple times.
-#. :cmd:ref:`fsm_expand` optionally merges additional auxilliary gates into the
-   ``$fsm`` cell.
-#. :cmd:ref:`fsm_recode` also optimizes the FSM.
-#. :cmd:ref:`fsm_info` logs internal FSM information.
-#. :cmd:ref:`fsm_export` optionally exports each FSM to KISS2 files.
-#. :cmd:ref:`fsm_map` converts the (optimized) ``$fsm`` cell back to logic and
-   registers.
+.. literalinclude:: /code_examples/macro_commands/fsm.ys
+   :language: yoscrypt
+   :start-after: #end:
+   :caption: Passes called by :cmd:ref:`fsm`
 
 See also :doc:`/cmd/fsm`.
 
-The fsm pass performs finite-state-machine (FSM) extraction and recoding. The
-fsm pass simply executes the following other passes:
-
--  Identify and extract FSMs:
-
-   -  fsm_detect
-   -  fsm_extract
-
--  Basic optimizations:
-
-   -  fsm_opt
-   -  opt_clean
-   -  fsm_opt
-
--  Expanding to nearby gate-logic (if called with -expand):
-
-   -  fsm_expand
-   -  opt_clean
-   -  fsm_opt
-
--  Re-code FSM states (unless called with -norecode):
-
-   -  fsm_recode
-
--  Print information about FSMs:
-
-   -  fsm_info
-
--  Export FSMs in KISS2 file format (if called with -export):
-
-   -  fsm_export
-
--  Map FSMs to RTL cells (unless called with -nomap):
-
-   -  fsm_map
-
-The fsm_detect pass identifies FSM state registers and marks them using the
-``\fsm_encoding = "auto"`` attribute. The fsm_extract extracts all FSMs marked
-using the ``\fsm_encoding`` attribute (unless ``\fsm_encoding`` is set to
-"none") and replaces the corresponding RTL cells with a ``$fsm`` cell. All other
-``fsm_`` passes operate on these ``$fsm`` cells. The fsm_map call finally
-replaces the ``$fsm`` cells with RTL cells.
-
-Note that these optimizations operate on an RTL netlist. I.e. the :cmd:ref:`fsm`
-pass should be executed after the proc pass has transformed all
-``RTLIL::Process`` objects to RTL cells.
-
 The algorithms used for FSM detection and extraction are influenced by a more
 general reported technique :cite:p:`fsmextract`.
 
 FSM detection
 ~~~~~~~~~~~~~
 
-The fsm_detect pass identifies FSM state registers. It sets the ``\fsm_encoding
-= "auto"`` attribute on any (multi-bit) wire that matches the following
-description:
+The :cmd:ref:`fsm_detect` pass identifies FSM state registers. It sets the
+``\fsm_encoding = "auto"`` attribute on any (multi-bit) wire that matches the
+following description:
 
 -  Does not already have the ``\fsm_encoding`` attribute.
 -  Is not an output of the containing module.
@@ -101,7 +44,7 @@ results.
 FSM extraction
 ~~~~~~~~~~~~~~
 
-The fsm_extract pass operates on all state signals marked with the
+The :cmd:ref:`fsm_extract` pass operates on all state signals marked with the
 (``\fsm_encoding != "none"``) attribute. For each state signal the following
 information is determined:
 
@@ -142,8 +85,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
 of a stop-signal is needed in order to calculate the result signals.
 
-The fsm_extract pass uses the ConstEval class in the following way to create a
-transition table. For each state:
+The :cmd:ref:`fsm_extract` pass uses the ConstEval class in the following way to
+create a transition table. For each state:
 
 1. Create a ConstEval object for the module containing the FSM
 2. Add all control inputs to the list of stop signals
@@ -163,8 +106,9 @@ drivers for the control outputs are disconnected.
 FSM optimization
 ~~~~~~~~~~~~~~~~
 
-The fsm_opt pass performs basic optimizations on ``$fsm`` cells (not including
-state recoding). The following optimizations are performed (in this order):
+The :cmd:ref:`fsm_opt` pass performs basic optimizations on ``$fsm`` cells (not
+including state recoding). The following optimizations are performed (in this
+order):
 
 -  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
@@ -188,10 +132,11 @@ state recoding). The following optimizations are performed (in this order):
 FSM recoding
 ~~~~~~~~~~~~
 
-The fsm_recode pass assigns new bit pattern to the states. Usually this also
-implies a change in the width of the state signal. At the moment of this writing
-only one-hot encoding with all-zero for the reset state is supported.
+The :cmd:ref:`fsm_recode` pass assigns new bit pattern to the states. Usually
+this also implies a change in the width of the state signal. At the moment of
+this writing only one-hot encoding with all-zero for the reset state is
+supported.
 
-The fsm_recode pass can also write a text file with the changes performed by it
-that can be used when verifying designs synthesized by Yosys using Synopsys
-Formality.
+The :cmd:ref:`fsm_recode` pass can also write a text file with the changes
+performed by it that can be used when verifying designs synthesized by Yosys
+using Synopsys Formality.
diff --git a/docs/source/using_yosys/synthesis/memory.rst b/docs/source/using_yosys/synthesis/memory.rst
index 71da211d5..f2bfe9650 100644
--- a/docs/source/using_yosys/synthesis/memory.rst
+++ b/docs/source/using_yosys/synthesis/memory.rst
@@ -7,19 +7,22 @@ The :cmd:ref:`memory` command
 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`
 pass transforms memories to an implementation. Per default that is logic for
-address decoders and registers. It also is a macro command that the other common
-``memory_*`` commands in a sensible order:
+address decoders and registers. It also is a macro command that calls the other
+common ``memory_*`` passes in a sensible order:
 
-.. todo:: fill out missing :cmd:ref:`memory` subcommands descriptions
+.. literalinclude:: /code_examples/macro_commands/memory.ys
+   :language: yoscrypt
+   :start-after: #end:
+   :caption: Passes called by :cmd:ref:`memory`
 
-#. :cmd:ref:`memory_bmux2rom`
-#. :cmd:ref:`memory_dff` merges registers into the memory read- and write cells.
-#. :cmd:ref:`memory_share`
-#. :cmd:ref:`memory_memx`
-#. :cmd:ref:`memory_collect` collects all read and write cells for a memory and
+.. todo:: Make ``memory_*`` notes less quick
+
+Some quick notes:
+
+-  :cmd:ref:`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
    transforms them into one multi-port memory cell.
-#. :cmd:ref:`memory_bram`
-#. :cmd:ref:`memory_map` takes the multi-port memory cell and transforms it to
+-  :cmd:ref:`memory_map` takes the multi-port memory cell and transforms it to
    address decoder logic and registers.
 
 For more information about :cmd:ref:`memory`, such as disabling certain sub
diff --git a/docs/source/using_yosys/synthesis/proc.rst b/docs/source/using_yosys/synthesis/proc.rst
index 498e1264a..265930c8c 100644
--- a/docs/source/using_yosys/synthesis/proc.rst
+++ b/docs/source/using_yosys/synthesis/proc.rst
@@ -1,26 +1,21 @@
 Converting process blocks
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
+.. role:: yoscrypt(code)
+   :language: yoscrypt
+
 The Verilog frontend converts ``always``-blocks to RTL netlists for the
 expressions and "processess" for the control- and memory elements. The
 :cmd:ref:`proc` command then transforms these "processess" to netlists of RTL
 multiplexer and register cells. It also is a macro command that calls the other
 ``proc_*`` commands in a sensible order:
 
-#. :cmd:ref:`proc_clean` removes empty branches and processes.
-#. :cmd:ref:`proc_rmdead` removes unreachable branches.
-#. :cmd:ref:`proc_prune`
-#. :cmd:ref:`proc_init` special handling of "initial" blocks.
-#. :cmd:ref:`proc_arst` identifies modeling of async resets.
-#. :cmd:ref:`proc_rom`
-#. :cmd:ref:`proc_mux` converts decision trees to multiplexer networks.
-#. :cmd:ref:`proc_dlatch`
-#. :cmd:ref:`proc_dff` extracts registers from processes.
-#. :cmd:ref:`proc_memwr`
-#. :cmd:ref:`proc_clean` this should remove all the processes, provided all went
-   fine.
+.. literalinclude:: /code_examples/macro_commands/proc.ys
+   :language: yoscrypt
+   :start-after: #end:
+   :caption: Passes called by :cmd:ref:`proc`
 
-After all the ``proc_*`` commands, :yoscrypt:`opt_expr` is called. This can be
+After all the ``proc_*`` commands, :cmd:ref:`opt_expr` is called. This can be
 disabled by calling :yoscrypt:`proc -noopt`.  For more information about
 :cmd:ref:`proc`, such as disabling certain sub commands, see :doc:`/cmd/proc`.
 
diff --git a/docs/source/using_yosys/synthesis/synth.rst b/docs/source/using_yosys/synthesis/synth.rst
index c9ec45b8a..15d701fb4 100644
--- a/docs/source/using_yosys/synthesis/synth.rst
+++ b/docs/source/using_yosys/synthesis/synth.rst
@@ -43,4 +43,5 @@ The following commands are executed by the :cmd:ref:`prep` command:
    :end-before: .. raw:: latex
    :dedent:
 
-The following sections will get more into what each of these commands do.
+:doc:`/getting_started/example_synth` covers most of these commands and what
+they do.
diff --git a/docs/tests/macro_commands.py b/docs/tests/macro_commands.py
index 7942e4d31..faf2baa53 100755
--- a/docs/tests/macro_commands.py
+++ b/docs/tests/macro_commands.py
@@ -35,7 +35,12 @@ for macro in MACRO_SOURCE.glob("*.ys"):
         # immediately after.
         start = f.readline()
         end = f.readline()
-        expected_content = f.readlines()
+        file_content = f.readlines()
+    expected_content = []
+    for line in file_content:
+        line = line.split("#")[0].strip()
+        if line:
+            expected_content.append(line)
     # parse {command.ys}
     if "#start:" not in start or "#end:" not in end:
         logging.error(f"Missing start and/or end string in {relative_path}, see {THIS_FILE}")
@@ -49,7 +54,11 @@ for macro in MACRO_SOURCE.glob("*.ys"):
         logging.error(f"Couldn't find {start!r} and/or {end!r} in `yosys -h {command}` output")
         raise_error = True
         continue
-    actual_content = match.group(1).strip().splitlines()
+    match_content = match.group(1).strip().splitlines()
+    actual_content = []
+    for line in match_content:
+        if line:
+            actual_content.append(line)
     # iterate over and compare expected v actual
     for (expected, actual) in zip(expected_content, actual_content):
         expected = expected.strip()
@@ -59,7 +68,7 @@ for macro in MACRO_SOURCE.glob("*.ys"):
             continue
 
         # rip apart formatting to match line parts
-        pattern = r"(?P<cmd>\S+)(?P<pass> \[.*\])?(?P<opt>.*?)(?P<cond>  \(.*\))?(?P<comment>\s+#.*)?"
+        pattern = r"(?P<cmd>\S+)(?P<pass> \[.*\])?(?P<opt>.*?)(?P<cond>\s+\(.*\))?"
         try:
             expected_dict = re.fullmatch(pattern, expected).groupdict()
         except AttributeError: