[RFC] Extending seq.combreg with enables, resets and clears

(hi, i’m new here!)

I’d like to propose extending seq.combreg to support sync clear, async reset
and enables.

Motivation:

  • An explicit spec type is benefitial, as it avoids nasty ordering bugs, and
    parsing combreg arguments for things that may or may not be optional.
  • Having explicit sync clear / async reset / enables makes saves lower / higher passes
    from having to “guess” if mux-es structured a certain way is sync sets.

Concretely, these are the extensions to the dialect i’d like to add.

%spec = seq.spec.empty

// The following operations are immutable. They return a new spec!
%spec = seq.spec.set_sync_clear %spec
%spec = seq.spec.set_sync_clear_value %spec
%spec = seq.spec.set_async_reset %spec
%spec = seq.spec.set_async_reset_value %spec
%spec = seq.spec.set_enable %spec

// And the following change to the existing seq.combreg type.
%r    = seq.combreg %clk, %data, %spec

Example 1: creating a register with an synchronous clear will look something like this:

%spec0 = seq.spec.empty
%spec = seq.spec.set_sync_clear %spec0, %clear
%r    = seq.combreg %clk, %data, %spec

Example 2: creating a regiser with an asynchronous reset, with some enable signal:

%spec0 = seq.spec.empty
%spec1 = seq.spec.set_async_reset %spec0, %reset
%spec2 = seq.spec.set_enable %spec1, %enable
%r    = seq.combreg %clk, %data, %spec2

Example 3: creating a regiser with no reset, no clear, no enable

%spec = seq.spec.empty
%r    = seq.combreg %clk, %data, %spec

Example 4: create a shift register (this should map nicely to a FPGA SRL):

%spec = seq.spec.empty
$r0 = seq.combreg %clk, %data, %spec
$r1 = seq.combreg %clk, %r0, %spec
$r2 = seq.combreg %clk, %r1, %spec

seq.compreg is intended to be very simple to serve basic needs, which I suspect are the most common cases for computational code. (It’s ‘comp’ not ‘comb’ for ‘computation’.)

At the time, we said that we needed a more general seq.reg which supported everything and the kitchen sink.

You’re looking for attributes. They’re typically how complex operations are customized.

Not extending comp.reg makes sense, and introducing a general seq.reg makes sense.

If i understand correctly, attributes are only for compile-time constants. If that’s the case, it can capture some properties (posedge/negedge/edge-sensitive, and perhaps initial value), but not others (clearValue, clear, resetValue, reset)

Yes, you understood correctly. I thought that spec was a specification for the register – like what features it provides.

I don’t see a compelling reason for spec. Everything you’re talking about could just be operands (for the runtime values) + attributes (for the compile time constants). Does having all those operands make the IR more complex? Yes, but it’s just IR. Having a separate set of types and ops to operate on spec makes the IR more complex for analysis. (i.e. getting the sync_clear_value requires following the def-use chain through several operations rather than just having it available as a field.) At the end of the day, IRs are about ease of analysis and transformation.