DV Flow Task Reference

This section documents the DV Flow tasks provided by libfusesoc.

Task Overview

libfusesoc provides tasks organized into packages:

  • fusesoc - Core management tasks

  • fusesoc.edalize.sim - Simulation flow tasks

  • fusesoc.edalize.fpga - FPGA synthesis tasks (stub)

  • fusesoc.edalize.lint - Linting tasks (stub)

fusesoc Package

CoreResolve Task

Task: fusesoc.CoreResolve
Description: Resolve FuseSoC core and retrieve file lists

Purpose: Resolves a FuseSoC core by VLNV identifier, extracts all files, dependencies, and metadata. This is typically the first step in any flow using FuseSoC cores.

Input Parameters:

core:

Core VLNV (vendor:library:name:version)

target:

Target configuration (default: “sim”)

tool:

Tool name for tool-specific filesets (optional)

libraries:

Additional library mappings (dict)

workspace:

FuseSoC workspace directory path

flags:

Build flags (list)

Output Values:

core_name:

Resolved core name

core_root:

Core root directory path

files:

Converted file list (list of dicts)

dependencies:

Core dependencies (list)

parameters:

Core parameters (dict)

include_dirs:

Include directory paths (list)

Example Usage:

from dv_flow.libfusesoc.fusesoc_core_resolve import CoreResolve, CoreResolveParams

# Resolve a UART core for simulation
result = await CoreResolve(runner, CoreResolveParams(
    core="vendor:lib:uart:1.0",
    target="sim",
    tool="icarus",
    workspace="/tmp/fusesoc_workspace",
    libraries={
        "mylib": "/path/to/custom/cores"
    }
))

# Access outputs
print(f"Resolved: {result.output['core_name']}")
print(f"Found {len(result.output['files'])} files")
for file in result.output['files']:
    print(f"  {file['name']} ({file['file_type']})")

Caching: The task supports memento-based caching. Results are cached based on the input parameters, avoiding redundant core resolution.

CoreFetch Task

Task: fusesoc.CoreFetch
Description: Fetch remote FuseSoC core dependencies

Status: Not yet implemented

Purpose: Fetches remote FuseSoC cores from git repositories or other sources into the local workspace.

fusesoc.edalize.sim Package

The simulation package provides three tasks that form a complete simulation pipeline.

SimConfigure Task

Task: fusesoc.edalize.sim.SimConfigure
Description: Configure simulation using Edalize

Purpose: Configures a simulation tool with the design files and parameters. Builds the EDAM structure and sets up the Edalize backend.

Input Parameters:

core_name:

Name of the design

files:

File list from CoreResolve

include_dirs:

Include directory paths (list)

toplevel:

Toplevel module name

tool:

Simulation tool (icarus, verilator, modelsim, vcs, xcelium, ghdl)

parameters:

Build-time parameters (dict)

plusargs:

Runtime plusargs (list)

tool_options:

Tool-specific options (dict)

Output Values:

work_root:

Edalize work directory path

tool:

Configured simulation tool name

configured:

Configuration success flag (bool)

Supported Tools:

  • icarus - Icarus Verilog (open-source)

  • verilator - Verilator (open-source, high-performance)

  • modelsim - ModelSim/Questa (commercial)

  • vcs - Synopsys VCS (commercial)

  • xcelium - Cadence Xcelium (commercial)

  • ghdl - GHDL VHDL simulator (open-source)

Example Usage:

from dv_flow.libfusesoc.edalize_sim import SimConfigure, SimConfigureParams

result = await SimConfigure(runner, SimConfigureParams(
    core_name="my_uart",
    files=core_result.output['files'],
    include_dirs=core_result.output['include_dirs'],
    toplevel="uart_tb",
    tool="icarus",
    parameters={
        'BAUD_RATE': 115200,
        'DATA_WIDTH': 8
    },
    plusargs=['+dump_waves'],
    tool_options={
        'icarus': {
            'iverilog_options': ['-g2009']
        }
    }
))

SimBuild Task

Task: fusesoc.edalize.sim.SimBuild
Description: Build simulation executable/model
Dependencies: SimConfigure

Purpose: Compiles and elaborates the design to produce a simulation executable or model.

Input Parameters:

work_root:

Edalize work directory (from SimConfigure)

tool:

Simulation tool name

Output Values:

work_root:

Edalize work directory path

build_success:

Build success status (bool)

executable:

Path to simulation executable

Example Usage:

from dv_flow.libfusesoc.edalize_sim import SimBuild, SimBuildParams

result = await SimBuild(runner, SimBuildParams(
    work_root=config_result.output['work_root'],
    tool=config_result.output['tool']
))

if result.output['build_success']:
    print(f"Build succeeded: {result.output['executable']}")
