SymbiFlow / nextpnr

nextpnr portable FPGA place and route tool
ISC License
20 stars 2 forks source link

Implement primitive macro's #264

Open litghost opened 3 years ago

litghost commented 3 years ago

Current status

Primitive macro's are unimplemented, and therefore designs that use primitive's that have macro's cannot be placed and routed using the FPGA interchange implementation.

Description

The FPGA interchange DeviceResource's format describes [primitive macro's]() for any library primitive that is multiple elements during place and route. The most commonly encountered 7-series primitive's like this are different IO (e.g. OBUFTDS) and LUT-RAMs (e.g. RAM64X1D, RAM128X1D).

Implementing primitive macro's has two major parts:

Apply cell type exception map

The first is cell type rename, based on the https://github.com/SymbiFlow/fpga-interchange-schema/blob/f537a57fd7af091aabb776cb888f103b2b29349b/interchange/DeviceResources.capnp#L84 . This is required for cell types that have a name collision between the pre-macro expansion step and and the post-macro expansion step.

Example:

The primitive OBUFTDS macro expansion in verilog looks like:

module OBUFTDS_DUAL_BUF(input I, input T, output O, output OB);

OBUFTDS P(.I(I), .T(T), .O(O), .OB(OB));
wire I_INV;
INV INV(.I(I), .O(I_B));
OBUFTDS N(.I(I_B), .(T), .O(OB));

endmodule

In this case, the primitive OBUFTDS has a macro that inside of instances cells named OBUFTDS. To avoid the namespace collision, the exceptionMap in the DeviceResources renames the primitive type to OBUFTDS_DUAL_BUF.

Expand the macro

In the DeviceResources primLibs field are two libraries. One of those libraries are cell primitives with no macros. These cells need no further expansion. Examples would be FDRE, IBUF, OBUF. These cells have no interior contents.

The other set of library cells have interior contents and represent the macros to be expanded. Macro's can a depth greater than 1. The expansion should continue until all elements of the macro's are non-macro primitive cells. Several things to note:

Example for cell names:

Above, there was an example of the OBUFTDS macro. In that expansion, one primitive cell became 3 cells. If the original cell was named "example_obuftds", then the cell placements would be named "example_obuftds/P", "example_obuftds/INV" and "example_obuftds/N".

Place the design respecting the macro

Because a macro primitive expands into multiple cells there is the question of how to place the macro legally. In some cases, for each site there is only 1 legal placement.

As an example, the OBUFTDS_DUAL_BUF macro has exactly one legal placement per IOB pair. As a concrete example (part xc7a35tcpg236-1), if the P element of the macro is placed at IOB_X0Y14.IOB33M/OUTBUF BEL, then the INV element must be placed at IOB_X0Y13.IOB33S/O_ININV BEL and the N element must be placed at IOB_X0Y13.IOB33S/OUTBUF BEL.

In some cases, each site will be a handful of legal placements. The RAM64X1D has two legal placements in 7-series. The DP cell can be placed at C6LUT or A6LUT, and the SP cell at D6LUT or B6LUT within the same site, respectively.