Seq(uential) Dialect Rationale
This document describes various design points of the
seq dialect, why it is
the way it is, and current status. This follows in the spirit of other
Digital logic is generally split into two categories: combinational and
sequential. CIRCT contains a
comb dialect to model the basic combinational
operations and the (future)
seq dialect which is discussed here. The
intention of the
seq dialect is to provide a set of stateful constructs
which can be used to model sequential logic, independent of the output method
We have yet to flesh this dialect out to represent all common stateful components. We start with a register and will build from there.
For the sake of precision, we use the following definitions:
- Physical devices:
- Unclocked Latch: A memory element which is only sensitive to the levels of its inputs. Has no clock. Example: SR Latch.
- Clocked (gated) latch: A latch wherein the inputs are gated by a clock. Transparent the entire time the clock is high. Generally referred to as a “latch”. Examples: “gated SR latch”, “D latch”.
- Edge-triggered flip-flop: An edge-sensitive memory element. Captures the input value on one or both clock edges. Variants: posedge FF, negedge FF, “edge-sensitive” FF (captures the input value on both edges), resettable FF.
- Abstract models:
- Register: A synchronous, resettable memory element. Can be implemented using any of the above “circuit level” elements.
The computational register operation ¶
seq.compreg op models an abstract notion of a “register”, independent
of its implementation (e.g. latch, D flip-flop). This specific register op is
intended to support “computation support” or “reset-agnostic code” and thus
it cannot be used to model all the behaviors of a SystemVerilog register.
(E.g. FSM and pipeline registers.) It is intended to be ‘lowered’ to a
specific implementation, which may be an
sv.always_ff block, a device
primitive instantiation, or even a feedback loop in all
Our intention is to allow analysis and optimization of sequential logic without having to reason about implementation-specific behavior. This makes it somewhat distinct from the SystemVerilog register wherein one has to account for details like reset behavior and implementation (latch vs. flip-flop).
CompReg has four operands:
- input: The value to be captured at ‘clock’. Generally called ‘d’. Accepts any type, results in the same type. Does not support any notion of addressing, meaning that this operation sets / reads the entire value.
- clock: Capture ‘value’ on the positive edge of this signal.
- reset: Signal to set the state to ‘resetValue’. Optional.
- resetValue: A value which the state is set to upon reset. Required iff ‘reset’ is present.
%q = seq.compreg %input, %clk [, %reset, %resetValue ] : $type(input)
Upon initialization, the state is defined to be uninitialized.
Several design decisions were made in defining this op. Mostly, they were made to simplify it while still providing the common case. Providing support for all flavors of registers is an anti-goal of this op. If an omitted feature is needed, it can be added or (if not common or precludes optimization) another op could be added.
- Inclusion of optional ‘reset’ signal: This operand makes lowering to an efficient implementation of reset easier. Omission of it would require some (potentially complex) analysis to find the reset mux if required
- Inclusion of ‘resetValue’: if we have a ‘reset’ signal, we need to include a value.
- Omission of ‘enable’: enables are easily modeled via a multiplexer on the input with one of the mux inputs as the output of the register. This – we assume – property makes ‘enables’ easier to detect than reset in the common case.
Timing / clocking:
- Omission of ‘negedge’ event on ‘clock’: this is easily modeled by inverting the clock value.
- Omission of ‘dual edge’ event on ‘clock’: this is not expected to be terribly common.
- Omission of edge conditions on ‘reset’: Since this op specifically targets “reset-agnostic code”, the reset style shouldn’t affect logical correctness. It should, therefore, be determined by a lowering pass.
Future considerations ¶
- Enable signal: if this proves difficult to detect (or non-performant if we do not detect and generate the SystemVerilog correctly), we can build it into the compreg op.
- Reset style and clock style: how should we model posedge vs negedge clocks?
Async vs sync resets? There are some reasonble options here: attributes on
this op or
resettypes which are parameterized with that information.
- Initial value: this register is uninitialized. Using an uninitialized value
results in undefined behavior. We will add an
initialValueattribute if this proves insufficient.