File Structure - StanfordVLSI/dragonphy2 GitHub Wiki
DragonPHY file structure
We have adopted some standards for where files are placed to make it easier to manage the project. At the top level of the DragonPHY repo, we have the following directories:
build
: This folder is not committed to the git repo, but output products from generator scripts go here.config
: Put YAML files here representing the system configuration (number of ADCs, format of certain fixed-point numbers, etc.)dragonphy
: Put Python code here. Since this project is structured as a Python package, other scripts can access code in thedragonphy
folder withimport dragonphy
.inc
: Place Verilog header files here. (In this document, "Verilog" really means "Verilog or SystemVerilog.")tests
: Tests that should be automatically run on GitHub commits should be placed here. Since pytest is used to run the tests, each script name should start withtest_
, and the scripts should define one or more functions whose names start withtest_
(each such function will be run as a separate test by pytest). It's fine to have folder hierarchy inside thetests
folder.- vlog: Put Verilog code here. Subdirectory names like "chip_src" and "fpga_models" are labels for the purpose of the code in those folders. We take advantage of that labeling in the get_deps function that automatically resolves Verilog code dependencies based on label preferences (more on that later).
Verilog source rules
- Subdirectories in the
vlog
folder have labels likechip_src
andfpga_models
, which are assigned to the Verilog code inside those folders. - Please place Verilog code in the label directories (i.e., not in the top level of
vlog
). It's perfectly fine to use folder hierarchy inside the label directories. - Verilog code must use an extension
.v
or.sv
. - Only one module definition is allowed per Verilog file, and the name of the file must match the name of the module it defines. So a file that defines the module
top
, that module definition must be in a file calledtop.v
ortop.sv
.
get_deps
The point of the Verilog source rules is to make it easier to assemble a list of source files for different purposes, like CPU simulation, FPGA emulation, and synthesis. These source file lists are generated using the get_deps
function that can be imported from the dragonphy Python package.
For example, consider this file structure:
vlog
├── chip_src
| └── top.sv
├── cpu_models
| └── mod_a.sv
└── fpga_models
└── mod_a.sv
where vlog/chip_src/top.sv
contains:
module top;
mod_a mod_a_inst ();
endmodule
We can get the file list for FPGA emulation by running the following in Python:
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'fpga_models'])
['vlog/fpga_models/mod_a.sv', 'vlog/chip_src/top.sv']
Even though mod_a
has an implementation in cpu_models
, that implementation is not used because cpu_models
is not in the view list. Also note that the source file list structured such that each file is preceded by its dependencies, which means that you can generally pass the dependency list directly to CAD tools.
Here's another example for CPU simulation:
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'cpu_models'])
['vlog/cpu_models/mod_a.sv', 'vlog/chip_src/top.sv']
This is similar to the previous result, but the cpu_models
implementation of mod_a
is preferred.
It is also possible to provide a specific label that should be used for a certain module via the override
argument. For example:
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'cpu_models'],
... override={'mod_a': 'fpga_models'})
['vlog/fpga_models/mod_a.sv', 'vlog/chip_src/top.sv']
The view_order
is ignored for modules that appear in the override
dictionary. (This particular example is a bit contrived, but it is useful to have override
as an escape hatch.)
There are also times when it is useful to be able to tell get_deps
not to try to descend into a particular module, such as when the module implementation comes from a file outside of the vlog
directory. This is possible with the skip
argument. For example:
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'cpu_models'], skip={'mod_a'})
['vlog/chip_src/top.sv']
As you can see get_deps
does not try to find the implementation of mod_a
, and it does not try to descend into that module.
Since get_deps
parses Verilog files to determine what modules are being defined and instantiated, it is sometimes necessary to provide a search path for `include
files or declare `define
macros in order for the Verilog file to be syntactically correct. When that is the case, the includes
and defines
arguments can be provided to get_deps
, like this:
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'cpu_models'],
... includes=['dir1', 'dir2'], defines={'def1': 'val1', 'def2': None})
['vlog/cpu_models/mod_a.sv', 'vlog/chip_src/top.sv']
Note that includes
should be a list of directories to use in the `include
search path, while defines
is a dictionary of `define
macros. It's OK to use a value of None
in the defines
dictionary when a macro should be defined but not have a specific value.
Finally, it's worth noting that get_deps
actually searches both the vlog
and build
folders, using exactly the same rules. This means that you can generate models that go into the build
folder, and still have them discovered automatically when using get_deps
. As an example, consider this file structure:
build
├── fpga_models
| └── mod_a.sv
vlog
└── chip_src
└── top.sv
Then we can use get_deps
just as before to generate the file list for emulation.
>>> from dragonphy import get_deps
>>> get_deps('top', view_order=['chip_src', 'fpga_models'])
['build/fpga_models/mod_a.sv', 'vlog/chip_src/top.sv']
Even though the arguments to get_deps
have not changed, it now discovers that the implementation of mod_a
is in the build/fpga_models
folder. If mod_a
were defined in both build/fpga_models
and vlog/fpga_models
, get_deps
would error out with an Exception
.