mirror of https://github.com/YosysHQ/yosys.git
docs/functional: Minimal backend paragraphs
I was thinking about compiling the dummy example and including a simple example usage, but it turns out functional.h isn't (currently) available for extensions.
This commit is contained in:
parent
3c493d2bef
commit
b56e3ec6e4
|
@ -149,44 +149,49 @@ S-expressions can be constructed with ``SExpr::list``, for example ``SExpr expr
|
||||||
Example: A minimal functional backend
|
Example: A minimal functional backend
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
At its most basic, there are three steps we need to accomplish for a minimal
|
||||||
|
functional backend. First, we need to convert our design into FunctionalIR.
|
||||||
|
This is most easily done by calling the ``Functional::IR::from_module()`` static
|
||||||
|
method with our top-level module, or iterating over and converting each of the
|
||||||
|
modules in our design. Second, we need to handle each of the
|
||||||
|
``Functional::Node``\ s in our design. Iterating over the ``Functional::IR``
|
||||||
|
includes reading the module inputs and current state, but not writing the
|
||||||
|
results. So our final step is to handle the outputs and next state.
|
||||||
|
|
||||||
|
In order to add an output command to Yosys, we implement the ``Yosys::Backend``
|
||||||
|
class and provide an instance of it:
|
||||||
|
|
||||||
.. literalinclude:: /code_examples/functional/dummy.cc
|
.. literalinclude:: /code_examples/functional/dummy.cc
|
||||||
:language: c++
|
:language: c++
|
||||||
:caption: Example source code for a minimal functional backend
|
:caption: Example source code for a minimal functional backend, ``dummy.cc``
|
||||||
|
|
||||||
- three main steps needed
|
Because we are using the ``Backend`` class, our ``"functional_dummy"`` is
|
||||||
|
registered as the ``write_functional_dummy`` command. The ``execute`` method is
|
||||||
|
the part that runs when the user calls the command, handling any options,
|
||||||
|
preparing the output file for writing, and iterating over selected modules in
|
||||||
|
the design. Since we don't have any options here, we set ``argidx = 1`` and
|
||||||
|
call the ``extra_args()`` method. This method will read the command arguments,
|
||||||
|
raising an error if there are any unexpected ones. It will also assign the
|
||||||
|
pointer ``f`` to the output file, or stdout if none is given.
|
||||||
|
|
||||||
+ convert to FunctionalIR
|
.. note::
|
||||||
+ handle nodes
|
|
||||||
+ handle outputs and next state
|
|
||||||
|
|
||||||
- backend pass boiler plate gives us ``write_functional_dummy`` command
|
For more on adding new commands to Yosys and how they work, refer to
|
||||||
|
:doc:`/yosys_internals/extending_yosys/extensions`.
|
||||||
|
|
||||||
The final part is the ``Backend`` itself, which registers the command in Yosys.
|
For this minimal example all we are doing is printing out each node. The
|
||||||
The ``execute`` method is the part that runs when the user calls the command,
|
``node.name()`` method returns an ``RTLIL::IdString``, which we convert for
|
||||||
handling any options, preparing the output file for writing, and iterating over
|
printing with ``id2cstr()``. Then, to print the function of the node, we use
|
||||||
selected modules in the design. For more on adding new commands to Yosys and
|
``node.to_string()`` which gives us a string of the form ``function(args)``. The
|
||||||
how they work, refer to :doc:`/yosys_internals/extending_yosys/extensions`.
|
``function`` part is the result of ``Functional::IR::fn_to_string(node.fn())``;
|
||||||
|
while ``args`` is the zero or more arguments passed to the function, most
|
||||||
|
commonly the name of another node. Behind the scenes, the ``node.to_string()``
|
||||||
|
method actually wraps ``node.visit(visitor)`` with a private visitor whose
|
||||||
|
return type is ``std::string``.
|
||||||
|
|
||||||
- pointer ``f`` is a ``std::ostream`` we can write to, being either a file or
|
Finally we iterate over the module's outputs and states, using
|
||||||
stdout
|
``Functional::IROutput::value()`` and ``Functional::IRState::next_value()``
|
||||||
- FunctionalIR conversion done by ``Functional::IR::from_module()``
|
respectively in order to get the results of the transfer function.
|
||||||
- each node performs some function or operation (including reading input/current
|
|
||||||
state)
|
|
||||||
|
|
||||||
+ each variable is assigned exactly once before being used
|
|
||||||
+ ``node.name()`` returns a ``RTLIL::IdString``, which we convert for
|
|
||||||
printing with ``id2cstr()``
|
|
||||||
+ ``node.to_string()`` converts the node into a string of the form
|
|
||||||
``function(args)``
|
|
||||||
|
|
||||||
* ``function`` is the result of ``Functional::IR::fn_to_string(node.fn())``
|
|
||||||
* ``args`` are the zero or more arguments passed to the function, most
|
|
||||||
commonly the name of another node
|
|
||||||
* wraps ``node.visit()`` with a private visitor with return type
|
|
||||||
``std::string``
|
|
||||||
|
|
||||||
- ``Functional::IROutput::value()`` and ``Functional::IRState::next_value()``
|
|
||||||
represent the outputs of our function
|
|
||||||
|
|
||||||
Example: Adapting SMT-LIB backend for Rosette
|
Example: Adapting SMT-LIB backend for Rosette
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue