External Stages

fud supports using stages that aren't defined in its main source tree. These are known as 'external stages' and the provide a mechanism for projects using Calyx to take advantage of fud. You can register an external stage with:

fud register stage_name -p /path/to/stage.py

Once an external stage is registered, it behaves exactly like any other stage.

You can remove an external stage with:

fud register stage_name --delete

The following defines a stage that transforms MrXL programs to Calyx programs.

from fud.stages import Stage, SourceType
from fud.utils import shell


class MrXLStage(Stage):
    """
    Stage that invokes the MrXL frontend.
    """

    name = "mrxl"

    def __init__(self):
        """
        Initialize this stage. Initializing a stage *does not* construct its
        computation graph.
        """
        super().__init__(
            src_state="mrxl",
            target_state="futil",
            input_type=SourceType.Path,
            output_type=SourceType.Stream,
            description="Compiles MrXL to Calyx.",
        )

    @staticmethod
    def defaults():
        """
        Specify defaults that should be added to fud's configuration file when
        this stage is registered.
        """
        return {"exec": "mrxl"}

    def _define_steps(self, input, builder, config):
        """
        Define the steps that will execute in this stage. Each step represents
        a delayed computation that will occur when the stage is executed.
        """

        # Commands at the top-level are evaluated when the computation is being
        # staged
        cmd = config["stages", self.name, "exec"]

        # Computations within a step are delayed from being executed until
        # the full execution pipeline is generated.
        @builder.step(description=cmd)
        def run_mrxl(mrxl_prog: SourceType.Path) -> SourceType.Stream:
            return shell(f"{cmd} {str(mrxl_prog)}")

        # Define a schedule using the steps.
        # A schedule *looks* like an imperative program but actually represents
        # a computation graph that is executed later on.
        return run_mrxl(input)


# Export the defined stages to fud
__STAGES__ = [MrXLStage]

External stages must define default values for configuration keys using the Stage.defaults() static method and the name of the stage using the static name field.

Stage Configuration

Like normal stages, external stages can have persistent configuration information saved using fud config.

To add persistent stage configuration, run:

fud config stages.<stage-name>.<key> <value>

To dynamically override the value of a field during execution, use the -s flag:

fud e -s <stage-name>.<key> <value> ...

The override order for stage configuration is:

  1. Dynamic values provided by -s.
  2. Configuration value in the fud config.
  3. Default value provided by Stage.defaults()