else:
    print("Build failed!")

Error Handling: If compilation fails, the task marks the build as unsuccessful. Check the build_success output and examine logs in the work_root directory.

SimRun Task

Task: fusesoc.edalize.sim.SimRun
Description: Execute simulation with runtime parameters
Dependencies: SimBuild

Purpose: Executes the compiled simulation with runtime arguments and captures results.

Input Parameters:

work_root:

Edalize work directory (from SimBuild)

tool:

Simulation tool name

runtime_plusargs:

Additional runtime plusargs (list)

Output Values:

work_root:

Edalize work directory path

run_success:

Simulation success status (bool)

log_file:

Path to simulation log file

Example Usage:

from dv_flow.libfusesoc.edalize_sim import SimRun, SimRunParams

result = await SimRun(runner, SimRunParams(
    work_root=build_result.output['work_root'],
    tool=build_result.output['tool'],
    runtime_plusargs=[
        '+testname=basic_test',
        '+seed=12345'
    ]
))

if result.output['run_success']:
    print("Simulation PASSED")
else:
    print("Simulation FAILED")

# Read simulation log
with open(result.output['log_file']) as f:
    print(f.read())

Success Detection: The task attempts to determine success/failure based on:

  • Tool exit code

  • Presence of error messages in output

  • Tool-specific success indicators

Complete Simulation Flow Example

Putting it all together:

from dv_flow.libfusesoc.fusesoc_core_resolve import CoreResolve, CoreResolveParams
from dv_flow.libfusesoc.edalize_sim import (
    SimConfigure, SimConfigureParams,
    SimBuild, SimBuildParams,
    SimRun, SimRunParams
)

# Step 1: Resolve the core
print("Resolving core...")
core = await CoreResolve(runner, CoreResolveParams(
    core="my_vendor:lib:my_ip:1.0",
    target="sim",
    workspace="/tmp/fusesoc_ws"
))

# Step 2: Configure simulation
print("Configuring simulation...")
config = await SimConfigure(runner, SimConfigureParams(
    core_name=core.output['core_name'],
    files=core.output['files'],
    include_dirs=core.output['include_dirs'],
    toplevel="top_tb",
    tool="verilator",
    parameters={'CLK_FREQ': 100_000_000}
))

# Step 3: Build
print("Building simulation...")
build = await SimBuild(runner, SimBuildParams(
    work_root=config.output['work_root'],
    tool=config.output['tool']
))

if not build.output['build_success']:
    print("Build failed!")
    exit(1)

# Step 4: Run
print("Running simulation...")
run = await SimRun(runner, SimRunParams(
    work_root=build.output['work_root'],
    tool=build.output['tool'],
    runtime_plusargs=['+verbose=2']
))

# Check results
if run.output['run_success']:
    print("✅ Test PASSED")
else:
    print("❌ Test FAILED")
    print(f"See log: {run.output['log_file']}")

fusesoc.edalize.fpga Package

Note

FPGA flow tasks are currently stubs and not yet implemented.

Planned Tasks:

  • FPGAConfigure - Configure FPGA synthesis flow

  • FPGABuild - Run synthesis and place & route

  • FPGAProgram - Program FPGA device

fusesoc.edalize.lint Package

Note

Linting flow tasks are currently stubs and not yet implemented.

Planned Tasks:

  • LintConfigure - Configure linting tool

  • LintRun - Execute lint checks

Task Development Guide

Creating Custom Tasks

To create custom tasks that integrate with libfusesoc:

  1. Import the CoreResolve task to get FuseSoC core files

  2. Use the file lists and parameters in your custom task

  3. Follow DV Flow task patterns (Pydantic models, async/await)

Example custom task:

from pydantic import BaseModel
from dv_flow.libfusesoc.fusesoc_core_resolve import CoreResolve, CoreResolveParams

class MyCustomParams(BaseModel):
    core: str
    workspace: str
    # ... custom parameters

class MyCustomOutput(BaseModel):
    success: bool
    # ... custom outputs

class MyCustomTask:
    async def __call__(self, runner, params: MyCustomParams):
        # First, resolve the core
        core_result = await CoreResolve(runner, CoreResolveParams(
            core=params.core,
            workspace=params.workspace
        ))

        # Now use the files in your custom logic
        files = core_result.output['files']

        # ... your custom task logic ...

        return MyCustomOutput(success=True)

Best Practices

  1. Always resolve cores first: Use CoreResolve before other operations

  2. Chain tasks properly: Pass outputs to next task’s inputs

  3. Handle errors gracefully: Check success flags and provide diagnostics

  4. Use appropriate tools: Choose the right simulator/synthesizer for your needs

  5. Leverage caching: CoreResolve caches results automatically

  6. Isolate workspaces: Use separate workspace directories for different projects