fusesoc icon indicating copy to clipboard operation
fusesoc copied to clipboard

Support for compiling and running cocotb simulations

Open imphil opened this issue 5 years ago • 1 comments

Cocotb is, at its core, a VPI/VHPI/FLI library. This library is loaded by the simulator during startup. The behavior of this library (and therefore, cocotb) is influenced by a series of environment variables, which are set before the simulator is started, and which are then read by the library.

Currently, cocotb produces a simulator-specific VPI/VHPI/FLI library during installation time.

To then run a simulation, users can either

  • manually call their simulator of choice and pass it the list of RTL sources, parameters/defines/etc, the VPI library, potentially a couple tool-specific options, and set a number of environment variables.
  • or, use Makefiles provided by cocotb, which do exactly that in a more abstracted way.

To get rid of the Makefiles in cocotb, and to be able to use the simulator abstraction in edalize, I'm envisioning something like this:

simple_dff.core: An example for a user-written core file to simulate the simple_dff design with cocotb.

CAPI=2:
name: cocotb:examples:simple_dff
filesets:
  rtl_files:
    files:
      - dff.sv
    file_type: systemVerilogSource
  sim_cocotb_files:
    depend:
      - cocotb:cocotb:lib:0.1
    files:
      - test_sim_dff.py
    file_type: pythonSource

targets:
  sim-cocotb:
    default_tool: icarus
    filesets:
      - rtl_files
      - sim_cocotb_files
    environment_variables: # That doesn't exist today
      MODULE: test_sim_dff

cocotb-libs.core: A cocotb-provided core file which can be included to simulate with cocotb. (It's likely we want to have a generator produce this file to get the full paths of the libraries and abstract away Windows/Linux differences, such as libcocotbvpi_icarus.vpi, from the cocotb-config tool. But that's an implementation detail.)

name: cocotb:libs:cocotb-libs

vpi:
  cocotb_vpi:
    libs:
      - tool_icarus ? (libcocotbvpi_icarus.vpi)
      - tool_modelsim ? (libcocotbvpi_modelsim.so)

targets:
  default:
    # Not sure about today's syntax.
    vpi:
      - cocotb_vpi
    # That's not inherited today (I think?)
    tools:
      modelsim:
        vsim_options: 
          - "-foreign cocotb_init libcocotbfli_modelsim.so"

This use case uncovers a couple areas in fusesoc/edalize which need changes.

  • Fusesoc/edalize take care of resources like files, tool options, and defines/parameters, but it's lacking support for environment variables in the same way.
  • VPI support is lacking in various fronts. We need to make sure we support VHPI/FLI the same way we support VPI, better support pre-compiled VPI libraries, and potentially the ability to define entry points which are passed to non-compliant simulators.
  • Inheritance of resources in the default target beyond file sets is not uniform/lacking.

To untangle this a bit: @olofk would you mind going over the example and add your thinking and correct what I got wrong? (It's probably best you edit my post directly.)

Once we have agreement on the general way of how things could work I'll file individual issues to track the detailed design and implementation of those (e.g. improved VPI support).

imphil avatar Jun 26 '20 14:06 imphil

This general approach looks good to me and would achieve most of what I was aiming to do in my edalize PR https://github.com/olofk/edalize/pull/162 in a neat way.

One aspect that I'd like to raise is how we build a PYTHONPATH. @eric-wieser raised some good points in an earlier PR (https://github.com/olofk/edalize/pull/138#discussion_r423196261) concerning what gets added to the path. I was adding the parent directory of every Python source file to the path, but this leads to ambiguity. As fusesoc stands, I could not see a way round this. In the world of this proposal, there is no cocotb backend to process the python files and construct the path in any case.

I've got some early thoughts about how this could be done - definitely not fully thought through, but presented for discussion...

We could enable fusesoc cores to contain path components rather like filesets. fusesoc would then build the path as it pulls in the dependencies. The Python files would still need to be listed individually so that they are copied into the working directory by fusesoc. We'd need to modify the path components so that they referenced the new location in the same way that file paths are modified now. I suppose that we might assume paths are set as environment variables, so fusesoc could pass them to the backend in that way.

An snippet of an example core file:

filesets:
  model:
    - src/my_package/__init__.py
    - src/my_package/some_module.py

paths:
  PYTHONPATH:
    - src

targets:
  default:
    filesets:
      - model
    paths: 
      - PYTHONPATH

In this example, any core depending on this one would end up with a PYTHONPATH environment variable set so that you could do:

import my_package.some_module

In case my motivation for wanting to be able to do this is not clear, some examples of how my team uses hierarchical Python models in our cocotb testbenches are in https://github.com/gchqdev1729/fusesoc-cores.

gchqdev1729 avatar Jun 29 '20 11:06 gchqdev1729