ESP Support

CHIA drives ESP (Embedded Scalable Platforms, Columbia SLD) flows through chia.esp. Every ESP flow is a make target run from a per-board working directory; a single EspWorkspaceNode models one such workspace, with a typed member per flow (configure, build, sim, accgen, accel, synth, fpga_program, fpga_run) plus generic primitives (make / put_file / remove / collect). All members share one placement so the path-based state a flow leaves behind is visible to the next.

The notes below cover what a worker needs to run these flows correctly; the api reference follows.

The worker

An ESP worker is built on ESP’s own container image, which supplies the OS dependencies, the RISC-V / SPARC cross-toolchains, and the socgen Python environment; CHIA is layered on top as a self-contained interpreter. Two consequences shape how everything else is set up:

  • No CAD tools live in the image. Simulation, HLS, and bitstream flows need the host’s tool installs bind-mounted into the container, with the matching license environment variables set. Only the license-free flows (configuration, software builds, the RTL accelerator flow) run with no mounts at all — a good first target when validating a new worker.

  • socgen needs the image’s Python, not CHIA’s. ESP’s socgen relies on pre-3.10 tkinter behavior (plus Pmw), so configure runs in the container even when other stages run elsewhere. Do not expect it to work against the CHIA interpreter.

Keep site-specific values — hostnames, install paths, license servers — out of committed cluster configuration. Parameterize the configuration with environment variables resolved at load time, and source the real values from an uncommitted file, so the configuration itself stays portable.

Simulation

sim runs a full-SoC RTL simulation. The worker needs the simulator (and, once per checkout, Vivado to compile the vendor simulation libraries) bind- mounted with its license environment. Three things that commonly trip a first run:

  • Point XILINX_VIVADO at the real Vivado install root. ESP’s image stubs it, which mangles the paths the simulation flow compiles.

  • Judge success by a transcript match, not exit code — an RTL simulation can exit cleanly without the program passing. sim takes a pass_pattern for this (ESP’s testbench prints a fixed end-of-run message).

  • After reconfiguring the SoC, run sim(clean=True) once. The simulator’s incremental rebuild fails on units compiled against the previous SoC map.

Vivado and the FPGA flow

Important

If you plan to run Vivado, keep the ESP checkout on the host and bind- mount it into the container, rather than synthesizing inside the container. Vivado’s multi-process synthesis (notably the DDR4 memory- controller IP) hangs inside ESP’s older container userland. The reliable arrangement:

  • Keep the ESP checkout on the host and bind-mount it into the worker container at the identical path. Vivado writes absolute paths into its project, so the host and the container must agree on where the workspace lives; pass that path as esp_root to every member.

  • Run synth on a worker that has Vivado and the host userland (a bare host worker, e.g. the cluster head), separate from the container that runs configure and build. Because both see the one shared workspace, they cooperate on the same tree — the container compiles the software and generates the RTL, the host synthesizes it.

Other FPGA-flow facts worth knowing:

  • Vendor IP versions are pinned per board. ESP pins exact Xilinx IP versions in its board constraints. A Vivado whose catalog has moved on fails at IP creation; adjust the pin in your checkout, or synthesize with an era-matched Vivado. No single value suits every Vivado release.

  • Match the hw_server version. Programming connects a Vivado client to a hw_server on the machine holding the JTAG cable, and the server only accepts clients at or below its own version. synth and fpga_program each take a vivado_bin override, so you can synthesize with one Vivado and program with an older, server-compatible one.

  • Programming is fully networked. fpga_program reaches hw_server over TCP; the worker needs reachability to it (a direct route or a tunnel), never the cable itself.

  • The run leg is EDCL over UDP. fpga_run loads the SoC over its Ethernet via ESPLink, so the worker needs a UDP route to the board’s IP (set in the SoC configuration). If that UDP is relayed, note that ESP’s EDCL only answers requests whose source port is the ESPLink port (a relay must preserve it), and that UDP cannot ride an SSH tunnel — a point-to- point board segment needs a relay on the cabled host or a scoped firewall opening.

  • The console is read over TCP. fpga_run scrapes a TCP-exposed serial port for its pass_pattern. Identify which serial channel is the console, and at what baud, for your board.

Resources as license seats

