olofk / edalize

An abstraction library for interfacing EDA tools
BSD 2-Clause "Simplified" License
642 stars 191 forks source link

EDAM missing the concept of Verilog compilation units #220

Open RasmusGOlsen opened 3 years ago

RasmusGOlsen commented 3 years ago

The EDAM format is missing the concept of Verilog compilation units. Comparing the implementation of the tools Modelsim and Vcs shows that Modelsim chooses to compile each file in its own compilation unit while Vcs choose to compile all files in a single compilation unit. Both cases are a simplified interpretation of compile units and cannot be generalized. I think compilation units must be specified in the EDAM data structure in order to ensure consistency between tools.

olofk commented 3 years ago

Yes, you are right and this is something that comes up more frequently. Problem I have is that I'm not really sure how these things are used in practice. As a first step towards fixing this, some backends have added a flag to select if the files should go into separate compilation units or just a big one. This solves a whole class of problems, but as you say, it isn't technically correct.

I'm wondering if we can reuse logical_name that is used for VHDL libraries to indicate compilation units so that all files with the same logical_name would go into the same unit. Would that be correct? And what about include files? Would they only be available for their respective compilation unit or are they considered global? Could we tjus treat each core as a compilation unit and be done with it? The key here is to find the method that works for most cases without being unreasonably tedious for the user

RasmusGOlsen commented 3 years ago

I think there are too many ways this is used in practice to be able to find a simplified way that suits all. We can not use the logical_name for specifying compilation units, because you can compile several units into a library. The include files are not global they are only used within a unit. I understand the challenges between usability and a generalized approach, but I believe that the backend should solve a general problem, then the frontend can simplify it and make it user-friendly.

I would suggest that the backend operates on units instead of files. Here is a quick example of how the data structure could look like in Yaml.

---
units:
  - name: A.unit
    logical_name: work
    type: Verilog
    dependencies: []
    args: []
    files:
      - name: moduleA.sv
        is_include_file: False
      - name: submoduleA.sv
        is_include_file: False

  - name: B.unit
    logical_name: work
    type: VHDL
    dependencies: [C.unit]
    args:
       - +define VAR=42
    files:
       - name: moduleB.vhd
         is_include_file: False

  - name: C.unit
    logical_name: work
    type: VHDL
    dependencies: []
    args: []
    files:
       - name: moduleC.vhd
         is_include_file: False

  - name: TB.unit
    logical_name: work
    type: SystemVerilog
    dependencies:
      - B.unit
      - C.unit
    args:
      - -sv
    files:
      - name: tb.sv
        is_include_file: False
      - name: tb_defines.svh
        is_include_file: True
olofk commented 3 years ago

I agree that Edalize should be open-ended enough to make this possible but it needs a bit of thinking to see how to achieve this. I think you're touching several topics here and I would like to break this down so that we don't have to solve them all at once.

  1. Dependencies between source files. Currently Edalize (and FuseSoC) guarantees the compile-order, but there is no dependancy graph between files. This is something we want to support long-term for partial recompilation.
  2. File/Fileset/Unit/Core-specific settings and include files. There is also no way currently to make an include files private to a subset of files. This ties into the dependencies above because we eventually only want to rebuild files that are actually affected by a change in an include file
  3. I had a third one but forgot what it was while writing the two first ones.