diff --git a/docs/source/code_examples/example_synth/Makefile b/docs/source/code_examples/example_synth/Makefile new file mode 100644 index 000000000..4446c2099 --- /dev/null +++ b/docs/source/code_examples/example_synth/Makefile @@ -0,0 +1,15 @@ +PROGRAM_PREFIX := + +YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys + +DOTS = control_hier.dot control_proc.dot +DOTS += example_hier.dot + +dots: $(DOTS) example.out + +$(DOTS) example.out: example.v example.ys + $(YOSYS) example.ys -l example.out -Q + +.PHONY: clean +clean: + rm -f *.dot diff --git a/docs/source/code_examples/example_synth/example.out b/docs/source/code_examples/example_synth/example.out new file mode 100644 index 000000000..f2c4bfafa --- /dev/null +++ b/docs/source/code_examples/example_synth/example.out @@ -0,0 +1,147 @@ + +-- Executing script file `example.ys' -- +echo on + +yosys> read_verilog -defer example.v + +1. Executing Verilog-2005 frontend: example.v +Parsing Verilog input from `example.v' to AST representation. +Storing AST representation for module `$abstract\example'. +Storing AST representation for module `$abstract\control'. +Storing AST representation for module `$abstract\data'. +Successfully finished Verilog frontend. + +yosys> hierarchy -top control + +2. Executing HIERARCHY pass (managing design hierarchy). + +3. Executing AST frontend in derive mode using pre-parsed AST for module `\control'. +Generating RTLIL representation for module `\control'. + +3.1. Analyzing design hierarchy.. +Top module: \control + +3.2. Analyzing design hierarchy.. +Top module: \control +Removing unused module `$abstract\data'. +Removing unused module `$abstract\control'. +Removing unused module `$abstract\example'. +Removed 3 unused modules. + +yosys> show -notitle -format dot -prefix control_hier + +4. Generating Graphviz representation of design. +Writing dot description to `control_hier.dot'. +Dumping module control to page 1. + +yosys> proc + +5. Executing PROC pass (convert processes to netlists). + +yosys> proc_clean + +5.1. Executing PROC_CLEAN pass (remove empty switches from decision trees). +Cleaned up 0 empty switches. + +yosys> proc_rmdead + +5.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees). +Marked 1 switch rules as full_case in process $proc$example.v:43$1 in module control. +Removed a total of 0 dead cases. + +yosys> proc_prune + +5.3. Executing PROC_PRUNE pass (remove redundant assignments in processes). +Removed 1 redundant assignment. +Promoted 0 assignments to connections. + +yosys> proc_init + +5.4. Executing PROC_INIT pass (extract init attributes). + +yosys> proc_arst + +5.5. Executing PROC_ARST pass (detect async resets in processes). + +yosys> proc_rom + +5.6. Executing PROC_ROM pass (convert switches to ROMs). +Converted 0 switches. + + +yosys> proc_mux + +5.7. Executing PROC_MUX pass (convert decision trees to multiplexers). +Creating decoders for process `\control.$proc$example.v:43$1'. + 1/2: $0\addr[7:0] + 2/2: $0\state[1:0] + +yosys> proc_dlatch + +5.8. Executing PROC_DLATCH pass (convert process syncs to latches). + +yosys> proc_dff + +5.9. Executing PROC_DFF pass (convert process syncs to FFs). +Creating register for signal `\control.\state' using process `\control.$proc$example.v:43$1'. + created $dff cell `$procdff$12' with positive edge clock. +Creating register for signal `\control.\addr' using process `\control.$proc$example.v:43$1'. + created $dff cell `$procdff$13' with positive edge clock. + +yosys> proc_memwr + +5.10. Executing PROC_MEMWR pass (convert process memory writes to cells). + +yosys> proc_clean + +5.11. Executing PROC_CLEAN pass (remove empty switches from decision trees). +Found and cleaned up 2 empty switches in `\control.$proc$example.v:43$1'. +Removing empty process `control.$proc$example.v:43$1'. +Cleaned up 2 empty switches. + +yosys> opt_expr -keepdc + +5.12. Executing OPT_EXPR pass (perform const folding). +Optimizing module control. + +yosys> show -notitle -format dot -prefix control_proc + +6. Generating Graphviz representation of design. +Writing dot description to `control_proc.dot'. +Dumping module control to page 1. + +yosys> design -reset + +yosys> read_verilog example.v + +7. Executing Verilog-2005 frontend: example.v +Parsing Verilog input from `example.v' to AST representation. +Generating RTLIL representation for module `\example'. +Generating RTLIL representation for module `\control'. +Generating RTLIL representation for module `\data'. +Successfully finished Verilog frontend. + +yosys> hierarchy -check -top example + +8. Executing HIERARCHY pass (managing design hierarchy). + +8.1. Analyzing design hierarchy.. +Top module: \example +Used module: \data +Used module: \control + +8.2. Analyzing design hierarchy.. +Top module: \example +Used module: \data +Used module: \control +Removed 0 unused modules. + +yosys> show -notitle -format dot -prefix example_hier example + +9. Generating Graphviz representation of design. +Writing dot description to `example_hier.dot'. +Dumping module example to page 1. + +End of script. Logfile hash: b45465606c, CPU: user 0.01s system 0.00s, MEM: 11.86 MB peak +Yosys 0.35+39 (git sha1 0cd4a10c8, clang 10.0.0-4ubuntu1 -fPIC -Os) +Time spent: 37% 4x read_verilog (0 sec), 23% 3x show (0 sec), ... diff --git a/docs/source/code_examples/example_synth/example.v b/docs/source/code_examples/example_synth/example.v new file mode 100644 index 000000000..f0fc5cdb5 --- /dev/null +++ b/docs/source/code_examples/example_synth/example.v @@ -0,0 +1,76 @@ +module example ( + input clk, + input rst, + input inc, + input [7:0] a, + input [7:0] b, + output [15:0] c +); + +wire [1:0] state; +wire [7:0] addr; + +control ctrl ( + .clk(clk), + .rst(rst), + .inc(inc), + .addr_o(addr), + .state_o(state) +); + +data dat ( + .clk(clk), + .addr_i(addr), + .state_i(state), + .a(a), + .b(b), + .c(c) +); + +endmodule + +module control ( + input clk, + input rst, + input inc, + output [7:0] addr_o, + output [1:0] state_o +); + +reg [1:0] state; +reg [7:0] addr; + +always @(posedge clk) begin + if (rst) begin + state <= 2'b00; + addr <= 0; + end else begin + if (inc) state <= state + 1'b1; + addr <= addr + 1'b1; + end +end + +endmodule //control + +module data ( + input clk, + input [7:0] addr_i, + input [1:0] state_i, + input [7:0] a, + input [7:0] b, + output reg [15:0] c +); + +reg [15:0] mem[255:0]; + +always @(posedge clk) begin + case (state_i) + 2'b00: mem[addr_i] <= a*b; + 2'b01: mem[addr_i] <= a+b; + 2'b10: mem[addr_i] <= a-b; + 2'b11: mem[addr_i] <= addr_i; + endcase + c <= mem[addr_i]; +end + +endmodule //data diff --git a/docs/source/code_examples/example_synth/example.ys b/docs/source/code_examples/example_synth/example.ys new file mode 100644 index 000000000..b8745dac5 --- /dev/null +++ b/docs/source/code_examples/example_synth/example.ys @@ -0,0 +1,17 @@ +# turn command echoes on to use the log output as a console session +echo on + +# ======================================================== +read_verilog -defer example.v +hierarchy -top control +show -notitle -format dot -prefix control_hier + +# ======================================================== +proc +show -notitle -format dot -prefix control_proc + +# ======================================================== +design -reset +read_verilog example.v +hierarchy -check -top example +show -notitle -format dot -prefix example_hier example diff --git a/docs/source/getting_started/example_synth.rst b/docs/source/getting_started/example_synth.rst index 6bc5be967..bedaa035c 100644 --- a/docs/source/getting_started/example_synth.rst +++ b/docs/source/getting_started/example_synth.rst @@ -13,33 +13,30 @@ used. .. seealso:: Advanced usage docs for :doc:`/using_yosys/synthesis/synth` -A simple counter -~~~~~~~~~~~~~~~~ +Demo design +~~~~~~~~~~~ .. role:: yoscrypt(code) :language: yoscrypt -.. TODO:: replace counter.v with a (slightly) more complex design - which includes hard blocks and maybe an FSM - First, let's quickly look at the design we'll be synthesizing: -.. literalinclude:: /code_examples/intro/counter.v - :language: Verilog - :caption: ``docs/source/code_examples/intro/counter.v`` - :linenos: +.. todo:: reconsider including the whole (~77 line) design like this -This is a simple counter with reset and enable. If the reset signal, ``rst``, -is high then the counter will reset to 0. Otherwise, if the enable signal, -``en``, is high then the ``count`` register will increment by 1 each rising edge -of the clock, ``clk``. +.. literalinclude:: /code_examples/example_synth/example.v + :language: Verilog + :linenos: + :caption: ``example.v`` + :name: example-v + +.. todo:: example.v description Loading the design ~~~~~~~~~~~~~~~~~~ Let's load the design into Yosys. From the command line, we can call ``yosys -counter.v``. This will open an interactive Yosys shell session and immediately -parse the code from ``counter.v`` and convert it into an Abstract Syntax Tree +example.v``. This will open an interactive Yosys shell session and immediately +parse the code from ``example.v`` and convert it into an Abstract Syntax Tree (AST). If you are interested in how this happens, there is more information in the document, :doc:`/yosys_internals/flow/verilog_frontend`. For now, suffice it to say that we do this to simplify further processing of the design. You @@ -47,13 +44,15 @@ should see something like the following: .. code:: console - $ yosys counter.v + $ yosys example.v - -- Parsing `counter.v' using frontend ` -vlog2k' -- + -- Parsing `example.v' using frontend ` -vlog2k' -- - 1. Executing Verilog-2005 frontend: counter.v - Parsing Verilog input from `counter.v' to AST representation. - Storing AST representation for module `$abstract\counter'. + 1. Executing Verilog-2005 frontend: example.v + Parsing Verilog input from `example.v' to AST representation. + Storing AST representation for module `$abstract\example'. + Storing AST representation for module `$abstract\control'. + Storing AST representation for module `$abstract\data'. Successfully finished Verilog frontend. .. seealso:: Advanced usage docs for @@ -63,9 +62,12 @@ Elaboration ~~~~~~~~~~~ Now that we are in the interactive shell, we can call Yosys commands directly. -Our overall goal is to call :yoscrypt:`synth_ice40 -top counter`, but for now we +Our overall goal is to call :yoscrypt:`synth_ice40 -top example`, but for now we can run each of the commands individually for a better sense of how each part -contributes to the flow. At the bottom of the :cmd:ref:`help` output for +contributes to the flow. We will also start with just a single module; +``control``. + +At the bottom of the :cmd:ref:`help` output for :cmd:ref:`synth_ice40` is the complete list of commands called by this script. Let's start with the section labeled ``begin``: @@ -75,6 +77,7 @@ Let's start with the section labeled ``begin``: :end-before: flatten: :dedent: :caption: ``begin`` section + :name: synth_begin :yoscrypt:`read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v` loads the iCE40 cell models which allows us to include platform specific IP blocks in our @@ -83,15 +86,20 @@ design. PLLs are a common example of this, where we might need to reference later. Since our simple design doesn't use any of these IP blocks, we can safely skip this command. -Let's instead start with run :yoscrypt:`hierarchy -check -top counter`. This -command declares that the top level module is ``counter``, and that we want to -expand it and any other modules it may use. Any other modules which were loaded -are then discarded, preventing the subsequent commands from trying to work on -them. By passing the ``-check`` option there we are also telling the -:cmd:ref:`hierarchy` command that if the design includes any non-blackbox -modules without an implementation it should return an error. +The control module +^^^^^^^^^^^^^^^^^^ -.. TODO:: more on why :cmd:ref:`hierarchy` is important +Since we're just getting started, let's instead begin with :yoscrypt:`hierarchy +-top control`. This command declares that the top level module is ``control``, +and everything else can be discarded. + +.. literalinclude:: /code_examples/example_synth/example.v + :language: Verilog + :start-at: module control + :end-at: endmodule //control + :lineno-match: + :caption: ``control`` module source + :name: control-v .. note:: @@ -100,51 +108,95 @@ modules without an implementation it should return an error. .. use doscon for a console-like display that supports the `yosys> [command]` format. -.. code:: doscon +.. literalinclude:: /code_examples/example_synth/example.out + :language: doscon + :start-at: yosys> hierarchy -top control + :end-before: yosys> show + :caption: :yoscrypt:`hierarchy -top control` output - yosys> hierarchy -check -top counter +Our ``control`` circuit now looks like this: - 2. Executing HIERARCHY pass (managing design hierarchy). - - 3. Executing AST frontend in derive mode using pre-parsed AST for module `\counter'. - Generating RTLIL representation for module `\counter'. - - 3.1. Analyzing design hierarchy.. - Top module: \counter - - 3.2. Analyzing design hierarchy.. - Top module: \counter - Removing unused module `$abstract\counter'. - Removed 1 unused modules. - -Our circuit now looks like this: - -.. figure:: /_images/code_examples/intro/counter_00.* +.. figure:: /_images/code_examples/example_synth/control_hier.* :class: width-helper + :name: control_hier - ``counter`` module after :cmd:ref:`hierarchy` + ``control`` module after :cmd:ref:`hierarchy` -Notice that block that says "PROC" in :ref:`counter-hierarchy`? Simple -operations like ``count + 2'd1`` can be extracted from our ``always @`` block in -:ref:`counter-v`. This gives us the ``$add`` cell we see. But control logic -(like the ``if .. else``) and memory elements (like the ``count <='2d0``) are +Notice that block that says "PROC" in :ref:`control_hier`? Simple operations +like ``addr + 1'b1`` can be extracted from our ``always @`` block in +:ref:`control-v`. This gives us the two ``$add`` cells we see. But control +logic (like the ``if .. else``) and memory elements (like the ``addr <= 0``) are not so straightforward. To handle these, let us now introduce the next command: :doc:`/cmd/proc`. :cmd:ref:`proc` is a macro command like :cmd:ref:`synth_ice40`. Rather than -processing our design itself, it instead calls a series of other commands. In +modifying the design directly, it instead calls a series of other commands. In the case of :cmd:ref:`proc`, these sub-commands work to convert the behavioral -logic of processes into multiplexers and registers. We go into more detail on -:cmd:ref:`proc` later in :doc:`/using_yosys/synthesis/proc`, but for now let's -see what happens when we run it. +logic of processes into multiplexers and registers. Let's see what happens when +we run it. -.. figure:: /_images/code_examples/intro/counter_proc.* +.. figure:: /_images/code_examples/example_synth/control_proc.* :class: width-helper - ``counter`` module after :cmd:ref:`proc` + ``control`` module after :cmd:ref:`proc` -The ``if`` statements are now modeled with ``$mux`` cells, and the memory -consists of a ``$dff`` cell. +The ``if`` statements are now modeled with ``$mux`` cells, while the registers +use ``$dff`` cells. If we look at the terminal output we can also see all of +the different ``proc_*`` commands being called. We will look at each of these +in more detail in :doc:`/using_yosys/synthesis/proc`. + +The full example +^^^^^^^^^^^^^^^^ + +Let's now go back and check on our full design by using :yoscrypt:`hierarchy +-check -top example`. By passing the ``-check`` option there we are also +telling the :cmd:ref:`hierarchy` command that if the design includes any +non-blackbox modules 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 +is because we already removed all of the modules other than ``control``. We +could restart our shell session, but instead let's use two new commands: + +- :doc:`/cmd/design`, and +- :doc:`/cmd/read_verilog`. + +.. literalinclude:: /code_examples/example_synth/example.out + :language: doscon + :start-at: design -reset + :end-before: yosys> show + :caption: reloading ``example.v`` and running :yoscrypt:`hierarchy -check -top example` + +Notice how this time we didn't see any of those `$abstract` modules? That's +because when we ran ``yosys example.v``, the first command Yosys called was +:yoscrypt:`read_verilog -defer example.v`. The ``-defer`` option there tells +:cmd:ref:`read_verilog` only read the abstract syntax tree and defer actual +compilation to a later :cmd:ref:`hierarchy` command. This is useful in cases +where the default parameters of modules yield invalid or not synthesizable code, +which is why Yosys does this automatically and is one of the reasons why +hierarchy should always be the first command after loading the design. If we +know that our design won't run into this issue, we can skip the ``-defer``. + +.. note:: + + The number before a command's output increments with each command run. Don't + worry if your numbers don't match ours! The output you are seeing comes from + the same script that was used to generate the images in this document, + included in the source as ``example.ys``. There are extra commands being run + which you don't see, but feel free to try them yourself, or play around with + different commands. You can always start over with a clean slate by calling + ``exit`` or hitting ``ctrl+c`` (i.e. SIGINT) and re-launching the Yosys + interactive terminal. + +.. figure:: /_images/code_examples/example_synth/example_hier.* + :class: width-helper + :name: example_hier + + ``example`` module after :cmd:ref:`hierarchy` + +We can also run :cmd:ref:`proc` now, although we won't actually see any change +in this top view. + +.. TODO:: more on why :cmd:ref:`hierarchy` is important .. seealso:: Advanced usage docs for :doc:`/using_yosys/synthesis/proc` @@ -153,26 +205,27 @@ Flattening ~~~~~~~~~~ At this stage of a synthesis flow there are a few other commands we could run. -First off is :cmd:ref:`flatten`. If we had any modules within our ``counter``, -this would replace them with their implementation. Flattening the design like -this can allow for optimizations between modules which would otherwise be -missed. - -Depending on the target architecture, we might also run commands such as -:cmd:ref:`tribuf` with the ``-logic`` option and :cmd:ref:`deminout`. These -remove tristate and inout constructs respectively, replacing them with logic -suitable for mapping to an FPGA. +In :cmd:ref:`synth_ice40` we get these: .. literalinclude:: /cmd/synth_ice40.rst :language: yoscrypt :start-after: flatten: :end-before: coarse: :dedent: - :name: flatten + :name: synth_flatten :caption: ``flatten`` section -The iCE40 flow puts these commands into thier own :ref:`flatten`, -while some synthesis scripts will instead include them in the next section. +First off is :cmd:ref:`synth_flatten`. Flattening the design like this can +allow for optimizations between modules which would otherwise be missed. We +will skip this command for now because it makes the design schematic quite +large. If you would like to see for yourself, you can do so with +:doc:`/cmd/show`. Note that the :cmd:ref:`show` command only works with a +single module, so you may need to call it with :yoscrypt:`show example`. + +Depending on the target architecture, we might also see commands such as +:cmd:ref:`tribuf` with the ``-logic`` option and :cmd:ref:`deminout`. These +remove tristate and inout constructs respectively, replacing them with logic +suitable for mapping to an FPGA. The coarse-grain representation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -195,6 +248,13 @@ In the iCE40 flow we get all the following commands: :end-before: map_ram: :dedent: :caption: ``coarse`` section + :name: synth_coarse + +.. note:: + + While the iCE40 flow had a :ref:`synth_flatten` and put :cmd:ref:`proc` in + the :ref:`synth_begin`, some synthesis scripts will instead include these in + the :ref:`synth_coarse` section. .. TODO:: talk more about DSPs (and their associated commands)