llvm / circt

Circuit IR Compilers and Tools
https://circt.org
Other
1.67k stars 298 forks source link

Add support for lowering vectors of wires from FIRRTL to RTL #18

Closed amaleewilson closed 3 years ago

amaleewilson commented 4 years ago

To finish lowering wire from the FIRRTL dialect to the RTL dialect, the RTL dialect must support vectors of wires.

While FIRRTL seems to have only vectors of wires, Verilog allows n-dimensional wires, which can be either packed or unpacked. The packed vs unpacked distinction has a huge impact on simulator performance. From my discussions with Verilog folks, here are some examples of wires:

wire a; // single wire, e.g. firrtl.wire : !firrtl.uint<1>
wire [7:0] b; // bitvector, e.g. firrtl.wire : !firrtl.uint<8> (I think) 
wire [0:0] c; // bitvector length one, not equivalent to a. 
wire [0:0] d [0:7] // unpacked, technically 2D
wire [0:0] [0:7] d // packed, technically 2D
wire [2:0] [0:7] e // packed, 2D
wire [2:0] [0:7] e [3:0] // unpacked?, 3D

q = b[5]; // slice one bit of bitvctor b
r = b[5:5] // vector slice of bitvector b

// more examples from http://www.verilogpro.com/verilog-arrays-plain-simple/
reg [31:0] x      [127:0];        // 128-element array of 32-bit wide reg
wire[15:0] y[7:0], z[7:0];        // 2 arrays of 16-bit wide wires indexed from 7 to 0
reg [ 7:0] mema   [255:0];        // 256-entry memory mema of 8-bit registers
reg        arrayb [  7:0][255:0]; // two-dimensional array of one bit registers

I'm not sure how fine grained these distinctions should be in the RTL dialect, but it might make sense to start with vectors and eventually support tensors of wires.

Additionally, bitvectors can be of length 0, and can also be of length unknown.

lattner commented 4 years ago

Interesting, is the 'packed vs unpacked' distinction just simulator performance, or is there something else going on here?

It seems like there are a couple of ways we could model this: 1) we could model this with a list of dimensions, then a "number of packed dimensions" integer in the type. 2) we could model this as a single "packed vector" and "unpacked vector" type that compose onto each other.

I think the major distinction should be how these compose with non-bit types like the SystemVerilog bundle types.

solomatnikov commented 4 years ago

FYI https://www.veripool.org/issues/1656-Verilator--RFC-Relaxing-UNOPTFLAT-by-dividing-unpacked-array#note-1

Something to keep in mind when generating arrays b/c Verilator is the most used open source simulator.

drom commented 4 years ago

4D array

//      2     1        3     4
logic [1:5] [7:0] v4 [1:7] [1:8];

1,2 = packed dimensions - guaranteed to be represented as a contiguous set of bits. 3,4 = unpacked dimentions - can be resized (grow, shrink)

1 varies most rapidly, followed by 2,3,4

stephenneuendorffer commented 4 years ago

Generally for memory inference to work you want something like: reg [DWIDTH-1:0] ram[0:MEM_SIZE-1];

amaleewilson commented 4 years ago

@lattner I think option 2 is most intuitive.

drom commented 4 years ago

All N packed dimensions have to compose first before to compose with M unpacked dimensions. Could we make sure that packed type can compose into primitive or packed type only, while unpacked can compose into primitive, packed or unpacked.

lattner commented 4 years ago

It could be good to bring this up on the forum to see if others have an opinion, it would also be worth looking at what LLHD is doing here.

teqdruid commented 4 years ago

I'm not sure if we ended up discussing this in one of the meetings, but I'm planning on adding a tensor type to the RTL dialect. I welcome additional input!

lattner commented 3 years ago

We now have ArrayType (packed) and UnpackedArrayType, I think this is done.