CHIA models tool licenses and scarce hardware as Ray resources, so the scheduler does admission control instead of letting tools fail at checkout. Advertise capacity on the workers that can satisfy each, and give members the matching demand:

Resource

Held by / meaning

esp

any ESP-capable worker (config, software, RTL flow)

esp_xcelium

simulator seats — capacity = concurrent sims admitted

esp_vivado

Vivado synthesis seats (advertise on the host worker)

esp_fpga

an attached board — capacity 1 serializes access

API reference

Generated from the source docstrings, so it stays in sync with the code.

State definitions

chia.esp.state_def — result/artifact dataclasses for the ESP nodes.

ESP (Embedded Scalable Platforms, Columbia SLD; github.com/sld-columbia/esp) drives everything through make targets run from a per-board working directory <esp_root>/socs/<board>/, and that directory is the state: config, generated RTL, and software outputs accumulate in place, with later targets reading what earlier ones wrote. These artifacts therefore mostly describe what happened on the worker; small binaries ship by value and anything over a caller-set cap stays in the workspace.

class chia.esp.state_def.EspMakeResult(success: bool, returncode: int, target: str, work_dir: str, stdout: str, stderr: str, listing: dict[str, int]=<factory>)[source]

Bases: object

One generic ESP make-target run.

class chia.esp.state_def.EspCollectResult(base_dir: str, files: dict[str, str], skipped: dict[str, int], listing: dict[str, int])[source]

Bases: object

Text files fetched by value from a workspace.

class chia.esp.state_def.EspConfigResult(success: bool, returncode: int, board_dir: str, esp_config: str, stdout: str, stderr: str)[source]

Bases: object

One headless socgen run (make esp-config).

class chia.esp.state_def.EspAccelSpec(name: str, flow: Literal['rtl', 'vivado', 'stratus', 'catapult']='rtl', device_id: str = '', answers_tail: list[str] = <factory>)[source]

Bases: object

Inputs for one accgen.sh run (the script’s prompts, in order).

property make_name: str

Name in per-accelerator make targets (<make_name>-hls, …): the skeleton directory’s basename, not the bare accelerator name.

property acc_dir: str

Skeleton directory relative to the ESP root.

to_answers() str[source]

Render the newline-separated stdin script accgen.sh consumes.

class chia.esp.state_def.EspAccgenResult(success: bool, returncode: int, acc_dir: str, listing: dict[str, int], stdout: str, stderr: str)[source]

Bases: object

One accgen.sh run: a generated accelerator skeleton.

class chia.esp.state_def.EspAccelResult(success: bool, returncode: int, name: str, action: str, stdout: str, stderr: str)[source]

Bases: object

One per-accelerator make target (<name>-hls, <name>-baremetal, …).

class chia.esp.state_def.EspSimResult(success: bool, returncode: int, board_dir: str, test_program: str | None, pass_matched: bool | None, stdout: str, stderr: str)[source]

Bases: object

One full-system RTL simulation (make xmsim).

class chia.esp.state_def.EspSynthResult(success: bool, returncode: int, board_dir: str, bitstream: str | None, reports: dict[str, str], stdout: str, stderr: str)[source]

Bases: object

One FPGA synthesis run (make vivado-syn).

class chia.esp.state_def.EspFpgaRunResult(success: bool, returncode: int, board_dir: str, pass_matched: bool | None, uart: str, stdout: str, stderr: str)[source]

Bases: object

One software run on the programmed FPGA (make fpga-run[-linux]) with the UART console captured over TCP.

class chia.esp.state_def.EspSoftArtifact(target: Literal['soft', 'linux'], cpu: str, board: str, success: bool, binaries: dict[str, bytes], kept: dict[str, int], soft_build_dir: str, missing: list[str], stdout: str, stderr: str, returncode: int)[source]

Bases: object

ESP software build outputs (make soft / make linux) for one SoC.

Outputs land in <board_dir>/soft-build/<cpu>/ on the worker; files at or under the build’s inline cap ship by value in binaries, larger ones (normally just linux.bin) are recorded in kept and stay in the workspace.

Workspace node

chia.esp.esp_workspace — one node class for ESP make flows.

