librecores / riscv-sodor

educational microarchitectures for risc-v isa
Other
64 stars 20 forks source link

find a way to allow verilator access binary #1

Closed wallento closed 6 years ago

wallento commented 7 years ago

This is the ELF, right?

Here is a recent discussion about it: https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/NPYFXN4XNYk

There are two options:

  1. loading the hex file via $readmemh and use DPI to trigger that function. Example: https://github.com/optimsoc/sources/blob/master/src/soc/hw/sram/verilog/sram_sp_impl_plain.sv#L116 and https://github.com/wallento/fusesoc_cores/blob/master/tools/simutil/verilator/src/VerilatedControl.cpp#L72 (a bit more complex)

  2. using an ELF loader to load to memory. The memory array is accessed by a DPI function and the base address known. The ELF loaded is then loaded directly. For an example elf loader see https://github.com/openrisc/orpsoc-cores/blob/master/cores/elf-loader/elf-loader.c or https://github.com/opensocdebug/software/blob/master/src/memory.c#L337

wallento commented 7 years ago

@ccelio The memory is generated by Chisel, right? Does it also generate some DPI functions along with it? If not its worth suggesting it.

ccelio commented 7 years ago

@wallento this is where the scratchpad memory is instantiated:

https://github.com/librecores/riscv-sodor/blob/master/src/common/memory.scala#L88

Also notice there's an extra wrinkle of complication -- the memory is banked (because the HTIF protocol wrote 8 byte chunks but the core only reads in 4 byte chunks). I think @codelec should probably remove the banking. For starters, it will make initializing the scratchpad memory easier.

wallento commented 7 years ago

Is SeqMem transformed to a simple memory in FIRRTL? (Sorry, I hope you simply know, otherwise I can look it up too)

If that is the case we may suggest adding some complexity to the Verilog emitter and provide the configuration option to write SystemVerilog with DPI here: https://github.com/ucb-bar/firrtl/blob/master/src/main/scala/firrtl/Emitter.scala#L612

This seems kind of the cleanest way for me.

wallento commented 7 years ago

Ah, maybe its even more clean to add an extra FIRRTL transform that creates a blackbox and put the systemverilog file into the sources. I will need to check how easy it can be hooked in and if this is useful to a broader community in which case the other solution is maybe preferable.

ccelio commented 7 years ago

I'm not fully familiar with how SeqMem's are handled, except to say that (with a --repl-seq-mem flag to firrtl) they are blackboxed (so you can use your foundry's SRAM model in its place).

Example invocation:

https://github.com/freechipsproject/rocket-chip/blob/master/vsim/Makefrag-verilog#L17

wallento commented 7 years ago

Ah, I see. Then we should maybe try this option and use a simple System Verilog + DPI memory module for the blackbox. This is the best option for Verilator I think.

jackkoenig commented 7 years ago

I've proposed some Chisel support to help with this: https://github.com/ucb-bar/chisel3/issues/609

In effect, this wouldn't provide DPI functions or anything but would provide the information necessary to easily generate it. I agree that initializing memories is such a common thing in simulation that perhaps it should have additional supports on top though.

wallento commented 7 years ago

Thanks @jackkoenig, that is indeed also very useful! Verilator works fine with hierarchical wiring and it should be possible to have the DPI in the testbench top then.

One slight disadvantage of this approach is that the DPI is not in the scope of the module then and in the case of multiple memories one initialization function per memory is needed. When the DPI is in the memory it is instead possible to scope.

For example see how we do this in one of my projects, where we add multiple memories in the cpp top: https://github.com/optimsoc/sources/blob/master/examples/sim/system_2x2_cccc/tb_system_2x2_cccc.cpp#L21 and then then the hierarchical names are used to scope into each of them for initialization: https://github.com/wallento/fusesoc_cores/blob/master/tools/simutil/verilator/src/VerilatedControl.cpp#L74

This seems a bit more elegant, but either would work just fine.

wallento commented 7 years ago

The next step here is to wait until AsyncReadMem is ready and then move forward with: