144  CIRCT ssp Dialect

144.1 Beginner Summary

The CIRCT ssp dialect represents static scheduling problem instances and their solutions. SSP stands for Static Scheduling Problems. It is a compact MLIR format for describing the abstract problems handled by CIRCT’s scheduling infrastructure: operations, dependences, operator types, resource types, resource limits, latencies, initiation intervals, and scheduled start times.

For a beginner, the important distinction is that ssp is not a hardware IR like hw, comb, seq, or firrtl. It is a problem-description dialect. It lets CIRCT store, print, test, benchmark, roundtrip, and schedule problem instances without needing the original source dialect that produced them.

A typical SSP instance looks like this:

ssp.instance @example of "ModuloProblem" [II<3>] {
  library {
    operator_type @Memory [latency<1>]
    operator_type @Add [latency<1>]
  }
  resource {
    resource_type @ReadPort [limit<1>]
  }
  graph {
    %0 = operation<@Memory>() uses[@ReadPort] [t<0>]
    %1 = operation<@Add>(%0) [t<1>]
  }
}

That IR is not saying “emit this hardware.” It is saying “this is a scheduling problem, here are the nodes and constraints, and here is the schedule or partial schedule attached as properties.”

144.2 Why This Dialect Exists

CIRCT has a dialect-independent C++ scheduling infrastructure. That infrastructure can be used by high-level synthesis flows, lowering flows, or other compiler components that need static scheduling. However, a C++ API is not itself a convenient file format.

The ssp dialect fills that gap. It gives scheduling problems a textual MLIR representation that can be checked into tests, generated by tools, shared for benchmarks, and loaded back into the scheduler. The rationale document describes three main use cases: testing, benchmarking, and rapid prototyping.

The dialect is especially useful because scheduling is a hard optimization problem. Different algorithms can produce different schedules, take different amounts of time, or support different constraints. A self-contained SSP file can be used as a benchmark input without requiring the original HLS frontend, private source IR, or full lowering pipeline.

144.3 When It Matters

You will see ssp when working on CIRCT’s scheduling layer itself, rather than ordinary hardware lowering. It matters when:

  • testing scheduling problem definitions, input checkers, and solution verifiers;
  • comparing scheduling algorithms on the same instance;
  • dumping a scheduling problem from another flow for debugging;
  • creating small handwritten scheduler examples;
  • converting between ssp.instance and circt::scheduling::Problem;
  • preserving a schedule using properties such as t<...> or z<...>.

The dialect is not meant to replace direct scheduling integration in production clients. The rationale is explicit that clients such as HLS flows should usually use the C++ scheduling APIs directly. SSP is the import/export and experiment format around that infrastructure.

144.4 Core Model

An SSP instance has three main parts.

ssp.library contains ssp.operator_type declarations. An operator type describes a kind of operation in the target problem model, such as memory, addition, multiplication, or an implicit node. Operator types can carry properties such as latency, incoming delay, or outgoing delay.

ssp.resource contains ssp.resource_type declarations. A resource type describes a constrained resource, such as a read port, write port, functional unit, or shared operator pool. Resource types can carry properties such as a usage limit.

ssp.graph contains ssp.operation nodes. Operations form the dependence graph that the scheduler must schedule. Def-use dependences are represented with MLIR SSA operands and results. Auxiliary dependences are represented with symbol references to named operations. This split is important: the CIRCT scheduling infrastructure already treats SSA def-use edges as dependences, so auxiliary edges must be stored separately to avoid double counting.

Properties are dialect attributes stored on instances, operations, operator types, resource types, or dependences. They connect the textual IR to concrete C++ problem classes such as Problem, CyclicProblem, SharedOperatorsProblem, ModuloProblem, ChainingProblem, and ChainingCyclicProblem.

144.5 Complete Operation Inventory

The current ssp dialect defines seven operations:

ssp.graph
ssp.instance
ssp.library
ssp.operation
ssp.operator_type
ssp.resource
ssp.resource_type

ssp.instance is the top-level scheduling problem container. It has a problem name string, optional symbol name, optional problem properties, and a single body. In the normal structured form, that body contains a library, a resource library, and a graph.