ESP exposes every flow as a make target run from a working directory — <esp_root>/socs/<board>/ for full-SoC targets, an accelerators/ subdir for per-accelerator ones. That directory is PATH-BASED state on the worker: later targets read what earlier ones wrote, so chained targets (esp-config -> soft -> sim) and file fetches must land on the SAME worker.

EspWorkspaceNode models exactly that: one instance = one workspace, pinned to one placement-group bundle. Its members are all stateless per-call functions — generic primitives (make / put_file / remove / collect) plus one typed member per ESP flow (configure, build, sim, accgen, accel; FPGA members to come). EspWorkspaceNode.<fn>.chia_remote (the class attribute) is the raw, unpinned form for callers that handle placement themselves.

Workers are assumed ESP-ready (toolchains on PATH); use the env argument for per-call overrides.

chia.esp.esp_workspace.board_dir(esp_root: str, board: str) str[source]

Absolute path of the per-board working directory socs/<board>.

chia.esp.esp_workspace.with_acc_tile(config_text: str, acc: str, row: int, col: int, impl: str = 'basic_dma64', has_l2: int = 0, vendor: str = 'sld') str[source]

Return config_text with tile (row, col) replaced by an accelerator.

Rewrites the TILE_<row>_<col> line (keeping its tile index) to ... acc <ACC> 0 0 0 <impl> <has_l2> <vendor> and points the matching POWER_ line’s first field at the accelerator. socgen identifies accelerators by their tech-library subdirectory name UPPERCASED (an unknown name silently becomes an empty tile), so acc should be the make name (e.g. “chiatest_rtl”) and is uppercased here. impl must be an implementation point whose DMA width matches the SoC’s (64 for the RISC-V CPUs), or socgen filters it out.

Raises ValueError when the tile or power line is absent.

class chia.esp.esp_workspace.EspWorkspaceNode(placement_group=None, require_colocated: bool = True, *, bundle_index: int = 0, reserve_bundle: dict | None = None, pg_strategy: str = 'STRICT_PACK', wait_for_pg: bool = True, pg_ready_timeout_s: float | None = None)[source]

Bases: ColocatedNode

One ESP workspace: all its flow members share one placement.

The members are @staticmethod @ChiaFunction(resources={"esp": 1}); __init__ re-binds each into a per-instance pinned form so node.<fn>.chia_remote(...) lands on this node’s bundle:

with EspWorkspaceNode() as ws:        # reserves {"CPU": 1, "esp": 1}
    root, board = "/home/espuser/esp", "xilinx-vc707-xc7vx485t"
    cfg = get(ws.configure.chia_remote(
        root, board,
        esp_config_path=f"{root}/socs/defconfig/esp_{board}_defconfig"))
    soft = get(ws.build.chia_remote(root, board, cpu="ariane"))
    outs = get(ws.collect.chia_remote(
        board_dir(root, board), ["soft-build/**/*.log"]))

Set up placement and bind the member functions.

Parameters:
  • placement_group – an existing Ray PlacementGroup to schedule onto. If given, require_colocated is moot (placement is already fixed) and this node will not remove the PG on close.

  • require_colocated – when no PG is given, reserve one so all members co-locate. When False, leave placement to the caller.

  • bundle_index – which bundle of the (given or reserved) PG to pin to.

  • reserve_bundle – resource shape of a self-reserved bundle (default _DEFAULT_BUNDLE). A bundle too small for some members is allowed — those members just can’t dispatch through this node (a construction-time warning lists them).

  • pg_strategy – placement strategy for a self-reserved PG.

  • wait_for_pg – block on pg.ready() for a self-reserved PG so the node is usable immediately.

  • pg_ready_timeout_s – optional timeout for that wait.

static make(work_dir: str, target: str, make_vars: dict[str, str] | None = None, jobs: int = 1, env: dict[str, str] | None = None, timeout_seconds: int = 86400, list_dir: str | None = None) EspMakeResult[source]

Run one make -C <work_dir> <target> on a worker.

The generic escape hatch behind the typed members.

Parameters:
  • work_dir – Directory to run make in.

  • target – Any ESP Makefile target: “esp-config”, “soft”, “linux”, “sim”, “vivado-syn”, “<acc>-hls”, …

  • make_vars – Makefile variables appended to the command line, e.g. {"TEST_PROGRAM": "./soft-build/ariane/baremetal/fft.exe"}.

  • jobs – make -j level.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; the make tree is killed and returncode=-1 returned on expiry.

  • list_dir – When given, listing manifests this directory after the run. Opt-in because a full board dir is a large tree.

