Expressions¶
DV Flow Manager supports dynamic parameter evaluation using the ${{ }}
expression syntax. Expressions allow parameters to reference other parameters,
perform calculations, and make decisions based on configuration values.
Expression Syntax¶
Expressions are enclosed in ${{ }} markers:
tasks:
- name: message
uses: std.Message
with:
msg: "Value is ${{ some_parameter }}"
Any parameter value can contain expressions. They are evaluated during task graph elaboration, before any task execution begins.
Basic Usage¶
Parameter References¶
Reference package and task parameters by name:
package:
name: my_pkg
with:
version:
type: str
value: "1.0"
debug:
type: bool
value: false
tasks:
- name: build
with:
build_type:
type: str
value: "debug"
uses: std.Message
with:
msg: "Building version ${{ version }} in ${{ build_type }} mode"
Expressions can reference:
Package parameters: Defined in the package’s
withsectionTask parameters: Defined in the task’s
withsectionParent task parameters: In compound tasks, access parent parameters
Arithmetic Operations¶
Perform calculations within expressions:
package:
name: example
with:
base_value:
type: int
value: 100
tasks:
- name: task1
uses: std.Message
with:
msg: "Double value: ${{ base_value * 2 }}"
- name: task2
uses: std.Message
with:
msg: "Sum: ${{ base_value + 50 }}"
Supported operators:
Arithmetic:
+,-,*,/,//,%,**Comparison:
==,!=,<,<=,>,>=Logical:
and,or,not
Boolean Expressions¶
Use boolean expressions for conditional logic:
package:
name: example
with:
debug:
type: bool
value: false
optimization:
type: int
value: 2
tasks:
- name: check
uses: std.Message
iff: ${{ debug and optimization < 2 }}
with:
msg: "Debug mode with low optimization"
String Operations¶
Concatenate strings and format values:
package:
name: example
with:
prefix:
type: str
value: "build"
version:
type: str
value: "1.0"
tasks:
- name: task1
uses: std.Message
with:
msg: "${{ prefix }}_v${{ version }}" # "build_v1.0"
Expression Contexts¶
Package Scope¶
At package level, expressions can reference package parameters:
package:
name: example
with:
compiler:
type: str
value: "gcc"
version:
type: str
value: "11"
imports:
- name: toolchain
with:
compiler: ${{ compiler }}
version: ${{ version }}
Task Scope¶
Within tasks, expressions can access:
Package parameters
Task parameters
Parent compound task parameters (if nested)
tasks:
- name: parent
with:
mode:
type: str
value: "release"
body:
- name: child
uses: std.Message
with:
# Access parent's 'mode' parameter
msg: "Running in ${{ mode }} mode"
Matrix Variables¶
When using matrix strategy, expressions can reference matrix variables:
tasks:
- name: test_suite
strategy:
matrix:
test: ["test1", "test2", "test3"]
seed: [100, 200, 300]
body:
- name: run_test
uses: std.Message
with:
msg: "Running ${{ matrix.test }} with seed ${{ matrix.seed }}"
This generates 9 tasks (3 tests × 3 seeds) with appropriate parameter values.
Advanced Features¶
Conditional Expressions¶
Use ternary-like conditional logic:
package:
name: example
with:
debug:
type: bool
value: false
tasks:
- name: build
shell: bash
run: ${{ "make debug" if debug else "make release" }}
Note: Python-style conditional expressions (x if condition else y) are supported.
List and Dict Operations¶
Access list elements and dictionary values:
package:
name: example
with:
flags:
type: list
value: ["-O2", "-Wall", "-Werror"]
config:
type: map
value:
arch: "x86_64"
os: "linux"
tasks:
- name: task1
uses: std.Message
with:
msg: "First flag: ${{ flags[0] }}" # "-O2"
- name: task2
uses: std.Message
with:
msg: "Architecture: ${{ config['arch'] }}" # "x86_64"
Function Calls¶
Limited set of built-in functions are available:
tasks:
- name: example
uses: std.Message
with:
msg: ${{ len(some_list) }} # List length
msg: ${{ str(some_int) }} # Convert to string
msg: ${{ int(some_str) }} # Convert to integer
Available functions:
len(x): Length of list/stringstr(x): Convert to stringint(x): Convert to integerbool(x): Convert to boolean
Expression Evaluation Order¶
Expressions are evaluated in the following order:
Package load time: Package-level expressions in imports and overrides
Task elaboration: Task parameter expressions
Condition evaluation:
iffexpressions for conditional tasksMatrix expansion: Matrix variable substitution
This order ensures that:
Configuration is resolved before task creation
Parameters are available when needed
Dependencies are properly evaluated
Limitations¶
Expressions have some limitations to maintain safety and predictability:
No side effects: Expressions cannot modify state
No I/O: Cannot read files or access network
No arbitrary code: Limited to safe expression subset
Static evaluation: Cannot depend on runtime task data
These limitations ensure that:
Flow specifications remain declarative
Task graphs can be analyzed before execution
Flows are reproducible and predictable
Best Practices¶
Keep Expressions Simple¶
Prefer simple, readable expressions:
Good:
msg: "Version ${{ version }}"
iff: ${{ debug }}
Avoid:
msg: ${{ "v" + str(major) + "." + str(minor) + ("_debug" if debug else "") }}
Use Parameters for Complex Logic¶
Move complex logic into parameters rather than inline expressions:
Good:
package:
with:
full_version:
type: str
value: "${{ major }}.${{ minor }}${{ '_debug' if debug else '' }}"
tasks:
- name: build
uses: std.Message
with:
msg: "Building version ${{ full_version }}"
Document Parameter Relationships¶
When parameters depend on each other, document the relationships:
package:
with:
optimization:
type: int
value: 2
doc: Optimization level (0-3)
debug_symbols:
type: bool
value: false
doc: |
Enable debug symbols. Typically true when optimization is 0,
false otherwise. Can be overridden explicitly.
Common Patterns¶
Version Construction¶
package:
with:
major:
type: int
value: 1
minor:
type: int
value: 0
patch:
type: int
value: 0
version:
type: str
value: "${{ major }}.${{ minor }}.${{ patch }}"
Path Construction¶
package:
with:
install_prefix:
type: str
value: "/opt/tools"
tool_name:
type: str
value: "mytool"
tool_path:
type: str
value: "${{ install_prefix }}/${{ tool_name }}"
Conditional Features¶
package:
with:
enable_coverage:
type: bool
value: false
enable_assertions:
type: bool
value: true
debug_mode:
type: bool
value: "${{ enable_coverage or enable_assertions }}"
Parameter Selection¶
package:
with:
simulator:
type: str
value: "verilator"
debug_level:
type: int
value: 0
tasks:
- name: sim
uses: std.Message
with:
msg: "Using simulator: ${{ simulator }} with debug=${{ debug_level }}"