Best Practices - slaclab/rogue GitHub Wiki

Best Practices for Pyrogue Python Code

This is an attempt to capture best practice for coding style and organization when creating a pyrogue Device Tree.

File naming

If a .py file only has one Device class, name it with an underscore. Example:

_DeviceClassName.py

It is preferred to organize all Device classes this way, to make them easier to find.

Mapping to Firmware Modules

Try to write Device classes that map directly to firmware modules. This makes the software more modular and makes it easier to determine the relationships to firmware. Give things the same name in both VHDL and Python when possible, such as:

  • Device classes <-> VHDL entities
  • Python packages <-> VHDL libraries

The Python package to VHDL library mapping can get a little tricky since VHDL doesn't have the concept of sub-libraries. It is encouraged to create python sub-packages that track the directory structure where the VHDL resides. Example:

python package: surf.axi.axi_lite <-> vhdl directory: surf/axi/axi-lite

The guiding principle behind all of this is that it should be easy to determine sofware/firmware mapping based on how things are named. There may be cases when it makes sense to deviate from this. When this happens, be sure to document in the Python code which firmware modules are being mapped.

Imports

import * is Bad

Never do:

from somelibrary import *

Use import as sparingly

It usually makes it clearer to eschew import as and simply use the full package.module name in the code. Only use import as if it really saves verbosity, such as a long package path that is called multiple times in the code.

In the example below, the import as doesn't really buy much, especially if only one class from surf.axi is ever instantiated. It only creates a level of redirection for someone unfamiliar with the code would have to trace down.

Not useful
import surf.axi as axi
...
self.add(axi.AxiVersion(...))
Better
import surf.axi
...
self.add(surf.axi.AxiVersion(...))
OK to use in some cases
import some.very.long.package.path as svlpp
...
self.add(svlpp.Device1())
self.add(svlpp.Device2())
self.add(svlpp.Device3())
self.add(svlpp.Device4())