The extract pass

  • Like the techmap pass, the extract pass is called with a map file. It compares the circuits inside the modules of the map file with the design and looks for sub-circuits in the design that match any of the modules in the map file.

  • If a match is found, the extract pass will replace the matching subcircuit with an instance of the module from the map file.

  • In a way the extract pass is the inverse of the techmap pass.

Example code can be found in docs/source/code_examples/macc.

read_verilog macc_simple_test.v
hierarchy -check -top test;;
../../_images/macc_simple_test_00a.svg

Fig. 25 before extract

extract -constports -map macc_simple_xmap.v;;
../../_images/macc_simple_test_00b.svg

Fig. 26 after extract

Listing 43 macc_simple_test.v
module test(a, b, c, d, y);
input [15:0] a, b;
input [31:0] c, d;
output [31:0] y;
assign y = a * b + c + d;
endmodule
Listing 44 macc_simple_xmap.v
module macc_16_16_32(a, b, c, y);
input [15:0] a, b;
input [31:0] c;
output [31:0] y;
assign y = a*b + c;
endmodule
Listing 45 macc_simple_test_01.v
module test(a, b, c, d, x, y);
input [15:0] a, b, c, d;
input [31:0] x;
output [31:0] y;
assign y = a*b + c*d + x;
endmodule
../../_images/macc_simple_test_01a.svg
../../_images/macc_simple_test_01b.svg
Listing 46 macc_simple_test_02.v
module test(a, b, c, d, x, y);
input [15:0] a, b, c, d;
input [31:0] x;
output [31:0] y;
assign y = a*b + (c*d + x);
endmodule
../../_images/macc_simple_test_02a.svg
../../_images/macc_simple_test_02b.svg

The wrap-extract-unwrap method

Often a coarse-grain element has a constant bit-width, but can be used to implement operations with a smaller bit-width. For example, a 18x25-bit multiplier can also be used to implement 16x20-bit multiplication.

A way of mapping such elements in coarse grain synthesis is the wrap-extract-unwrap method:

wrap

Identify candidate-cells in the circuit and wrap them in a cell with a constant wider bit-width using techmap. The wrappers use the same parameters as the original cell, so the information about the original width of the ports is preserved. Then use the connwrappers command to connect up the bit-extended in- and outputs of the wrapper cells.

extract

Now all operations are encoded using the same bit-width as the coarse grain element. The extract command can be used to replace circuits with cells of the target architecture.

unwrap

The remaining wrapper cell can be unwrapped using techmap.

Example: DSP48_MACC

This section details an example that shows how to map MACC operations of arbitrary size to MACC cells with a 18x25-bit multiplier and a 48-bit adder (such as the Xilinx DSP48 cells).

Preconditioning: macc_xilinx_swap_map.v

Make sure A is the smaller port on all multipliers

Listing 47 macc_xilinx_swap_map.v
(* techmap_celltype = "$mul" *)
module mul_swap_ports (A, B, Y);

parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] Y;

wire _TECHMAP_FAIL_ = A_WIDTH <= B_WIDTH;

\$mul #(
	.A_SIGNED(B_SIGNED),
	.B_SIGNED(A_SIGNED),
	.A_WIDTH(B_WIDTH),
	.B_WIDTH(A_WIDTH),
	.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
	.A(B),
	.B(A),
	.Y(Y)
);

endmodule

Wrapping multipliers: macc_xilinx_wrap_map.v

Listing 48 macc_xilinx_wrap_map.v
(* techmap_celltype = "$mul" *)
module mul_wrap (A, B, Y);

parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] Y;

wire [17:0] A_18 = A;
wire [24:0] B_25 = B;
wire [47:0] Y_48;
assign Y = Y_48;

wire [1023:0] _TECHMAP_DO_ = "proc; clean";

reg _TECHMAP_FAIL_;
initial begin
	_TECHMAP_FAIL_ <= 0;
	if (A_SIGNED || B_SIGNED)
		_TECHMAP_FAIL_ <= 1;
	if (A_WIDTH < 4 || B_WIDTH < 4)
		_TECHMAP_FAIL_ <= 1;
	if (A_WIDTH > 18 || B_WIDTH > 25)
		_TECHMAP_FAIL_ <= 1;
	if (A_WIDTH*B_WIDTH < 100)
		_TECHMAP_FAIL_ <= 1;
end

\$__mul_wrapper #(
	.A_SIGNED(A_SIGNED),
	.B_SIGNED(B_SIGNED),
	.A_WIDTH(A_WIDTH),
	.B_WIDTH(B_WIDTH),
	.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
	.A(A_18),
	.B(B_25),
	.Y(Y_48)
);

endmodule

Wrapping adders: macc_xilinx_wrap_map.v

Listing 49 macc_xilinx_wrap_map.v
(* techmap_celltype = "$add" *)
module add_wrap (A, B, Y);

parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] Y;

wire [47:0] A_48 = A;
wire [47:0] B_48 = B;
wire [47:0] Y_48;
assign Y = Y_48;

wire [1023:0] _TECHMAP_DO_ = "proc; clean";

