-
Notifications
You must be signed in to change notification settings - Fork 55
Refactoring for VHDL Libraries
SURF and many other firmware repositories will soon transition to using proper VHDL libraries. This explainer will help you refactor your code for this change.
The VHDL language allows modules to be grouped into "library" namespaces. This is similar to the namespace/package features found in every modern software language (C++, Python, etc). VHDL libraries prevent naming conflicts between modules from different codebases.
For a long time, we have been punting on proper VHDL library use and instead dropping everything in the default work
namespace. This is becoming a problem as some of our projects use code from CERN that also has modules with names like: Synchronizer
, etc.
An upcoming release of SURF will finally fix this by placing all SURF modules and packages in a surf
VHDL library. This is implemented in the VHDL code itself as well as the Ruckus TCL scripts that build Vivado projects. Since almost every other firmware repository uses SURF, this changes will create a ripple effect requiring those repositories to use proper VHDL libraries as well. (E.g. AmcCarrierCore, axi-pcie-core, etc).
All projects that use SURF will need to refactor their code as shown below.
Old code with SURF modules and packages in work
:
use work.StdRtlPkg
use work.AxiLitePkg
...
U_Synchronizer : entity work.Synchronizer
port map(
clk => clk,
rst => rst,
dataIn => din,
dataOut => dout);
New code with SURF modules and packages in surf
library:
library surf;
use surf.StdRtlPkg
use surf.AxiLitePkg
...
U_Synchronizer : entity surf.Synchronizer
port map(
clk => clk,
rst => rst,
dataIn => din,
dataOut => dout);
We have developed a script that can refactor any code base in a matter of seconds. The script can be found at surf/python/tools/vhdlib.py
# General usage
> python3 firmware/submodules/surf/python/tools/vhdlib.py \
--libname <name> --libpath <path/to/library/code> \
--refactor <path/to/your/code | [another/path/to/your/code]>
# surf example usage
> python3 firmware/submodules/surf/python/tools/vhdlib.py \
--libname surf -libpath firmware/submodules/surf \
--refactor firmware/targets firmware/common
The script first finds every .vhd and .vhdl file recursively in --libpath
. It then parses those VHDL files and makes lists of all of the package
and entity
names that it finds. These lists make up the library namespace.
The script then parses every .vhd and .vhdl file recursively in --refactor
. (You can also specify multiple --refactor
paths). It looks for packages and entities from the namespace that have been declared in the work
namespace and replaces work
with the correct library name. It also adds a library surf;
declaration when necessary.
The script is not SURF specific. It will work to refactor code from any library. Every VHDL library maintained by TID AIR ES will transition to using libraries at the same time, so you will have to run the script once for each library that your project uses in order to fully refactor it.
# Refactor code using AmcCarrierCore
> python3 vhdlib.py --libname amc_carrier_core --libpath firmware/submodules/AmcCarrierCore --refactor firmware/targets
The VHDL naming convention for libraries is lower_case_with_underscores
. Various libraries are therefore named as follows:
AmcCarrierCore -> amc_carrier_core
lcls-timing-core -> lcls_timing_core
axi-pcie-core -> axi_pcie_core
Basicaly, the library name should be the github repository name with underscore separators instead of (-) dashes or CamelCase.
Our firmware projects also tend to dump all local project code into work
as well. You can now easily fix that using the script:
# Put local project code into its own library
> python3 vhdlib.py --libname project_name --libpath firmware/common firmware/targets \
--refactor firmware/common firmware/targets
Note that the --libpath
and --refactor
arguments are the same. The script finds all entities and packages in the --libpath
and then refactors those same packages and entities to use project_name
instead of work
.
You will also have to edit your ruckus.tcl
to tell Vivado to put your code into a library. This is done with the -lib
argument to the loadSource
function:
loadSource -lib project_name -dir "$::DIR_PATH/hdl"
The vhdl-lib branch of SURF has all of the changes that put things into a VHDL library. This is also where you will find the refactoring script. You are encouraged to check out this branch in your own projects' submodules to test it all out before this branch gets put into a release.
Other libraries also have vhdl-lib branches where the transition to libraries has been applied. You will need to checkout the vhdl-lib
branch of each library that your project uses.
The following are the related pull requests for each slaclab VHDL library
- https://github.com/slaclab/surf/pull/541
- https://github.com/slaclab/lcls-timing-core/pull/82
- https://github.com/slaclab/amc-carrier-core/pull/236
- https://github.com/slaclab/rce-gen3-fw-lib/pull/22
- https://github.com/slaclab/axi-pcie-core/pull/43
- https://github.com/slaclab/clink-gateway-fw-lib/pull/2
- https://github.com/slaclab/lcls2-pgp-fw-lib/pull/4