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:
Import the CoreResolve task to get FuseSoC core files
Use the file lists and parameters in your custom task
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
Always resolve cores first: Use CoreResolve before other operations
Chain tasks properly: Pass outputs to next task’s inputs
Handle errors gracefully: Check success flags and provide diagnostics
Use appropriate tools: Choose the right simulator/synthesizer for your needs
Leverage caching: CoreResolve caches results automatically
Isolate workspaces: Use separate workspace directories for different projects