static put_file(base_dir: str, relpath: str, content: bytes | str) str[source]

Write content to <base_dir>/<relpath> on this worker.

Parent directories are created; relpath may not escape base_dir (ValueError). Dispatch via the pinned instance member so the write lands on the workspace’s worker. Returns the absolute path written.

static remove(base_dir: str, relpath: str) bool[source]

Delete <base_dir>/<relpath> (file or directory tree).

Workspaces are stateful, and some generated state must be scrubbed rather than rebuilt over (e.g. stale HLS project outputs a re-run would silently re-install). relpath may not escape base_dir (ValueError). Returns whether the path existed.

static collect(base_dir: str, patterns: list[str], max_bytes_per_file: int | None = None) EspCollectResult[source]

Fetch text files from a previous make’s working dir on this worker.

Dispatch via the pinned instance member so it lands on the worker that owns the files.

Parameters:
  • base_dir – Directory a previous target ran in.

  • patterns – Globs relative to base_dir (** is recursive), e.g. ["soft-build/**/*.log", "socgen/esp/.esp_config"]. Files matched by multiple patterns appear once.

  • max_bytes_per_file – When set, files over this size are recorded in skipped instead of shipped through the object store — protects against a glob accidentally matching linux.bin. None (and 0, the falsy edge) means no cap.

static configure(esp_root: str, board: str, esp_config: str | None = None, esp_config_path: str | None = None, make_vars: dict[str, str] | None = None, env: dict[str, str] | None = None, timeout_seconds: int = 1800) EspConfigResult[source]

Configure the SoC: write .esp_config, run make esp-config.

Headless socgen. The config is written where the board Makefile actually reads it — socgen/esp/.esp_config (ESP_CFG_BUILD) under the board dir; when that file is absent ESP silently seeds it from the board’s defconfig (socs/defconfig/esp_<board>_defconfig), ignoring any config placed elsewhere. Exactly one of esp_config / esp_config_path must be given.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • esp_config – Full text of the .esp_config to configure with.

  • esp_config_path – Worker-side path of an existing config to copy in instead.

  • make_vars – Extra Makefile variables for the esp-config run.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; returncode=-1 on expiry.

Returns:

EspConfigResult echoing the config text actually used.

Raises:
  • ValueError – If neither or both config sources are given.

  • FileNotFoundError – If esp_config_path does not exist on the worker, or socs/<board> is not a directory.

static build(esp_root: str, board: str, cpu: str = 'ariane', target: Literal['soft', 'linux'] = 'soft', smp: bool | None = None, make_vars: dict[str, str] | None = None, jobs: int = 16, env: dict[str, str] | None = None, timeout_seconds: int = 7200, inline_max_bytes: int = 16777216) EspSoftArtifact[source]

Build ESP software (make soft / make linux) and read back its canonical outputs.

