Skip to content

Latest commit

 

History

History
270 lines (210 loc) · 9.12 KB

File metadata and controls

270 lines (210 loc) · 9.12 KB

Google XLS HLS Flow

This tutorial runs the built-in DSLX dataset through Google XLS, explains the generated artifacts and metrics, and shows how to add a custom function or stateful proc.

Prerequisites

Install HLSFactory and an XLS build containing these executables:

  • ir_converter_main
  • opt_main
  • codegen_main

Set HLSFACTORY_XLS_PATH to the installation root:

export HLSFACTORY_XLS_PATH=/path/to/xls

On the HLSFactory server, use:

export HLSFACTORY_XLS_PATH=/usr/scratch/common/xls

The flow accepts release bundles with executables at the installation root and source builds with executables below bazel-bin/xls/. You can check a release bundle directly with:

$HLSFACTORY_XLS_PATH/ir_converter_main --version
$HLSFACTORY_XLS_PATH/opt_main --version
$HLSFACTORY_XLS_PATH/codegen_main --version

Also set a writable work directory in .env:

HLSFACTORY_WORK_DIR=/absolute/path/to/hlsfactory_work

HLSFACTORY_XLS_PATH is read from the process environment. If you also record it in .env for convenience, export that file's values before starting Python; HLSFactory does not currently load this particular setting from .env.

Load the Built-In Dataset

The test_designs_xls dataset contains 11 small designs spanning arithmetic, arrays, loops, parametric functions, structs, pattern matching, bit operations, pipeline and combinational codegen, stateful procs, and a proc that calls pure helper functions.

from hlsfactory.datasets_builtin import dataset_test_designs_xls_builder
from hlsfactory.utils import get_work_dir, remove_and_make_new_dir_if_exists

work_dir = get_work_dir() / "xls_tutorial"
remove_and_make_new_dir_if_exists(work_dir)

dataset = dataset_test_designs_xls_builder(
    "test_designs_xls",
    work_dir,
)
datasets = {dataset.name: dataset}

The builder copies the packaged sources into the work directory. XLS and HLSFactory outputs are written into those copies, leaving the packaged dataset unchanged.

Run Synthesis

Construct the flow from HLSFACTORY_XLS_PATH and synthesize the dataset:

from hlsfactory.flow_xls import XLSHLSSynthFlow

flow = XLSHLSSynthFlow()
results = flow.execute_multiple_design_datasets_fine_grained_parallel(
    datasets,
    copy_dataset=False,
    n_jobs=4,
    timeout=12 * 60,
)

An explicit installation directory overrides the environment and server default:

flow = XLSHLSSynthFlow(xls_install_dir="/path/to/xls")

For each design, the flow performs three stages:

  1. DSLX to XLS IR with ir_converter_main.
  2. Standard IR optimization with opt_main.
  3. Pipeline or combinational RTL generation with codegen_main.

Validator Smoke Test

From the repository root, validate every packaged design with:

export HLSFACTORY_XLS_PATH=/usr/scratch/common/xls
uv run python tests/dataset_validator.py \
    hlsfactory/hls_dataset_sources/test_designs_xls \
    --flow XLSHLSSynthFlow \
    -j 4

The validator copies the dataset under $HLSFACTORY_WORK_DIR/dataset_validator/, runs each design independently, and fails if the flow produces no successful designs.

Configuration

A feed-forward pipelined function can use:

design_name = "adder"
dataset_name = "my_xls_dataset"

[[flow_configs]]
flow_name = "XLSHLSSynthFlow"
dslx_file = "adder.x"
top = "add"
generator = "pipeline"
pipeline_stages = "1"
delay_model = "unit"

For combinational RTL, set generator = "combinational" and omit pipeline_stages, delay_model, and reset.

Stateful procs use the same pipeline generator and normally require a reset:

[[flow_configs]]
flow_name = "XLSHLSSynthFlow"
dslx_file = "running_sum_proc.x"
top = "RunningSum"
generator = "pipeline"
pipeline_stages = "1"
delay_model = "unit"
reset = "rst"

Generated Artifacts

For a DSLX file named adder.x, a successful run produces:

