[Comb][ExportVerilog] Add an operation to swap bits

Issue 2249 suggests emitting expressions of this form

b = {a[0], a[1], a[2], a[3], a[4]...}

as a more idiomatic expression. One such expression could be the streaming operator:

b = {>>{a}}

It was also suggested to add a swap operator to the comb dialect. Concat-expressions of the form above could then be expressed in a more concise way like this:

hw.module @Foo(%a : i16) -> (o: i16) {
   %0 = comb.swap %a : i16
   hw.output %0 : i16
}

I want to implement this operator but I believe that there are some design choices still open:

  • Would a swap operator allow a size of slices that can be swapped? This could come in handy to also support common use cases such as byte-swaps or nibble-swaps. Such slicing operators have an idiomatic representation in Verilog since the streaming operator allows to specify a slice size.
    An example of the usage would be this:

    hw.module @Foo(%a : i64) -> (o: i64) {
       %0 = comb.swap %a slice 8 : i64 // swaps the bytes of `a`
       hw.output %0 : i64
    }
    
  • The streaming operator is a feature of Verilog 2017. What is the fallback for older versions, is it a simple concatenation of the bits as it is done now?

  • Is there are an approach more general than swapping bits (or slices), maybe something more similar to the streaming operator in Verilog (I believe the answer to that is No though since in the context of bit-vectors the left-streaming operator << has no real purpose and the right-streaming operator >> cannot do more than the suggested swap operation with slices already does)

  • Is the swap operator even necessary or is it just burdensome syntactic sugar?

IMO it’s just burdensome syntactic sugar. Could make for more compact IR (especially if it supported arrays), but I still don’t think it’s worth it. I could see an argument use for a more general bit/element swizzle operation if the swizzle could be represented compactly.

I, however, have no objection to adding a stream op to the SV dialect and detecting comb/hw patterns which can be expressed with it in the pretty verilog pass.

Operators like this should be added when they serve a purpose: for example if there is some SV syntax that export-verilog should produce then it can be important to have an IR node for it (rather than trying to pattern match in the printer). If there are (important!) mid-level optimizations that this form helps expose then it can be useful.

At this phase of development, I’d ask if there is V/SV syntax for this, and if any clients of the verilog printer actually want it :slight_smile: