# PartitionedSignal nmigen-aware eq (assign) * For copying (assigning) PartitionedSignal to PartitionedSignal of equal size there is no issue. However if the source has a greater width than the target, *partition-aware* truncation must occur. For the opposite, sign/zero extension must occur. Finally for a Signal or Const, duplication across all Partitions must occur, again, following the rules of zero, sign or unsigned. Take two PartitionedSignals (source a, dest b) of 32 bit: partition: p p p (3 bits) a : AAA3 AAA2 AAA1 AAA0 (32 bits) b : BBB3 BBB2 BBB1 BBB0 (32 bits) For all partition settings this copies verbatim. However when A is either shorter or longer, different behaviour occurs. If A is shorter than B: partition: p p p (3 bits) a : A7A6 A5A4 A3A2 A1A0 (8 bits) b : BBB3 BBB2 BBB1 BBB0 (16 bits) then it matters what the partition settings are: | partition | o3 | o2 | o1 | o0 | | --------- | -- | -- | -- | -- | | 000 | [A7A7A7A7] | [A7A7A7A7] | A7A6A5A4 | A3A2A1A0 | | 001 | [A7A7A7A7] | [A7A7]A7A6 | A5A4A3A2 | [A1A1]A1A0 | | 010 | [A7A7A7A7] | A7A6A5A4 | [A3A3A3A3] | A3A2A1A0 | | 011 | [A7A7A7A7] | A7A6A5A4 | [A3A3]A3A2 | [A1A1]A1A0 | | 100 | [A7A7]A7A6 | [A5A5A5A5] | [A5A5]A5A4 | A3A2A1A0 | | 101 | [A7A7]A7A6 | [A5A5A5A5] | A5A4A3A2 | [A1A1]A1A0 | | 110 | [A7A7]A7A6 | [A5A5]A5A4 | [A3A3A3A3] | A3A2A1A0 | | 111 | [A7A7]A7A6 | [A5A5]A5A4 | [A3A3]A3A2 | [A1A1]A1A0 | where square brackets are zero if A is unsigned, and contains the specified bits if signed. Here, each partition copies the smaller value (A) into the larger partition (B) then, depending on whether A is signed or unsigned, sign-extends or zero-extends *on a per-partition basis*. For A longer than B: partition: p p p (3 bits) a : AAAA AAAA AAAA AAAA (16 bits) b : B7B6 B5B4 B3B2 B1B0 (8 bits) truncation occurs at different points depending on partitions: | partition | o3 | o2 | o1 | o0 | | --------- | -- | -- | -- | -- | | 000 | A7A6 | A5A4 | A3A2 | A1A0 | | 001 | A9A8 | A7A6 | A5A4 | A1A0 | | 010 | A11A10 | A9A8 | A3A2 | A1A0 | | 011 | A11A10 | A9A8 | A5A4 | A1A0 | | 100 | A13A12 | A5A4 | A3A2 | A1A0 | | 101 | A13A12 | A7A6 | A5A4 | A1A0 | | 110 | A13A12 | A9A8 | A3A2 | A1A0 | | 111 | A13A12 | A9A8 | A5A4 | A1A0 | In effect, copying starts from the beginning of a partition, ending when a closed partition point is found. # Scalar source When the source A is scalar and is equal or larger than the destination it requires copying across multiple partitions: partition: p p p (3 bits) a : AAAA AAAA AAAA AAAA (16 bits) b : B7B6 B5B4 B3B2 B1B0 (8 bits) As the source is Scalar, it must be copied (broadcast) into each partition of the output, B, starting at the beginning of each partition. With each partition being smaller than A (except in one case) truncation is guaranteed. The exception is when all pattitions are open (1x) and the length of A and B are the same. The partition options are: | partition | o3 | o2 | o1 | o0 | | --------- | -- | -- | -- | -- | | 000 | A7A6 | A5A4 | A3A2 | A1A0 | | 001 | A5A4 | A3A2 | A1A0 | A1A0 | | 010 | A3A2 | A1A0 | A3A2 | A1A0 | | 011 | A3A2 | A1A0 | A1A0 | A1A0 | | 100 | A1A0 | A5A4 | A3A2 | A1A0 | | 101 | A1A0 | A3A2 | A1A0 | A1A0 | | 110 | A1A0 | A1A0 | A3A2 | A1A0 | | 111 | A1A0 | A1A0 | A1A0 | A1A0 | When the partitions are all open (1x) only the bits that will fit across the whole of the target are copied. In this example, B is 8 bits so only 8 bits of A are copied. When the partitions are all closed (4x SIMD) each partition of B is 2 bits wide, therefore only the *first two* bits of A are copied into *each* of the four 2-bit partitions in B. For the case where A is shorter than B output, sign or zero extension is required. Here we assume A is 8 bits, B is 16. This is similar to the parallel case except A is repeated (broadcast) across all of B. | partition | o3 | o2 | o1 | o0 | | --------- | -- | -- | -- | -- | | 000 | [A7A7A7A7] | [A7A7A7A7] | A7A6A5A4 | A3A2A1A0 | | 001 | [A7A7A7A7] | A7A6A5A4 | A3A2A1A0 | A3A2A1A0 | | 010 | A7A6A5A4 | A3A2A1A0 | A7A6A5A4 | A3A2A1A0 | | 011 | A7A6A5A4 | A3A2A1A0 | A3A2A1A0 | A3A2A1A0 | | 100 | A3A2A1A0 | [A7A7A7A7] | A7A6A5A4 | A3A2A1A0 | | 101 | A3A2A1A0 | A7A6A5A4 | A3A2A1A0 | A3A2A1A0 | | 110 | A3A2A1A0 | A3A2A1A0 | A7A6A5A4 | A3A2A1A0 | | 111 | A3A2A1A0 | A3A2A1A0 | A3A2A1A0 | A3A2A1A0 | Note how when the entire partition set is open (1x 16-bit output) that all of A is copied out, and either zero or sign extended in the top half of the output. At the other extreme is the 4x 4-bit output partitions, which have four copies of A, truncated from the first 4 bits of A. Unlike the parallel case, A is not itself partitioned, so is copied over as much as is possible. In some cases such as `1x 4-bit, 1x 12-bit` (partition mask = `0b100`, above) when copying the 8-bit scalar source into the highest part of B (o3) it is truncated to 4 bis (because each partition of B is only 4 bits) but for copying to the 12-bit partition (o2-o1-00) the 8-bit scalar source, A, will need sign or zero extending.