Draft PR: Add generic testbench CLI #242
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is something that I have been mulling over for a while to replace the need for makefiles. The idea is simple, set things up such that testbenches can be run both via the command line and via pytest with a minimal amount of per-testbench code, while enabling parameter values and other settings to be easily adjusted.
For reference, with Makefiles, you can specify parameter overrides via the command line and pass these through in a simulator-specific way. Usually I do something along these lines:
This is great because parameters can be specified both in the makefile itself and via the command line, and parameter values can also be computed based on other parameter values. For example, the makefile could contain some lines like so:
Individual parameters can also be overridden on the command line like so:
And in the above example, this will also automatically propagate to
KEEP_ENABLE
andKEEP_WIDTH
.The question, then, is how to replicate this functionality in Python. It's simple enough to add a CLI entry point and use argparse, but handling the parameter overriding in a similar way is a bit more complex. And also it makes no sense to carry around a bunch of boilerplate CLI code in every testbench. Additionally, due to how pytest decorators work, it's also necessary to support multiple entry points so that both the CLI and pytest can coexist.
There are several things that need to be done for this to work correctly. The first is that
cocotb_test.simulator.run
cannot be called from the testbench itself, that has to be abstracted away a bit. The testbench configuration has to be defined piecemeal - part of it statically in the testbench script (names, paths, files, registering parameters, etc.), then it can be augmented as needed by both the CLI entry point as well as one or more pytest entry points. Ideally, the CLI entry point would be a single function call that passes control to a generic implementation, which handles argparse internally.Parameters (and potentially also defines) can then be registered with generic CLI module, along with default values. The default values can be either raw values or computations involving other parameters.
eval
is used internally to evaluate the parameter values, while also considering any values overridden by command line arguments.As an example, here is an updated version of
test_parameters.py
:The current implementation is very much a rough draft and has a number of pitfalls and limitations that would have to be addressed. But, I'm also thinking there may be some deeper changes worth considering in cocotb-test itself.
Primarily, it might be worth considering reworking some stuff in
simulator.py
so that all of the settings can be split off from the rest of the implementation. This way, the settings can be built up incrementally and passed around as a single object, instead of dealing with a stack of separate arguments or adict
. With the current setup, you either need a very cumbersome long list of arguments, or a dict that might as well be a proper object. The currentSimulator
class and its subclasses are not appropriate - all of the settings get passed into the constructor, messing with the settings after the constructor is called is potentially problematic. And theSimulator
object itself isn't meant to be used directly, instead the proper subclass should be used based on the target simulator, and if the CLI is going to have a command-line option for the simulator, then the determination of which object to use would have to be done after running argparse, which is much too late.Other things that would need to be resolved include proper handling of string parameters and HDL-style numbers (e.g.
16'hABCD
,32'd54321
, etc.). The current CLI implementation also only supports parameters and--waves
, this should be extended to support defines, simulator selection, and really anything else that might need to be adjusted at run time. There may also need to be some way of determining when the parameters/defines/etc. have been changed, triggering a rebuild. Not sure if this should be done via adjustingsim_build
based on some/all of the settings, by writing out the configuration to a file insim_build
and checking this against the current configuration, or perhaps some combination of the two.