Argument-partitioning
How arguments to instance arrays are split up and given to the
individual instances.
Recall that in the replicate-insts transform we are
basically rewriting instance arrays like this:
type instname [N:0] (arg1, arg2, ..., argM) ;
Into things like this:
type instname_0 (arg1-0, arg2-0, ..., argM-0);
type instname_1 (arg1-1, arg2-1, ..., argM-1);
...
type instname_N (arg1-N, arg2-N, ..., argM-N);
Let us consider a particular, non-blank argument, ArgI, whose width is
ArgI-W. Suppose this argument is connected to a non-blank port with width
P-W.
Let's be clear on what we mean by P-W. If we are talking about module
instances then this is quite straightforward: the module has a list of ports,
and we can see how wide these ports are supposed to be by looking at the widths
of their port expressions; see vl-port-p. The argument ArgI
corresponds to some particular port, and so the width of that port is what
P-W is going to be. If we are talking about gates, then P-W is always
1.
According to the semantics laid forth in 7.1.6, there are only two valid
cases.
Case 1. ArgI-W = P-W. In this case, the argument is simply to be
replicated, verbatim, across all of the new instances.
Case 2. ArgI-W = P-W * K, where K is the number of
instances specified by this array. That is, if our instance array declaration
is:
type instname [N:0] (arg1, arg2, ...);
then K is N+1. In this case, we are going to slice up ArgI
into K segments of P-W bits each, and send them off to the instances.
For example, in the code:
wire w[3:0];
not g [3:0] (w, 4'b0011);
The ArgI-W of both w and 4'b0011 is four, while the P-W
is 1. In this case, we create four one-bit slices of w, and four one-bit
slices of 4'b0011, and connect them with four separate not-gates.
When we are dealing with gates, P-W is always 1. But when we talk
about modules, P-W might be larger. For example, consider the module:
module two_bit_and (o, a, b) ;
output [1:0] o;
input [1:0] a;
input [1:0] b;
assign o = a & b;
endmodule
And here we have an array of these two_bit_and modules:
wire [7:0] j;
two_bit_and myarray [3:0] (j, 8'b 11_00_10_01, 2'b 01);
This array is equivalent to:
two_bit_and myarray_0 (j[7:6], 2'b 11, 2'b 01) ;
two_bit_and myarray_1 (j[5:4], 2'b 00, 2'b 01) ;
two_bit_and myarray_2 (j[3:2], 2'b 10, 2'b 01) ;
two_bit_and myarray_3 (j[1:0], 2'b 01, 2'b 01) ;
And so the value of j will be 8'b 0100_0001.
That is, since all of the ports of two_bit_and are 2 bits, and we are
creating four instances, each of the array arguments can only be 2 or 8 bits
long. Any 8-bit arguments are split into 2-bit slices, and any 2-bit arguments
are replicated.
Subtopics
- Vl-partition-plainarg
- Partition a plain argument into slices.
- Vl-partition-msb-bitslices
- Group up a list of bits into N-bit concatenations.
- Vl-partition-plainarglist
- Extend vl-partition-plainarg across a list of arguments.
- Vl-reorient-partitioned-args
- Group arguments for instances after vl-partition-plainarglist.
- Vl-assemble-gateinsts
- Build vl-gateinst-p's from the sliced-up arguments.
- Vl-plainarglists-to-arguments
- Convert each plainarglist in a vl-plainarglistlist-p into an
vl-arguments-p.