License-free; requires a configured SoC (the .esp_config decides the CPU the cross-toolchain targets), so run configure() on this workspace first.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • cpu – Processor tile the SoC was configured with (“ariane”, “ibex”, or “leon3”) — names the soft-build/<cpu> output directory. If that directory is missing after a successful make but exactly one soft-build/* subdir exists, that one is used (with a warning).

  • target"soft" (bare-metal prom.bin + systest.bin) or "linux" (linux.bin).

  • smp – When set, passed as SMP=1 / SMP=0 on the make command line, overriding the board Makefile’s setting. None leaves the Makefile default.

  • make_vars – Any other Makefile variables; appended after smp so they win on conflict.

  • jobs – make -j level.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit — make linux compiles a kernel + root fs, so give it hours, not minutes.

  • inline_max_bytes – Outputs at or under this size ship by value in binaries; larger ones are recorded in kept and stay at soft_build_dir on the worker.

Returns:

EspSoftArtifact; success iff make exited 0 AND every canonical output exists, else missing names what the build failed to produce.

Raises:

ValueError – If target is not a recognized value.

static sim(esp_root: str, board: str, test_program: str | None = None, sim_input: str | None = None, pass_pattern: str | None = None, clean: bool = False, make_vars: dict[str, str] | None = None, jobs: int = 1, env: dict[str, str] | None = None, timeout_seconds: int = 14400) EspSimResult[source]

Run a full-system RTL simulation (make xmsim, Xcelium).

Compiles the configured SoC’s RTL into the workspace’s xcelium/ work library (incremental on repeat runs) and simulates the bare-metal software. Requires configure() and a licensed Xcelium (plus Vivado for the one-time Xilinx simlib compile) on the worker; demands the esp_xcelium resource, so dispatch through a node whose bundle includes it, e.g. EspWorkspaceNode(reserve_bundle={"CPU": 1, "esp": 1, "esp_xcelium": 1}).

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • test_program – Worker-side path of the bare-metal ELF to simulate, passed as TEST_PROGRAM= (the make dependency chain regenerates the boot srecs from it). None runs the default systest.

  • sim_input – Full text for xcelium/xmsim.in, the simulator’s batch input script. Defaults to XMSIM_BATCH_INPUT (severity settings + run + exit); override to bound the run (run 10 ms) or add tracing commands.

  • pass_pattern – Regex searched in the console transcript; when given, success additionally requires a match (RTL sims can end with exit code 0 without the test passing).

  • clean – Run make xmsim-distclean first, discarding the compiled work library. Needed after an SoC reconfiguration: Xcelium’s incremental rebuild fails on units compiled against the previous socmap (DLCSMD checksum mismatches).

  • make_vars – Any other Makefile variables.

  • jobs – make -j level (RTL compile benefits).

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit for compile + simulate; the backstop for a testbench that never terminates.

Returns:

EspSimResult; success iff make exited 0 and, when pass_pattern was given, it matched.

Raises:

FileNotFoundError – If socs/<board> is not a directory.

static accgen(esp_root: str, spec: EspAccelSpec, overwrite: bool = False, env: dict[str, str] | None = None, timeout_seconds: int = 600) EspAccgenResult[source]

Generate an accelerator skeleton (tools/accgen/accgen.sh).

accgen is an interactive prompt sequence; this drives it by piping spec.to_answers() on stdin (empty answers take its defaults). The skeleton lands in <esp_root>/<spec.acc_dir>: hardware implementations, the accelerator XML, and bare-metal/Linux software.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • spec – The accgen prompt answers.

  • overwrite – accgen refuses to regenerate an existing skeleton; True deletes spec.acc_dir first (idempotent reruns).

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; returncode=-1 on expiry.

Returns:

EspAccgenResult; success iff accgen exited 0 and the skeleton directory exists.

static accel(esp_root: str, board: str, name: str, action: str, make_vars: dict[str, str] | None = None, jobs: int = 16, env: dict[str, str] | None = None, timeout_seconds: int = 3600) EspAccelResult[source]

Run one per-accelerator make target: make <name>-<action>.

Common actions: hls (synthesize the kernel — or, for the RTL flow, just package it — and install the implementation points into the tech library so socgen can instantiate the tile), baremetal (the generated self-test program, output under soft-build/<cpu>/baremetal/), driver/app (Linux pieces).

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • name – The accelerator’s make name — its skeleton directory basename, e.g. “chiatest_rtl” (EspAccelSpec.make_name).

  • action – Target suffix; unknown ones fail in make, not here.

  • make_vars – Any other Makefile variables.

  • jobs – make -j level.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; returncode=-1 on expiry.

static synth(esp_root: str, board: str, top: str = 'top', overwrite_project: bool = False, vivado_bin: str | None = None, make_vars: dict[str, str] | None = None, jobs: int = 1, env: dict[str, str] | None = None, timeout_seconds: int = 21600, report_max_bytes: int = 262144) EspSynthResult[source]

Synthesize the configured SoC to a bitstream (make vivado-syn).

A batch Vivado implementation run — hours of wall clock for the larger parts. The bitstream stays in the workspace (linked as <top>.bit in the board dir); the implementation reports Vivado writes alongside it ship back by value.

Demands only esp_vivado (a Vivado seat), not esp — synthesis needs Vivado and the generated RTL, not the ESP cross-toolchains, so it can run on a Vivado-only worker (e.g. bare host) separate from the container that runs configure/build. When it does, that worker and the container must see the workspace at the SAME path (Vivado writes absolute paths into its project), so pass the shared-workspace path as esp_root to every member.

ESP’s project-setup recipe re-runs on every invocation and asks interactively whether to overwrite an existing Vivado project — a headless run would hang on it forever, so the answer is piped in: “n” (reuse the project) unless overwrite_project.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • top – The design’s top module (the board Makefile’s TOP), naming the bitstream link.

  • overwrite_project – Regenerate the Vivado project instead of reusing it. Needed when the SoC’s source list changed (e.g. after adding an accelerator and reconfiguring); a plain RTL edit does not need it. Vivado projects don’t open across versions, so also pass it when vivado_bin changed.

  • vivado_bin – When given, a Vivado bin dir prepended to PATH for this run — the synthesis Vivado’s IP catalog must carry the versions the board’s scripts pin, which may rule out the newest install.

  • make_vars – Any other Makefile variables.

  • jobs – make -j level (the Vivado run manages its own threads).

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; returncode=-1 on expiry.

  • report_max_bytes – Per-report cap; larger reports are skipped.

Returns:

EspSynthResult; success iff make exited 0 AND the bitstream exists.

static fpga_program(esp_root: str, board: str, fpga_host: str = 'localhost', hw_server_port: int = 3121, vivado_bin: str | None = None, make_vars: dict[str, str] | None = None, env: dict[str, str] | None = None, timeout_seconds: int = 1800) EspMakeResult[source]

Program the FPGA with the workspace bitstream (make fpga-program).

Fully network-based: connects to a Xilinx hw_server at fpga_host:hw_server_port (which runs on whatever machine holds the JTAG cable) and streams the bitstream through it.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • fpga_host – Host running hw_server, as reachable from the worker.

  • hw_server_port – hw_server’s TCP port.

  • vivado_bin – When given, a Vivado bin dir prepended to PATH for this run — hw_server only accepts clients at or below its own version, which may rule out the synthesis Vivado.

  • make_vars – Any other Makefile variables.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit; returncode=-1 on expiry.

static fpga_run(esp_root: str, board: str, uart_host: str, uart_port: int, esplink_ip: str, linux: bool = False, dram_image: str | None = None, prom_image: str | None = None, pass_pattern: str | None = None, uart_timeout_seconds: int = 600, esplink_port: int | None = None, make_vars: dict[str, str] | None = None, env: dict[str, str] | None = None, timeout_seconds: int = 1800) EspFpgaRunResult[source]

Load and start software on the programmed FPGA and watch the UART.

Loads PROM + a payload into the running SoC over its Ethernet (ESPLink, EDCL/UDP to esplink_ip), then watches the console for a verdict. The board executes asynchronously, so a TCP connection to the UART (a ser2net- or socat-style bridge at uart_host:uart_port) is opened BEFORE the load and read until pass_pattern matches or uart_timeout_seconds passes.

By default this runs make fpga-run[-linux], which loads the generic systest/Linux image. To run a specific program — e.g. an accelerator’s bare-metal self-test, which the make targets can’t load — pass dram_image: esplink is built and the reset/PROM/DRAM/reset sequence is driven directly with that image.

Parameters:
  • esp_root – ESP checkout root on the worker.

  • board – Board working-directory name under socs/.

  • uart_host – Host of the TCP-exposed UART console.

  • uart_port – Its TCP port.

  • esplink_ip – The SoC’s EDCL IP (a socgen config field), as reachable from the worker.

  • linux – Load linux.bin (fpga-run-linux) instead of the bare-metal systest.bin. Ignored when dram_image is set.

  • dram_image – Worker-side path of a program image to load into DRAM instead of systest — the direct-esplink path.

  • prom_image – PROM image for the direct path; defaults to the sole soft-build/**/prom.bin in the workspace.

  • pass_pattern – Regex searched in the UART transcript; when given, success additionally requires a match.

  • uart_timeout_seconds – How long to keep reading the console after the load, absent a match.

  • esplink_port – Override the SoC’s EDCL UDP port.

  • make_vars – Any other Makefile variables.

  • env – Extra environment variables layered over the worker’s.

  • timeout_seconds – Wall-clock limit for the load.