Environment & Paths
Overview
IVPM provides two mechanisms for managing project-specific configuration:
Environment Variables - Set, modify, and export shell variables
Project Paths - Organize and export file paths by category
Both features help tools discover project resources and configuration.
Environment Variables
Note
IVPM delegates environment application to direnv. It does not set variables in your shell itself;
instead it emits the env: directives (together with each package’s
export.envrc) into packages/packages.envrc. Running direnv
allow once authorizes that file, after which the environment loads
automatically whenever you are in the project directory.
Declaring Environment Variables
Define environment variables in ivpm.yaml with a top-level env:
list. Each entry names a variable and one action (see below):
package:
name: my-project
env:
- name: MY_VAR
value: "hello world"
- name: PROJECT_ROOT
value: "${IVPM_PROJECT}"
When env: directives (or packages that publish export.envrc) are
present, ivpm update writes packages/packages.envrc. env:
directives are emitted last, so the project’s own declarations take
precedence over variables set by packages.
Built-in Variables:
The direnv handler always writes these into packages.envrc:
IVPM_PROJECT- Path to project root directoryIVPM_PACKAGES- Path to packages directory
They are available to your own env: directives via ${IVPM_PROJECT}
/ ${IVPM_PACKAGES} (expanded by direnv at load time).
Variable Actions
IVPM supports four actions, each mapping to a direnv/bash directive:
value
Set a variable to a literal value:
env:
- name: BUILD_TYPE
value: "debug"
- name: MAX_JOBS
value: "4"
Result:
export BUILD_TYPE="debug"
export MAX_JOBS="4"
With lists (space-separated):
env:
- name: CFLAGS
value:
- "-O2"
- "-Wall"
- "-Werror"
Result:
export CFLAGS="-O2 -Wall -Werror"
path
Set a variable as a path (colon-separated):
env:
- name: LD_LIBRARY_PATH
path:
- "${IVPM_PACKAGES}/lib1/lib"
- "${IVPM_PACKAGES}/lib2/lib"
- "/usr/local/lib"
Result:
export LD_LIBRARY_PATH="${IVPM_PACKAGES}/lib1/lib:${IVPM_PACKAGES}/lib2/lib:/usr/local/lib"
path-append
Append to an existing path variable:
env:
- name: PATH
path-append:
- "${IVPM_PACKAGES}/bin"
- "${IVPM_PACKAGES}/tools/bin"
Result (emitted into packages.envrc):
# A leading ':' separator is added only when PATH is already set
export PATH="${PATH:+$PATH:}${IVPM_PACKAGES}/bin:${IVPM_PACKAGES}/tools/bin"
path-prepend
Prepend to an existing path variable:
env:
- name: PYTHONPATH
path-prepend:
- "${IVPM_PROJECT}/src"
- "${IVPM_PACKAGES}/mylib/src"
Result (uses the direnv stdlib path_add, which prepends its
arguments and de-duplicates on re-source):
path_add PYTHONPATH "${IVPM_PROJECT}/src" "${IVPM_PACKAGES}/mylib/src"
Variable Expansion
${VAR} references are emitted verbatim and expanded by direnv
(via bash) when the environment loads – IVPM does not expand them
itself:
env:
# Use built-in IVPM variables
- name: PROJECT_SRC
value: "${IVPM_PROJECT}/src"
# Reference previously-set variables
- name: LIB_PATH
value: "${PROJECT_SRC}/lib"
# Reference system environment
- name: USER_HOME
value: "${HOME}"
Order matters: Variables are processed in order, so you can reference earlier variables in later ones.
Complete Environment Example
package:
name: verification-project
env:
# Set project paths
- name: PROJECT_ROOT
value: "${IVPM_PROJECT}"
- name: RTL_ROOT
value: "${PROJECT_ROOT}/rtl"
- name: TB_ROOT
value: "${PROJECT_ROOT}/testbench"
# Configure build
- name: BUILD_TYPE
value: "release"
- name: CFLAGS
value:
- "-O2"
- "-Wall"
# Add tools to PATH
- name: PATH
path-prepend:
- "${IVPM_PACKAGES}/tools/bin"
- "${PROJECT_ROOT}/scripts"
# Set library paths
- name: LD_LIBRARY_PATH
path:
- "${IVPM_PACKAGES}/lib64"
- "${IVPM_PACKAGES}/lib"
# Configure Python
- name: PYTHONPATH
path-prepend: "${IVPM_PROJECT}/src"
Loading the Environment
The generated packages.envrc is consumed by direnv. Authorize it
once with direnv allow; thereafter the environment loads automatically
whenever you cd into the project:
$ direnv allow
$ echo $PROJECT_ROOT
/home/user/projects/myproject
$ echo $PATH
/home/user/projects/myproject/packages/tools/bin:/home/user/projects/myproject/scripts:...
To run a single command in the project environment without an interactive
shell, use direnv exec:
$ direnv exec . pytest
Note
Windows: direnv evaluates packages.envrc with bash, so a bash
is required even under PowerShell. The supported setup is direnv +
git-bash (bundled with Git-for-Windows). For native PowerShell, add
Invoke-Expression "$(direnv hook pwsh)" to your $PROFILE; inside
git-bash or WSL use direnv normally.
Or for a single command:
$ direnv exec . echo \$PROJECT_ROOT
/home/user/projects/myproject
Project Paths
The paths section organizes project file paths by category for tools
to discover.
Path Organization
Paths are organized by:
Kind - High-level category (e.g.,
rtl,dv,docs)Type - Specific type within kind (e.g.,
vlog,sv,vhdl)
Basic Structure
Software project:
package:
name: web-service
paths:
src:
python:
- src/api
- src/workers
typescript:
- frontend/src
test:
python:
- test/unit
- test/integration
config:
yaml:
- deploy/k8s
- deploy/terraform
Hardware project:
package:
name: soc-design
paths:
rtl: # Kind: RTL source
vlog: # Type: Verilog
- rtl/common
- rtl/peripherals
sv: # Type: SystemVerilog
- rtl/cpu
- rtl/bus
dv: # Kind: Design verification
sv: # Type: SystemVerilog
- tb/agents
- tb/sequences
python: # Type: Python
- tb/models
Paths are relative to the project root (directory containing ivpm.yaml).
Common Path Categories
rtl - RTL source files:
vlog- Verilog filessv- SystemVerilog filesvhdl- VHDL files
dv - Design verification:
sv- SystemVerilog testbenchpython- Python testbenchc- C/C++ models
docs - Documentation:
rst- ReStructuredTextmd- Markdownpdf- PDF files
data - Data files:
testdata- Test vectorsconfig- Configuration files
src - Source code:
python- Python source filestypescript- TypeScript source filesgo- Go source files
test - Test suites:
python- Python teststypescript- TypeScript testsshell- Shell-based integration tests
config - Configuration and deployment:
yaml- YAML configuration filesjson- JSON configuration filestoml- TOML configuration files
Complete Paths Example
package:
name: uart-ip
paths:
# RTL source files
rtl:
sv:
- rtl/uart_core
- rtl/uart_tx
- rtl/uart_rx
vlog:
- rtl/uart_apb_if
# Verification
dv:
sv:
- tb/uart_agent
- tb/uart_monitor
- tb/sequences
python:
- tb/models
- tb/tests
# Documentation
docs:
rst:
- docs/source
md:
- docs/guides
# IP-XACT or other metadata
metadata:
ipxact:
- ip-xact/uart.xml
# Scripts
scripts:
python:
- scripts/build
shell:
- scripts/sim
Using Path Information
Tools can query path information via the ivpm pkg-info command:
# Get all RTL SystemVerilog paths
$ ivpm pkg-info paths -k rtl --type sv my-package
# Get all verification paths
$ ivpm pkg-info paths -k dv my-package
This enables tools like FuseSoC, simulators, and build systems to discover source files automatically.
Practical Examples
Example 1: Simulation Environment
package:
name: cpu-verification
env:
# Simulation variables
- name: SIM_ROOT
value: "${IVPM_PROJECT}"
- name: WORK_DIR
value: "${SIM_ROOT}/work"
- name: LOG_DIR
value: "${SIM_ROOT}/logs"
# Simulator paths
- name: PATH
path-prepend:
- "${IVPM_PACKAGES}/verilator/bin"
- "${IVPM_PACKAGES}/gtkwave/bin"
# Library paths for compiled libraries
- name: LD_LIBRARY_PATH
path:
- "${IVPM_PACKAGES}/lib"
- "${SIM_ROOT}/build/lib"
paths:
rtl:
sv:
- rtl/core
- rtl/cache
- rtl/mmu
dv:
sv:
- tb/top
- tb/agents
python:
- tb/tests
Usage:
$ ivpm update
$ direnv allow
$ cd $WORK_DIR
$ make sim
Example 2: Multi-Language Project
package:
name: mixed-project
env:
# Project structure
- name: HDL_ROOT
value: "${IVPM_PROJECT}/hdl"
- name: SW_ROOT
value: "${IVPM_PROJECT}/software"
# Compilation flags
- name: VLOG_FLAGS
value:
- "+incdir+${HDL_ROOT}/include"
- "-timescale=1ns/1ps"
- name: CFLAGS
value:
- "-I${SW_ROOT}/include"
- "-Wall"
# Tool configuration
- name: PYTHONPATH
path-prepend:
- "${SW_ROOT}/python"
- "${IVPM_PROJECT}/scripts"
paths:
rtl:
vlog:
- hdl/rtl
sv:
- hdl/interfaces
sw:
c:
- software/drivers
- software/firmware
python:
- software/python
Example 3: Team Development Setup
package:
name: team-project
env:
# Project info
- name: PROJECT_NAME
value: "TeamProject"
- name: PROJECT_VERSION
value: "1.0.0"
# Shared tools (from packages/)
- name: TOOL_ROOT
value: "${IVPM_PACKAGES}/tools"
- name: PATH
path-prepend:
- "${TOOL_ROOT}/bin"
- "${IVPM_PROJECT}/scripts"
# License servers
- name: LM_LICENSE_FILE
path:
- "27000@license-server-1"
- "27001@license-server-2"
# Output directories
- name: BUILD_DIR
value: "${IVPM_PROJECT}/build"
- name: REPORT_DIR
value: "${IVPM_PROJECT}/reports"
Best Practices
Use built-in variables (
IVPM_PROJECT,IVPM_PACKAGES) for portabilityDefine variables in order - reference order matters for expansion
Use path-prepend for tools - Ensure project tools override system tools
Document custom variables - Help team members understand the setup
Keep paths relative - Use
${IVPM_PROJECT}for portabilityGroup related variables - Organize by purpose (build, test, docs)
Test after changes - Always verify with
direnv exec . env
See Also
Getting Started with IVPM - Basic project setup
Core Concepts - Understanding IVPM’s model
Troubleshooting - Solutions to common problems
Package Handlers - How handlers process packages