amaranth
amaranth copied to clipboard
[RFC] add pre-run simulation hook for cli.main
as far as i can tell, current simulation cli-based workflow for a module is the following: module.py:
main(m, ...)
which gives control to cli.py:
https://github.com/nmigen/nmigen/blob/746886ca8ac3b9a8941b540a347452805acbbcf2/nmigen/cli.py#L68-L73
which sets up the simulation environment
this (again as far as could see) implies that one needs to have a separate python module that is to be invoked for simulation of module.py.
codegen for a module.py is invoked as module.py generate ..., while
sim for module.py is invoked as some_module.py simulate ...
suggested solution: pre-run simulation hook defined in module.py, invoked by simulate option in cli.main
- pros: unified cli interface for both simulation and codegenration via the
module.pycli arguments - cons: module code bloating as a module will have both hdl-relaed code and testbench-related code in a single file. this may be a problem as testbench code tends to be times larger then uut
For me, the fact that a single files contains all (code + test) was, among other things, a plus when exploring alternatives to VHDL/Verilog. However it is true that I am at a stage where codesize is very modest.
For the little bits of code I could write, coverage and simulation code seems to require setting up a top module. One could imagine to write a Test/Simulation/Whatever Suite that would look like (disclaimer, heavily inspired by JUnit) :
# imports
from ...
class mySuiteOfStuff:
@formalVerification
def shouldVerifyThis(context:VerificationContext): # at least a top module to setup assert/covers etc...
# update the context
@formalVerification
def shouldVerifyThat(c:VerificationContext): # for more concise writing ; and one can have disjointed sets of verifications
# update the context
# of course, a new context is regenerated between each call
@simulation
def simulateThisCase(context:SimulationContext): # at least a simulator instance and a Module to setup
# update the context
@simulation
def simulateThatCase(c: SimulationContext): # again, several simulation can be defined
# update the context
@BeforeAllVerification
def setupGlobalVerification(...): # did I say that I am heavily inspired by JUnit ?
# return something ? or update a provided context ?
@BeforeEachVerification
def setupOneVerification(...): # remainder the function name is free, the decorator is there to spot the function of interest
# return something ? or update a provided context ?
@AfterEachVerification
def tearDownOneVerification(...) : #....
#etc...
@AfterAllVerification
def tearDownAllVerifications(...) : #...
# etc...
# And the same for simulation, but it's so long
# @{Before|After}{All|Each}Simulation
### Launcher ###
if __name__ == "__main__":
main(..., suite=mySuiteOfStuff)
We have a more formal RFC process these days and this proposal would have to go through it to be accepted. In general, CLI improvements are desirable; I have a prototype for a new CLI in #904.