File Description
adder.ir IR produced directly from DSLX
adder.opt.ir Optimized IR passed to codegen
adder.v Synthesizable Verilog/SystemVerilog
adder.signature.textproto Module ports, channels, reset, pipeline latency, and II
adder.block_metrics.textproto Flop count, estimated path delays, feedthrough status, and operation BOM
adder.interface.pb Binary DSLX interface metadata passed into codegen
adder.interface.textproto Human-readable DSLX interface metadata
adder.ir_converter_options.textproto Effective converter configuration
adder.optimizer_options.textproto Effective optimizer configuration
adder.scheduling_options.textproto Effective scheduling configuration
adder.codegen_options.textproto Effective codegen configuration
adder.schedule.textproto Pipeline stages, timed nodes, and minimum estimated period; pipeline designs only
adder.scheduled.ir Post-scheduling IR
adder.block.ir Lowered block IR with ports and registers
adder.verilog_line_map.textproto DSLX-to-Verilog source-line mapping
adder.optimization_pass_metrics.textproto Optimizer pass timing and transformations
adder.scheduling_pass_metrics.textproto Scheduling pass timing and transformations
adder.codegen_pass_metrics.textproto Codegen pass timing and transformations
data_hls.json Parsed settings, artifact names, and synthesis metrics
execution_data.json Runtime, CPU, and completion status when logging is enabled

Failures create error__XLSHLSSynthFlow.txt; timeouts create timeout__XLSHLSSynthFlow.txt. Failed designs return no output design from the flow.

Output Data

data_hls.json contains:

Metric group Fields
Design and configuration dslx_file, top, generator, pipeline_stages, delay_model, reset
Schedule latency_cycles, initiation_interval
Structure flop_count, feedthrough_path_exists
Estimated timing metrics_delay_model, max_reg_to_reg_delay_ps, max_input_to_reg_delay_ps, max_reg_to_output_delay_ps, max_feedthrough_path_delay_ps
Operations operation_counts, operation_kind_counts
Artifacts Paths for IR, RTL, interfaces, signature, schedule, line map, option snapshots, pass metrics, block metrics, and enabled debug outputs

Read selected results with standard Python:

import json

for design in results["test_designs_xls"].designs:
    data = json.loads((design.dir / "data_hls.json").read_text())
    print(
        design.name,
        data["latency_cycles"],
        data["initiation_interval"],
        data["flop_count"],
    )

Pipeline latency and II are parsed from the generated module signature rather than inferred from pipeline_stages. XLS may add input and output registers, so these values can differ. Combinational modules have no cycle-based signature; their latency and II fields are therefore null.

Block-metrics delays are XLS estimates. With the default unit model, they are not technology-specific timing. Operation/BOM counts and flop counts describe the generated block, but they are not FPGA resource utilization or standard-cell area. Physical area and post-route timing require a separate implementation flow with a target device or cell library.

Optional Debug Artifacts

Interface metadata, effective option snapshots, scheduled and block IR, source-line maps, and optimization/scheduling/codegen pass metrics are generated by default. Pipeline designs also receive a schedule textproto; combinational designs record schedule_file as null.

The much larger compiler dumps and profiles remain opt-in:

[[flow_configs]]
flow_name = "XLSHLSSynthFlow"
dslx_file = "adder.x"
top = "add"
generator = "pipeline"
pipeline_stages = "1"
delay_model = "unit"
dump_optimizer_ir = "true"
dump_codegen_ir = "true"
profile_passes = "true"

dump_optimizer_ir creates <source-stem>.optimizer_ir_dumps/, while dump_codegen_ir creates <source-stem>.codegen_ir_dumps/. profile_passes creates separate optimizer and codegen .pprof files. A trivial adder can produce hundreds of optimizer snapshots, so these settings are intended for compiler debugging rather than routine dataset generation.

See the official codegen options, scheduling, and delay estimation documentation for the meaning of these reports and scheduling controls.

Add a Custom Design

Create one directory containing the DSLX source and configuration:

my_design/
    kernel.x
    hlsfactory.toml

Load it directly with Design.from_dir_with_config() or place several such directories under a dataset root and use DesignDataset.from_dir(). No Tcl entry point is required. Use the packaged adder, running_sum_proc, and packet_checksum_proc directories as function, proc, and mixed proc/function examples.