Skip to content

Commit

Permalink
Fix flow API docs
Browse files Browse the repository at this point in the history
  • Loading branch information
olofk committed Nov 21, 2023
1 parent 18dadce commit f83a8b3
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 6 deletions.
91 changes: 90 additions & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.graphviz",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"sphinx_autodoc_typehints",
Expand Down Expand Up @@ -211,5 +212,93 @@
from edalize.edatool import gen_tool_docs

s = gen_tool_docs()
with open(os.path.join(os.path.abspath("."), "edam/tools.rst"), "w") as f:
with open(os.path.join(os.path.abspath("."), "edam/legacytools.rst"), "w") as f:
f.write(s)

from importlib import import_module
from pkgutil import iter_modules

import edalize.flows


def make_rst_table(options):
s = ""
lines = []
name_len = 10
type_len = 4
for name, item in options.items():
_type = item["type"]
if item.get("list"):
_type = "List of " + _type
name_len = max(name_len, len(name))
type_len = max(type_len, len(_type))
lines.append((name, _type, item["desc"]))

s += "=" * name_len + " " + "=" * type_len + " " + "=" * 11 + "\n"
s += "Field Name".ljust(name_len + 1) + "Type".ljust(type_len + 1) + "Description\n"
s += "=" * name_len + " " + "=" * type_len + " " + "=" * 11 + "\n"
for line in lines:
s += line[0].ljust(name_len + 1)
s += line[1].ljust(type_len + 1)
s += line[2]
s += "\n"
s += "=" * name_len + " " + "=" * type_len + " " + "=" * 11 + "\n"
return s


def iter_namespace(ns_pkg):
# Specifying the second argument (prefix) to iter_modules makes the
# returned name an absolute name instead of a relative one. This allows
# import_module to work without having to do additional modification to
# the name.
return iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".")


discovered_plugins = {
name: import_module(name) for finder, name, ispkg in iter_namespace(edalize.flows)
}

s = ""
table = {}
for k, v in discovered_plugins.items():
name = k.split(".")[-1]
if name == "edaflow":
continue

table[name] = {
"type": f"`{name.capitalize()} flow`_",
"desc": name + "-specific options",
}
_class = getattr(v, name.capitalize())
s += "\n{} flow\n{}\n\n".format(name.capitalize(), "~" * (len(name) + 5))
s += _class.__doc__ + "\n\n"
s += f".. graphviz:: {name}.gv\n\n"
s += make_rst_table(_class.get_flow_options())

with open(os.path.join(os.path.abspath("."), "edam/flows.rst"), "w") as f:
f.write(s) # make_rst_table(table)+s)

import edalize.tools

discovered_plugins = {
name: import_module(name) for finder, name, ispkg in iter_namespace(edalize.tools)
}

s = ""
table = {}
for k, v in discovered_plugins.items():
name = k.split(".")[-1]
if name == "edatool":
continue

table[name] = {
"type": f"`{name.capitalize()} tool`_",
"desc": name + "-specific options",
}
_class = getattr(v, name.capitalize())
s += "\n{} tool\n{}\n\n".format(name.capitalize(), "~" * (len(name) + 5))
s += (_class.__doc__ or _class.description) + "\n\n"
s += make_rst_table(_class.get_tool_options())

with open(os.path.join(os.path.abspath("."), "edam/tools.rst"), "w") as f:
f.write(s) # make_rst_table(table)+s)
17 changes: 16 additions & 1 deletion doc/edam/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Field Name Type Description
dependencies Dict of `Dependency`_ Direct dependencies of each core that is contained in the EDAM.
files List of `File`_ Contains all the HDL source files, constraint files,
vendor IP description files, memory initialization files etc. for the project.
flow_options `Flow Options`_ A dictionary of tool- and flow-specific options. Used by the Flow API
hooks `Hook`_ A dictionary of extra commands to execute at various stages of the project build/run.
name String **Required** Name of the project
parameters Dict of `Parameter`_ Specifies build- and run-time parameters, such as plusargs, VHDL generics, Verilog defines etc.
Expand Down Expand Up @@ -48,6 +49,7 @@ File
A file has a name, which is the absolute path or the relative path to the working directory. It also has a type, which describes the intended usage of the file.
Different EDA tools handle different subsets of files and are expected to ignore files that are not applicable to them, but might issue a warning. By specifying *user* as the file type, the backends will explicitly ignore the file. The valid file types are based on the IP-XACT 2014 standard, with some additional file types added. The file types not covered by IP-XACT are listed below


- QIP : Intel Quartus IP file
- UCF : Xilinx ISE constraint file
- verilogSource-2005 : Verilog 200 source
Expand All @@ -66,6 +68,19 @@ include_path String When is_include_file is true, the director
logical_name String Logical name (e.g. VHDL/SystemVerilog library) of the file
=============== ===================== ===========

Flow options
------------

The flow API consists of two layers. The *flow* defines how different *tools* are interconnected to perform a task. The topology of the flows can be very different. A simulation flow might consist of a single simulation tool. An FPGA flow might be built up from a synthesis tool followed by a place & route tool and finally some tool to convert into a device-specific FPGA image (bitstream). A gate-level simulation flow could be created with a synthesis tool feeding its output into a simulator.

