-
Notifications
You must be signed in to change notification settings - Fork 48
Description
I have been struggling with RISCOF two years ago and I gave up. This time I got through, and I would like to propose a few changes that would make it easier for less experienced developers to also get through. When somebody asks in a forum "what can I do to complete/test my hobby RISC-V" I struggle with guilt when recommending RISCOF. This is just a discussion before I prepare actual pull requests.
My intention is to only propose expanding the documentation and changes to templates. This way existing users would not be affected by changes breaking their flow.
Some examples below:
Separate sh
and Makefile
syntax in command construction
Currently multiple commands are combined into a single string which is used as a target in the Makefile.
Each command is appended a semicolon ;
which is a Makefile requirement.
It is easy to make a simple mistake and forget the semicolon in a new command, and this can take hours to debug (at least the first time you encounter it and after a two year pause all over again).
So instead I would propose the commands are first organized into a simple python list and then at the end combined into a Makefile target.
# list all commands that need to be executed within a make-target.
execute = []
execute.append(f'cd {test_dir}')
execute.append(f'{elfcmd}')
execute.append(f'{bincmd}')
execute.append(f'{disasscmd}')
execute.append(f'cd -')
execute.append(f'{simcmd}')
# create a target. The makeutil will create a target with the name "TARGET<num>" where num
# starts from 0 and increments automatically for each new target that is added
make.add_target('@' + ';\\\n'.join(execute))
This way each individual command is strictly a shell CLI, and everything Makefile related (@
, ;\\\n
) is added separately.
The compile (gcc) command
The command is now split into initialise
, build
and runTests
stages, it is not just a simple concatenation, and the format
arguments are not in order.
I get the idea that the executable (gcc, sail) is defined during initialise
, so its availability should be checked early (and missing executable paths reported). But this check can only be done during build
, since XLEN is extracted from YAML in the build
stage.
All the gcc arguments could just be specified in the runTests
stage, I do not see an advantage in specifying them early.
Python Formatted String Literals would make the code easier to read (f'cmd {elf} {signature}'
instead of 'cmd {0} {1}'.format(elf, signature)
).
cmd = self.compile_cmd.format(self.xlen, testentry['isa'].lower()) + f' {test} -o {elf} {" -D".join(testentry['macros'])}'
More
To be discussed separately:
- The current
master
branch is broken, I think it is a Python module dependency version change. - Why does the Python plugin
self.name
contain an extra character (I think it is a colon:
) that needs to be removed withself.name[:-1]
? - I plan to document the
sail
andspike
log format, and provide instructions on how to reproduce it on the DUT side in SystemVerilog and VHDL. Also hot to use the log to identify where in the waveforms to look for bugs. - I plan to document one approach for how the DUT testbench is supposed dump the signature. With
model_test.h
changes and Verilog/VHDL examples. - I had an idea to extract symbols (
begin_signature
,end_signature
,tohost
,fromhost
addresses change for each test) from the ELF file, and pass them to the DUT executable (plusparam
for Verilog and generics for VHDL) so the DUT could implement thehtif
interface. This way the DUT could use the samemodel_test.h
as the reference, instead of the user writing a custom signature dump procedure. But after writing most of the code, I figured I can't just switch back to the Python plugin in the middle of executing a Makefile target.