-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e7c889e
commit a56947f
Showing
18 changed files
with
1,426 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
Advanced usage | ||
============== | ||
|
||
.. ATTENTION:: | ||
|
||
(2024-05-31) To be updated. | ||
|
||
Multi project managment | ||
----------------------- | ||
|
||
.. code-block:: python | ||
PROJECTS = { | ||
'<NAME1>': Project( | ||
'<TOOLNAME>', | ||
'<PROJECTNAME>', | ||
{ | ||
'outdir': '<DIRNAME>', | ||
'part': '<PARTNAME>' | ||
'paths': [ | ||
'<PATHNAME1>', | ||
... | ||
'<PATHNAMEn>' | ||
], | ||
'vhdl': [ | ||
['<FILENAME1>', '<LIBRARYNAME1>'], | ||
'<FILENAME2>', | ||
... | ||
'<FILENAMEn>' | ||
], | ||
'verilog': [ | ||
'<FILENAME1>', | ||
... | ||
'<FILENAMEn>' | ||
], | ||
'constraint': [ | ||
'<FILENAME1>', | ||
... | ||
'<FILENAMEn>' | ||
], | ||
'params': { | ||
'<PARAMNAME1>': '<VALUE1>', | ||
... | ||
'<PARAMNAMEn>': '<VALUEn>' | ||
}, | ||
'top': '<TOPNAME>' | ||
} | ||
) | ||
'<NAME2>': Project( | ||
... | ||
) | ||
} | ||
.. _hooks: | ||
|
||
Hooks | ||
----- | ||
|
||
The following table depicts the parts of the *Project Creation* and the | ||
*Design Flow* internally performed by PyFPGA. | ||
|
||
+--------------------------+----------------------+ | ||
| Project Creation | Design Flow | | ||
+==========================+======================+ | ||
| Part specification | **preflow** hook | | ||
+--------------------------+----------------------+ | ||
| **prefile** hook | Synthesis | | ||
+--------------------------+----------------------+ | ||
| Files addition | **postsyn** hook | | ||
+--------------------------+----------------------+ | ||
| Top specification | Place and Route | | ||
+--------------------------+----------------------+ | ||
| Parameters specification | **postpar** hook | | ||
+--------------------------+----------------------+ | ||
| **project** hook | Bitstream generation | | ||
+--------------------------+----------------------+ | ||
| | **postbit** hook | | ||
+--------------------------+----------------------+ | ||
|
||
If the provided API if not enough or suitable for your project, you can | ||
specify additional *hooks* in different parts of the flow, using: | ||
|
||
.. code-block:: python | ||
prj.add_hook(hook, phase) | ||
.. NOTE:: | ||
|
||
* Valid vaues for *phase* are ``prefile``, ``project`` (default), ``preflow``, | ||
``postsyn``, ``postpar`` and ``postbit``. | ||
* The *hook* string must be a valid command (supported by the used tool). | ||
* If more than one *hook* is needed in the same *phase*, you can call this | ||
method several times (the commands will be executed in order). | ||
|
||
Parameters | ||
---------- | ||
|
||
The generics/parameters of the project can be optionally changed with: | ||
|
||
.. code-block:: python | ||
prj.add_param('param1', value1) | ||
... | ||
prj.add_param('paramN', valueN) | ||
Generate options | ||
---------------- | ||
|
||
The method ``generate`` (previously seen at the end of | ||
[Basic usage](#basic-usage) section) has optional parameters: | ||
|
||
.. code-block:: python | ||
prj.generate(to_task, from_task, capture) | ||
With *to_task* and *from_taks* (with default values ``bit`` and ``prj``), | ||
you are selecting the first and last task to execute when `generate` is | ||
invoqued. The order and available tasks are ``prj``, ``syn``, ``par`` and ``bit``. | ||
It can be useful in at least two cases: | ||
|
||
* Maybe you created a file project with the GUI of the Tool and only want to | ||
run the Design Flow, so you can use: ``generate(to_task='bit', from_task='syn')`` | ||
|
||
* Despite that a method to insert particular commands is provided, you would | ||
want to perform some processing from Python between tasks, using something | ||
like: | ||
|
||
.. code-block:: python | ||
prj.generate(to_task='syn', from_task='prj') | ||
#Some other Python commands here | ||
prj.generate(to_task='bit', from_task='syn') | ||
In case of *capture*, it is useful to catch execution messages to be | ||
post-processed or saved to a file: | ||
|
||
.. code-block:: python | ||
result = prj.generate(capture=True) | ||
print(result) | ||
In case of *capture*, it is useful to catch execution messages to be | ||
post-processed or saved to a file. | ||
|
||
Exceptions | ||
---------- | ||
|
||
Finally, you must run the bitstream generation or its transfer. Both of them | ||
are time-consuming tasks, performed by a backend tool, which could fail. | ||
Exceptions are raised in such cases, that should be ideally caught to avoid | ||
abnormal program termination. | ||
|
||
.. code-block:: python | ||
try: | ||
prj.generate() | ||
prj.transfer() | ||
except Exception as e: | ||
print('{} ({})'.format(type(e).__name__, e)) | ||
And wait for the backend Tool to accomplish its task. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
Basic usage | ||
=========== | ||
|
||
.. ATTENTION:: | ||
|
||
(2024-05-31) To be updated. | ||
|
||
Project Creation | ||
---------------- | ||
|
||
The first steps are import the module and instantiate the ``Project`` *class*, | ||
specifying the *TOOL* to use and, optionally, a *PROJECT NAME* (the *tool* | ||
name is used when *no name* is provided). | ||
|
||
.. code-block:: python | ||
from fpga.project import Project | ||
prj = Project('vivado', 'projectName') | ||
.. NOTE:: | ||
|
||
The supported tool are: ``ghdl``, ``ise``, ``libero``, ``openflow``, | ||
``quartus``, ``vivado``, ``yosys``, ``yosys-ise`` and ``yosys-vivado``. | ||
|
||
.. ATTENTION:: | ||
|
||
PyFPGA assumes that the backend Tool is ready to run. | ||
This implies, depending on the operating system, things such as: | ||
|
||
* Tool installed. | ||
* A valid License configured. | ||
* Tool available in the system PATH. | ||
* GNU/Linux: extra packages installed, environment variables assigned | ||
and permissions granted on devices (to transfer the bitstream). | ||
|
||
By default, the directory where the project is generated is called ``build`` | ||
and is located in the same place that the script, but another name and location | ||
can be specified. | ||
|
||
.. code-block:: python | ||
prj.set_outdir('../temp') | ||
Next, the FPGA part would be specified: | ||
|
||
.. code-block:: python | ||
prj.set_part('xc7k160t-3-fbg484') | ||
.. NOTE:: | ||
|
||
You can use the default FPGA part for a quick test or make a lazy comparison | ||
between tools, but generally, you will want to specify a particular one. | ||
Examples about how to specify a part according the tool, are (default values | ||
when ``set_part`` is not employed): | ||
|
||
* **Ise:** ``xc7k160t-3-fbg484`` (*device-speed-package*) | ||
* **Libero:** ``mpf100t-1-fcg484`` (*device-speed-package*) | ||
* **Openflow:** ``hx8k-ct256`` (*device-package*) | ||
* **Quartus:** ``10cl120zf780i8g`` (*part*) | ||
* **Vivado:** ``xc7k160t-3-fbg484`` (*part*) | ||
|
||
The files addition method allows specifying one or more HDL or constraint files | ||
(also block designs in case of Vivado). | ||
It uses ``glob`` internally, which makes available the use of wildcards. | ||
The path to their location must be relative to the Python script, and there | ||
are optional parameters to indicate the file type (``vhdl``, ``verilog``, | ||
``constraint`` or ``design``), which is automatically detected based on the | ||
file extension, and if it is a member of a VHDL package. | ||
|
||
.. code-block:: python | ||
prj.add_files('hdl/blinking.vhdl', library='examples') | ||
prj.add_files('hdl/examples_pkg.vhdl', library='examples') | ||
prj.add_files('hdl/top.vhdl') | ||
.. NOTE:: | ||
|
||
* In some cases, the files order could be a problem, so take into account to | ||
change the order if needed. | ||
* If a file seems unsupported, you can always use the ``prefile`` or | ||
``project`` :ref:`hooks`. | ||
* In case of Verilog, ``add_vlog_include`` can be used to specify where to | ||
search for included files. | ||
|
||
Finally, the top-level must be specified: | ||
|
||
.. code-block:: python | ||
prj.set_top('Top') | ||
.. NOTE:: | ||
|
||
A relative path to a valid VHDL/Verilog file is also accepted by ``set_top``, | ||
to automatically extract the top-level name. | ||
|
||
Project generation | ||
------------------ | ||
|
||
Next step if to generate the project. In the most basic form, you can run the | ||
following to get a bitstream: | ||
|
||
.. code-block:: python | ||
prj.generate() | ||
Additionally, you can specify which task to perform: | ||
|
||
.. code-block:: python | ||
prj.generate('syn') | ||
.. NOTE:: | ||
|
||
The valid values are: | ||
|
||
* ``prj``: to generate only a project file (only supported for privative tools) | ||
* ``syn``: to performs synthesis. | ||
* ``imp``: to performs synthesis and implementation (place and route, | ||
optimizations and static timming analysis when available). | ||
* ``bit``: (default) to perform synthesis, implementation and bitstream generation. | ||
|
||
Bitstream transfer | ||
------------------ | ||
|
||
This method is in charge of run the needed tool to transfer a bitstream to a | ||
device (commonly an FPGA, but memories are also supported in some cases). | ||
It has up to four main optional parameters: | ||
|
||
.. code-block:: python | ||
prj.transfer(devtype, position, part, width) | ||
Where *devtype* is ``fpga`` by default but can also be ``spi``, ``bpi``, etc, if | ||
supported. An integer number can be used to specify the *position* (1) in the | ||
Jtag chain. When a memory is used as *devtype*, the *part* name and the | ||
*width* in bits must be also specified. | ||
|
||
.. NOTE:: | ||
|
||
* In Xilinx, `spi` and `bpi` memories are out of the Jtag chain and are | ||
programmed through the FPGA. You must specify the FPGA *position*. | ||
* In a Linux systems, you need to have permission over the device | ||
(udev rule, be a part of a group, etc). | ||
|
||
Logging capabilities | ||
-------------------- | ||
|
||
PyFPGA uses the `logging <https://docs.python.org/3/library/logging.html>`_ | ||
module, with a *NULL* handler and the *INFO* level by default. | ||
Messages can be enabled with: | ||
|
||
.. code-block:: python | ||
import logging | ||
logging.basicConfig() | ||
You can enable *DEBUG* messages adding: | ||
|
||
.. code-block:: python | ||
logging.getLogger('fpga.project').level = logging.DEBUG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.