reg _TECHMAP_FAIL_;
initial begin
	_TECHMAP_FAIL_ <= 0;
	if (A_SIGNED || B_SIGNED)
		_TECHMAP_FAIL_ <= 1;
	if (A_WIDTH < 10 && B_WIDTH < 10)
		_TECHMAP_FAIL_ <= 1;
end

\$__add_wrapper #(
	.A_SIGNED(A_SIGNED),
	.B_SIGNED(B_SIGNED),
	.A_WIDTH(A_WIDTH),
	.B_WIDTH(B_WIDTH),
	.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
	.A(A_48),
	.B(B_48),
	.Y(Y_48)
);

endmodule

Extract: macc_xilinx_xmap.v

Listing 50 macc_xilinx_xmap.v
module DSP48_MACC (a, b, c, y);

input [17:0] a;
input [24:0] b;
input [47:0] c;
output [47:0] y;

assign y = a*b + c;

endmodule

… simply use the same wrapping commands on this module as on the design to create a template for the extract command.

Unwrapping multipliers: macc_xilinx_unwrap_map.v

Listing 51 $__mul_wrapper module in macc_xilinx_unwrap_map.v
module \$__mul_wrapper (A, B, Y);

parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

input [17:0] A;
input [24:0] B;
output [47:0] Y;

wire [A_WIDTH-1:0] A_ORIG = A;
wire [B_WIDTH-1:0] B_ORIG = B;
wire [Y_WIDTH-1:0] Y_ORIG;
assign Y = Y_ORIG;

\$mul #(
	.A_SIGNED(A_SIGNED),
	.B_SIGNED(B_SIGNED),
	.A_WIDTH(A_WIDTH),
	.B_WIDTH(B_WIDTH),
	.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
	.A(A_ORIG),
	.B(B_ORIG),
	.Y(Y_ORIG)
);

endmodule

Unwrapping adders: macc_xilinx_unwrap_map.v

Listing 52 $__add_wrapper module in macc_xilinx_unwrap_map.v
module \$__add_wrapper (A, B, Y);

parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

input [47:0] A;
input [47:0] B;
output [47:0] Y;

wire [A_WIDTH-1:0] A_ORIG = A;
wire [B_WIDTH-1:0] B_ORIG = B;
wire [Y_WIDTH-1:0] Y_ORIG;
assign Y = Y_ORIG;

\$add #(
	.A_SIGNED(A_SIGNED),
	.B_SIGNED(B_SIGNED),
	.A_WIDTH(A_WIDTH),
	.B_WIDTH(B_WIDTH),
	.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
	.A(A_ORIG),
	.B(B_ORIG),
	.Y(Y_ORIG)
);

endmodule
Listing 53 test1 of macc_xilinx_test.v
module test1(a, b, c, d, e, f, y);
    input [19:0] a, b, c;
    input [15:0] d, e, f;
    output [41:0] y;
    assign y = a*b + c*d + e*f;
endmodule
../../_images/macc_xilinx_test1a.svg
../../_images/macc_xilinx_test1b.svg
Listing 54 test2 of macc_xilinx_test.v
module test2(a, b, c, d, e, f, y);
    input [19:0] a, b, c;
    input [15:0] d, e, f;
    output [41:0] y;
    assign y = a*b + (c*d + e*f);
endmodule
../../_images/macc_xilinx_test2a.svg
../../_images/macc_xilinx_test2b.svg

Wrapping in test1:

../../_images/macc_xilinx_test1b.svg
techmap -map macc_xilinx_wrap_map.v

connwrappers -unsigned $__mul_wrapper Y Y_WIDTH \
             -unsigned $__add_wrapper Y Y_WIDTH;;
../../_images/macc_xilinx_test1c.svg

Wrapping in test2:

../../_images/macc_xilinx_test2b.svg
techmap -map macc_xilinx_wrap_map.v

connwrappers -unsigned $__mul_wrapper Y Y_WIDTH \
             -unsigned $__add_wrapper Y Y_WIDTH;;
../../_images/macc_xilinx_test2c.svg

Extract in test1:

../../_images/macc_xilinx_test1c.svg
design -push
read_verilog macc_xilinx_xmap.v
techmap -map macc_xilinx_swap_map.v
techmap -map macc_xilinx_wrap_map.v;;
design -save __macc_xilinx_xmap
design -pop

extract -constports -ignore_parameters \
        -map %__macc_xilinx_xmap       \
        -swap $__add_wrapper A,B ;;
../../_images/macc_xilinx_test1d.svg

Extract in test2:

../../_images/macc_xilinx_test2c.svg
design -push
read_verilog macc_xilinx_xmap.v
techmap -map macc_xilinx_swap_map.v
techmap -map macc_xilinx_wrap_map.v;;
design -save __macc_xilinx_xmap
design -pop

extract -constports -ignore_parameters \
        -map %__macc_xilinx_xmap       \
        -swap $__add_wrapper A,B ;;
../../_images/macc_xilinx_test2d.svg

Unwrap in test2:

../../_images/macc_xilinx_test2d.svg
techmap -map macc_xilinx_unwrap_map.v;;
../../_images/macc_xilinx_test2e.svg