This also means that configuring the flow consists of two types of options. The flow options listed for each flow below defines the topology. Depending on which tools that get pulled into the flow graph, additional tool-specific flow options becomes available as well. In addition, some tool-specific options might be hardcoded by the flow. If e.g. yosys is used in the Vivado flow, the architecture will always be set to *xilinx* and the output format will always be *edf* since that's what Vivado expects for its post-synthesis activities. Below is listed the flow options for each flow as well as the tool options for each tool. In order to programatically see what options are available for a specific flow configuration, first run ``get_flow_options()`` to get the available flow options. Assign values to any flow options of interest and then run ``get_tool_options(assigned_flow_options)`` with a dict containing the flow options and their values to see what tool options are available for this particular flow configuration.

The global flow options and options for each tool both goes into the ``flow_options`` section in the EDAM description.

.. include:: flows.rst

.. include:: tools.rst

Hook
----

Expand Down Expand Up @@ -118,7 +133,7 @@ paramtype String **Required** Type of parameter. Valid valu
Tool options
------------

.. include:: tools.rst
.. include:: legacytools.rst

VPI
---
Expand Down
5 changes: 5 additions & 0 deletions doc/edam/efinity.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
digraph G {
"$project.bit" [shape=box,style=filled]
frontends -> efinity;
efinity -> "$project.bit";
}
13 changes: 13 additions & 0 deletions doc/edam/f4pga.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
digraph G {
yosysblif [label="yosys\noutput_format=blif"]
nextpnr [label="nextpnr\narch=ice40"]
"$project.bit" [shape=box,style=filled]

frontends -> yosysjson[label="pnr==nextpnr "];
frontends -> yosyseblif[label="pnr==vpr "];
yosysjson -> nextpnr;
yosyseblif -> vpr;
vpr -> genfasm;
genfasm -> xcfasm;
xcfasm -> "$project.bit";
}
5 changes: 5 additions & 0 deletions doc/edam/generic.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
digraph G {
"?" [shape=box,style=filled]
frontends -> "$tool";
"$tool" -> "?";
}
6 changes: 6 additions & 0 deletions doc/edam/gls.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
digraph G {
"model" [shape=box,style=filled,label="Simulation model"]
frontends -> "$synth";
"$synth" -> "$sim";
"$sim" -> "model";
}
14 changes: 14 additions & 0 deletions doc/edam/icestorm.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
digraph G {
"$project.bit" [shape=box,style=filled]
"$project.json" [shape=box,style=filled]
yosys [label="yosys\narch=ice40\noutput_format=json"]
nextpnr [label="nextpnr\narch=ice40"]

frontends -> yosys;
yosys -> nextpnr;
yosys -> "$project.json" [label="pnr==none"];
nextpnr -> icetime;
nextpnr -> icebox_stat;
nextpnr -> icepack;
icepack -> "$project.bit";
}
3 changes: 3 additions & 0 deletions doc/edam/lint.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
digraph G {
frontends -> "$tool";
}
5 changes: 5 additions & 0 deletions doc/edam/sim.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
digraph G {
"model" [shape=box,style=filled,label="Simulation model"]
frontends -> "$tool";
"$tool" -> "model";
}
12 changes: 12 additions & 0 deletions doc/edam/vivado.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
digraph G {
yosys [label="yosys\narch=xilinx\noutput_format=edif"]
vpnr [label="vivado\nsynth=none"]
"$project.bit" [shape=box,style=filled]
"$project.v" [shape=box,style=filled]
frontends -> yosys[label="synth==yosys "];
frontends -> "vivado"[label="synth!=yosys"];
yosys -> "vpnr";
vivado -> "$project.v"[label="pnr==none"];
vivado -> "$project.bit"[label="pnr!=none"];
"vpnr" -> "$project.bit";
}
8 changes: 8 additions & 0 deletions doc/edam/vpr.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
digraph G {
yosysblif [label="yosys\noutput_format=blif"]
"$project.analysis" [shape=box,style=filled]

frontends -> yosysblif;
yosysblif -> vpr;
vpr -> "$project.analysis";
}
4 changes: 2 additions & 2 deletions edalize/edatool.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,12 +568,12 @@ def gen_tool_docs():
table.append(
{
"name": name.lower(),
"type": "`" + name + "`_",
"type": "`" + name + " backend`_",
"desc": name + "-specific options",
}
)

s += "\n{}\n{}\n\n".format(name, "~" * len(name))
s += "\n{} backend\n{}\n\n".format(name, "~" * (len(name) + 8))
s += _class_doc(backend.get_doc(0))

return (
Expand Down
4 changes: 2 additions & 2 deletions edalize/flows/vivado.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


class Vivado(Edaflow):
"""The Vivado backend executes Xilinx Vivado to build systems and program the FPGA"""
"""The Vivado flow executes AMD Vivado to create a bitstream and optionally program a board. Yosys can be used for synthesis by setting the synth option accordingly"""

argtypes = ["vlogdefine", "vlogparam"]

Expand All @@ -19,7 +19,7 @@ class Vivado(Edaflow):
FLOW_OPTIONS = {
"frontends": {
"type": "str",
"desc": "Tools to run before yosys (e.g. sv2v)",
"desc": "Tools to run before Vivado (e.g. sv2v)",
"list": True,
},
"pgm": {
Expand Down

0 comments on commit f83a8b3

Please sign in to comment.