'pipeline' Dialect
Operation definition ¶
pipeline.pipeline
(::circt::pipeline::PipelineOp) ¶
pipeline operation
Syntax:
operation ::= `pipeline.pipeline` `(` $inputs `)` `clock` $clock `reset` $reset attr-dict `:` functional-type($inputs, results) $body
The “pipeline.pipeline” operation represents a retimeable pipeline.
The pipeline contains a single block representing a graph region. Pipeline
stages are represented by pipeline.rt.register
operations. Semantics
of values crossing register boundaries are defined by lowering passes.
The pipeline representation is centered around providing latency insensitive
values (valid signals between stages). Such signals can either be removed
(in the feedforward, statically scheduled case), used to control stalling
(feedback, statically scheduled case) or in conjunction with handshake signals
for dynamically scheduled pipelines.
A pipelines’ latency sensitivity is based on the I/O of the pipeline - if
any in- or output port is an ESI channel, all ports are expected to be ESI
channels, and the pipeline is considered latency sensitive.
The internal representation of the pipeline is agnostic to the latency
insensitivity of the I/O. This is by design - allowing us a single source
of truth for lowering either latency sensitive or latency insensitive pipelines.
A typical flow would go like this:
An untimed datapath is defined:
pipeline.pipeline(%in0 : i32, %in1 : i32) -> (i32) {
^bb0:(%arg0 : i32, %arg1: i32):
%add0 = comb.add %arg0, %arg1 : i32
%add1 = comb.add %add0, %arg0 : i32
%add2 = comb.add %add1, %arg1 : i32
pipeline.return %add2 : i32
}
The datapath is scheduled:
pipeline.pipeline(%in0 : i32, %in1 : i32) -> (i32) {
^bb0:(%arg0 : i32, %arg1: i32, %go : i1):
%add0 = comb.add %arg0, %arg1 : i32
%s0_valid = pipeline.stage when %go
%add1 = comb.add %add0, %arg0 : i32
%s1_valid = pipeline.stage when %g1
%add2 = comb.add %add1, %arg1 : i32
pipeline.return %add2 valid %s1_valid : i32
}
Stage-crossing dependencies are made explicit through registers.
pipeline.pipeline(%in0 : i32, %in1 : i32) -> (i32) {
^bb0:(%arg0 : i32, %arg1: i32):
%add0 = comb.add %arg0, %arg1 : i32
%s0_valid, %add0_r = pipeline.stage.register when %go regs (%add0: i32)
%add1 = comb.add %add0_r, %arg0 : i32
%s1_valid, %add1_r = pipeline.stage.register when %g1 regs (%add1: i32)
%add2 = comb.add %add1_r, %arg1 : i32
pipeline.return %add2 valid %s1_valid : i32
}
This representation can then be lowered to statically or dynamically scheduled pipelines.
Traits: AlwaysSpeculatableImplTrait, HasOnlyGraphRegion, IsolatedFromAbove, SingleBlockImplicitTerminator
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), RegionKindInterface
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
inputs | any type |
clock | 1-bit signless integer |
reset | 1-bit signless integer |
Results: ¶
Result | Description |
---|---|
results | any type |
pipeline.register
(::circt::pipeline::PipelineRegisterOp) ¶
Pipeline dialect pipeline register.
Syntax:
operation ::= `pipeline.register` $operands (`:` qualified(type($operands))^)? attr-dict
The pipeline.register
terminates a pipeline stage and
“registers” the values specified as operands. These values become the
results of the stage.
Traits: HasParent<PipelineWhileOp, PipelineWhileStageOp>, Terminator
Operands: ¶
Operand | Description |
---|---|
operands | any type |
pipeline.stage
(::circt::pipeline::PipelineStageOp) ¶
Pipeline pipeline stage.
Syntax:
operation ::= `pipeline.stage` `when` $when attr-dict
The pipeline.stage
operation represents a stage separating register
in a pipeline. The stage does not define any explicit registers, but solely
defines a cut of a dataflow graph based on its lexical position in the
pipeline. Pipeline registers are made explicit through the register
materialization pass, wherein this op is replaced by
pipeline.stage.register
operations.
Traits: HasParent
Interfaces: InferTypeOpInterface
Operands: ¶
Operand | Description |
---|---|
when | 1-bit signless integer |
Results: ¶
Result | Description |
---|---|
valid | 1-bit signless integer |
pipeline.stage.register
(::circt::pipeline::PipelineStageRegisterOp) ¶
Pipeline pipeline stage.
Syntax:
operation ::= `pipeline.stage.register` `when` $when (`regs` $regIns^)? attr-dict (`:` type($regIns)^)?
The pipeline.stage
operation represents a stage separating register
in a pipeline with materialized register values. pipeline.stage
and
pipeline.stage.register
operations are not allowed to co-exist in the
same pipeline body. This is because, once register values are materialized,
all delays as well as knowledge about multicycle paths have been lowered
away.
Traits: HasParent
Operands: ¶
Operand | Description |
---|---|
regIns | any type |
when | 1-bit signless integer |
Results: ¶
Result | Description |
---|---|
regOuts | any type |
valid | 1-bit signless integer |
pipeline.terminator
(::circt::pipeline::PipelineTerminatorOp) ¶
Pipeline dialect pipeline terminator.
Syntax:
operation ::= `pipeline.terminator` `iter_args` `(` $iter_args `)` `,`
`results` `(` $results `)` `:`
functional-type($iter_args, $results) attr-dict
The pipeline.terminator
operation represents the terminator of
a pipeline.while
.
The results
section accepts a variadic list of values which become the
pipeline’s return values. These must be results of a stage, and their types
must match the pipeline’s return types. The results need not be defined in
the final stage, and it is up to lowering passes to preserve these values
until the final stage is complete.
The iter_args
section accepts a variadic list of values which become the
next iteration’s iter_args
. These may be the results of any stage, and
their types must match the pipeline’s iter_args
types.
Traits: AttrSizedOperandSegments, HasParent
Operands: ¶
Operand | Description |
---|---|
iter_args | any type |
results | any type |
pipeline.while
(::circt::pipeline::PipelineWhileOp) ¶
Pipeline dialect pipeline while-loop.
The pipeline.while
operation represents a statically scheduled
pipeline stucture that executes while a condition is true. For more details,
see:
https://llvm.discourse.group/t/rfc-representing-pipelined-loops/4171.
A pipeline captures the result of scheduling, and is not generally safe to transform, besides lowering to hardware dialects. For more discussion about relaxing this, see: https://github.com/llvm/circt/issues/2204.
This is the top-level operation representing a high-level pipeline. It is
not isolated from above, but could be if this is helpful. A pipeline
contains two regions: condition
and stages
.
The pipeline may accept an optional iter_args
, similar to the SCF dialect,
for representing loop-carried values like induction variables or reductions.
When the pipeline starts execution, the registers indicated as iter_args
by pipeline.terminator
should be initialized to the initial
values specified in the iter_args
section here. The iter_args
relate to
the initiation interval of the loop. The maximum distance in stages between
where an iter_arg
is used and where that iter_arg
is registered must be
less than the loop’s initiation interval. For example, with II=1, each
iter_arg
must be used and registered in the same stage.
The single-block condition
region dictates the condition under which the
pipeline should execute. It has a register
terminator, and the
pipeline initiates new iterations while the registered value is true : i1
.
It may access SSA values dominating the pipeline, as well as iter_args
,
which are block arguments. The body of the block may only contain
“combinational” operations, which are currently defined to be simple
arithmetic, comparisons, and selects from the Standard
dialect.
The single-block stages
region wraps pipeline.stage
operations. It has a pipeline.terminator
terminator, which can
both return results from the pipeline and register iter_args
. Stages may
access SSA values dominating the pipeline, as well as iter_args
, which are
block arguments.
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
II | ::mlir::IntegerAttr | 64-bit signless integer attribute |
tripCount | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operands: ¶
Operand | Description |
---|---|
iterArgs | any type |
Results: ¶
Result | Description |
---|---|
results | any type |
pipeline.while.stage
(::circt::pipeline::PipelineWhileStageOp) ¶
Pipeline dialect while pipeline stage.
Syntax:
operation ::= `pipeline.while.stage` `start` `=` $start (`when` $when^)? $body (`:` qualified(type($results))^)? attr-dict
This operation has a single-block region which dictates the operations that may occur concurrently.
It has a start
attribute, which indicates the start cycle for this stage.
It may have an optional when
predicate, which supports conditional
execution for each stage. This is in addition to the condition
region that
controls the execution of the whole pipeline. A stage with a when
predicate should only execute when the predicate is true : i1
, and push a
bubble through the pipeline otherwise.
It has a register
terminator, which passes the concurrently
computed values forward to the next stage.
Any stage may access iter_args
. If a stage accesses an iter_arg
after
the stage in which it is defined, it is up to lowering passes to preserve
this value until the last stage that needs it.
Other than iter_args
, stages may only access SSA values dominating the
pipeline or SSA values computed by any previous stage. This ensures the
stages capture the coarse-grained schedule of the pipeline and how values
feed forward and backward.
Traits: HasParent
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
start | ::mlir::IntegerAttr | 64-bit signed integer attribute |
Operands: ¶
Operand | Description |
---|---|
when | 1-bit signless integer |
Results: ¶
Result | Description |
---|---|
results | any type |
pipeline.return
(::circt::pipeline::ReturnOp) ¶
Pipeline dialect return.
Syntax:
operation ::= `pipeline.return` ($outputs^)? `valid` $valid attr-dict (`:` type($outputs)^)?
The “return” operation represents a terminator of a pipeline.pipeline
.
Traits: Terminator
Operands: ¶
Operand | Description |
---|---|
outputs | any type |
valid | 1-bit signless integer |