Question about WriteRes records

I’ve got two questions about tablegen WriteRes records…

So WriteRes records enumerate the ProcResources used per cycle. So writing:
def some_write : WriteRes<some_res, some_res>
indicates that “some_res” is used for two consecutive cycles.

Writing:
def some_write : WriteRes { let ResourceCycles = [2] }
also indicates “res” is used for 2 cycles.

So the first question is: is there a difference between the two ways of defining WriteRes records? The documentation seems to imply that the former indicates the unit is fully pipelined, even though the resource is used for 2 cycles. My interpretation is that you could only issue an instruction every 2 cycles, regardless of which specification you use, and that in this context, these two ways of expressing it are equivalent. Is that true?

This gets more interesting if “some_res” is actually a resource group:

   def A57UnitV : ProcResGroup<[A57UnitX, A57UnitW]>;

Presumably a reservation of A57UnitV can reserve either A57UnitX or A57UnitW.
Makes sense - this is the method tablegen uses to indicate something can issue on more than one unit.

So the second question is: how are you supposed to interpret: (I’ll abbreviate the unit names to make it easier to read):

 def V : ProcResGroup<[X, W]>;
 def some_write : WriteRes<V, V>

ie one or more ResGroups in a WriteRes spec. The naive thing to do would be do assume all 4 permutations of the two resource groups (in this case) are plausible, ie:

SchedWriteRes<X, X> | SchedWriteRes<X, W> | SchedWriteRes<W, X> | SchedWriteRes<W, W>

But its not clear whether:

  1. this is what the hardware does, and
  2. even if this is what the hardware can do, would this actually be helpful to a scheduler.

Clearly as the number of referenced groups grows, the number of permutations of functional unit usage grows. A different interpretation, is that you interpret the above WriteRes as:

  SchedWriteRes<X, X> | SchedWriteRes<Y, Y>

Or more generally, if a ResGroup is used in a WriteRes spec, all appearances of that group in a permutation use the same group member. Now the number of possible permutations is simply the product of all mentioned group sizes, which frankly can still get quite large, but is generally manageable.

If thats not valid, then you might make the case that perhaps there IS an intended difference between:

 SchedWriteRes<group, group>
  and
 SchedWriteRes<group> { let ResourceCycles = [2] }

There are cases where people have written something like:

  def KryoUnitX : ProcResGroup<[KryoUnitXA, KryoUnitXB]>;
  def write : WriteRes<KryoUnitX, KryoUnitX, KryoUnitX, KryoUnitX, KryoUnitX, ... (~14 times)>

This can lead to a very complex scheduling task if we allow all permutations of functional units,
or just 2 possibilities which all use A or all use B.

So could someone clarify this for me? Thanks in advance!

-Reid