ssp.library is a symbol table container for operator types. It can appear inside an instance or stand alone so multiple instances can refer to the same operator library.

ssp.operator_type declares an operator type symbol and its properties. Examples include latency<1>, incDelay<...>, and outDelay<...>, depending on the scheduling problem class.

ssp.resource is a symbol table container for resource types. It can also be stand-alone, which is useful when resource descriptions are shared.

ssp.resource_type declares a resource type symbol and its properties. The most visible built-in resource property is limit<...>.

ssp.graph contains the operations that make up the dependence graph for an instance.

ssp.operation is a scheduling node. It can have zero or more none-typed SSA operands, zero or more none-typed SSA results, an optional symbol name, optional auxiliary dependences, and optional properties. Its custom syntax puts the linked operator type near the operation keyword and resource uses in a uses[...] clause.

144.6 Attributes And Properties

The dialect defines #ssp.dependence, an internal dependence-edge attribute. It records an operand index, an optional source symbol reference for auxiliary dependences, and optional dependence properties. The custom syntax of ssp.operation normally hides this attribute from beginners.

The in-tree property attributes are:

opr
rsrcs
t
latency
dist
II
z
incDelay
outDelay
limit

opr links an operation to an operator type. rsrcs links an operation to one or more resource types. t records an operation start time. latency records operator latency. dist records a cyclic dependence distance. II records a cyclic initiation interval on an instance. z records a start time within a cycle for chaining problems. incDelay and outDelay describe operator delay properties for chaining. limit records the capacity of a resource type.

These properties are not arbitrary comments. Their TableGen base classes generate methods for loading values into, and saving values from, the matching circt::scheduling C++ problem classes.

144.7 Transformations And Conversions

The SSP dialect has three registered passes:

ssp-print
ssp-roundtrip
ssp-schedule

ssp-print loads each ssp.instance into the matching scheduling problem class and dumps the problem as a DOT graph. It supports the built-in problem classes handled by the scheduling infrastructure.

ssp-roundtrip loads an instance into a C++ scheduling problem and writes it back as SSP IR. It has options to check input constraints and verify solution constraints. This is useful for testing that the SSP import/export path preserves the problem structure and properties.

ssp-schedule runs a scheduler and replaces the original instances with the scheduled results. Its scheduler option dispatches to simplex by default, or to asap. When CIRCT is built with OR-Tools support, lp and cpsat schedulers are also available. The options string can designate the objective operation with last-op-name=... and can provide a cycle-time=... value for chaining problems.

The most important conversion utilities live in circt/Dialect/SSP/Utilities.h. They convert between ssp.InstanceOp and circt::scheduling::Problem subclasses through loadProblem and saveProblem helpers. This is not a normal MLIR dialect conversion from hardware IR to SSP. Instead, it is a bridge between textual problem instances and CIRCT’s scheduling data structures.

144.8 What The Dialect Implies

Seeing ssp means you are looking at the scheduling problem boundary. The IR is about constraints and solutions, not hardware emission. The names of operations, operator types, and resources are there to make a problem reproducible and understandable.

It also implies that properties matter as much as operations. Without latency, limit, dist, II, t, or linked operator/resource properties, an SSP graph may be structurally valid but not meaningful for the intended problem class.

The design is intentionally extensible. Out-of-tree projects can define their own property attributes by inheriting from the SSP property base classes. SSP’s own properties get compact pretty printing; external properties still work but fall back to normal dialect attribute syntax.

144.9 How To Use It In Practice

Use ssp when you want a small, self-contained scheduling test case. Start by choosing a problem name such as Problem, CyclicProblem, SharedOperatorsProblem, ModuloProblem, ChainingProblem, or ChainingCyclicProblem. Then declare the operator types and resource types, build the dependence graph with ssp.operation, and attach the properties that the selected problem class expects.

For debugging, ssp-print is the fastest way to see the graph structure. For infrastructure testing, ssp-roundtrip checks that load and save preserve the intended instance. For actual scheduling experiments, use ssp-schedule with a scheduler and options appropriate for the problem.

The beginner rule is simple: if you want to understand hardware behavior, look at the hardware dialects. If you want to understand the abstract scheduling problem that a scheduler sees, look at ssp.