Techmap by example¶
As a quick recap, the techmap
command replaces cells in the design
with implementations given as Verilog code (called “map files”). It can replace
Yosys’ internal cell types (such as $or
) as well as user-defined cell types.
Verilog parameters are used extensively to customize the internal cell types.
Additional special parameters are used by techmap to communicate meta-data to the map files.
Special wires are used to instruct techmap how to handle a module in the map file.
Generate blocks and recursion are powerful tools for writing map files.
Code examples used in this document are included in the Yosys code base under
docs/source/code_examples/techmap
.
Mapping OR3X1¶
Note
This is a simple example for demonstration only. Techmap shouldn’t be used to implement basic logic optimization.
module \$reduce_or (A, Y);
parameter A_SIGNED = 0;
parameter A_WIDTH = 0;
parameter Y_WIDTH = 0;
input [A_WIDTH-1:0] A;
output [Y_WIDTH-1:0] Y;
function integer min;
input integer a, b;
begin
if (a < b)
min = a;
else
min = b;
end
endfunction
genvar i;
generate begin
if (A_WIDTH == 0) begin
assign Y = 0;
end
if (A_WIDTH == 1) begin
assign Y = A;
end
if (A_WIDTH == 2) begin
wire ybuf;
OR3X1 g (.A(A[0]), .B(A[1]), .C(1'b0), .Y(ybuf));
assign Y = ybuf;
end
if (A_WIDTH == 3) begin
wire ybuf;
OR3X1 g (.A(A[0]), .B(A[1]), .C(A[2]), .Y(ybuf));
assign Y = ybuf;
end
if (A_WIDTH > 3) begin
localparam next_stage_sz = (A_WIDTH+2) / 3;
wire [next_stage_sz-1:0] next_stage;
for (i = 0; i < next_stage_sz; i = i+1) begin
localparam bits = min(A_WIDTH - 3*i, 3);
assign next_stage[i] = |A[3*i +: bits];
end
assign Y = |next_stage;
end
end endgenerate
endmodule
read_verilog red_or3x1_test.v
hierarchy -check -top test
techmap -map red_or3x1_map.v;;
splitnets -ports
show -prefix red_or3x1 -format dot -notitle -lib red_or3x1_cells.v
module test (A, Y);
input [6:0] A;
output Y;
assign Y = |A;
endmodule
Conditional techmap¶
In some cases only cells with certain properties should be substituted.
The special wire
_TECHMAP_FAIL_
can be used to disable a module in the map file for a certain set of parameters.The wire
_TECHMAP_FAIL_
must be set to a constant value. If it is non-zero then the module is disabled for this set of parameters.Example use-cases:
coarse-grain cell types that only operate on certain bit widths
memory resources for different memory geometries (width, depth, ports, etc.)
Example:
module \$mul (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 || B_WIDTH != Y_WIDTH;
MYMUL #( .WIDTH(Y_WIDTH) ) g ( .A(A), .B(B), .Y(Y) );
endmodule
module test(A, B, C, Y1, Y2);
input [7:0] A, B, C;
output [7:0] Y1 = A * B;
output [15:0] Y2 = A * C;
endmodule
read_verilog sym_mul_test.v
hierarchy -check -top test
techmap -map sym_mul_map.v;;
show -prefix sym_mul -format dot -notitle -lib sym_mul_cells.v
Scripting in map modules¶
The special wires
_TECHMAP_DO_*
can be used to run Yosys scripts in the context of the replacement module.The wire that comes first in alphabetical oder is interpreted as string (must be connected to constants) that is executed as script. Then the wire is removed. Repeat.
You can even call techmap recursively!
Example use-cases:
Note
PROTIP:
Commands such as shell
, show -pause
, and dump
can
be used in the _TECHMAP_DO_*
scripts for debugging map modules.
Example:
module MYMUL(A, B, Y);
parameter WIDTH = 1;
input [WIDTH-1:0] A, B;
output reg [WIDTH-1:0] Y;
wire [1023:0] _TECHMAP_DO_ = "proc; clean";
integer i;
always @* begin
Y = 0;
for (i = 0; i < WIDTH; i=i+1)
if (A[i])
Y = Y + (B << i);
end
endmodule
module test(A, B, Y);
input [1:0] A, B;
output [1:0] Y = A * B;
endmodule
read_verilog mymul_test.v
hierarchy -check -top test
techmap -map sym_mul_map.v \
-map mymul_map.v;;
rename test test_mapped
read_verilog mymul_test.v
miter -equiv test test_mapped miter
flatten miter
sat -verify -prove trigger 0 miter
splitnets -ports test_mapped/A
show -prefix mymul -format dot -notitle test_mapped
Handling constant inputs¶
The special parameters
_TECHMAP_CONSTMSK_<port-name>_
and_TECHMAP_CONSTVAL_<port-name>_
can be used to handle constant input values to cells.The former contains 1-bits for all constant input bits on the port.
The latter contains the constant bits or undef (x) for non-constant bits.
Example use-cases:
Converting arithmetic (for example multiply to shift).
Identify constant addresses or enable bits in memory interfaces.
Example:
module MYMUL(A, B, Y);
parameter WIDTH = 1;
input [WIDTH-1:0] A, B;
output reg [WIDTH-1:0] Y;
parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
reg _TECHMAP_FAIL_;
wire [1023:0] _TECHMAP_DO_ = "proc; clean";
integer i;
always @* begin
_TECHMAP_FAIL_ <= 1;
for (i = 0; i < WIDTH; i=i+1) begin
if (_TECHMAP_CONSTVAL_A_ === WIDTH'd1 << i) begin
_TECHMAP_FAIL_ <= 0;
Y <= B << i;
end
if (_TECHMAP_CONSTVAL_B_ === WIDTH'd1 << i) begin
_TECHMAP_FAIL_ <= 0;
Y <= A << i;
end
end
end
endmodule
module test (A, X, Y);
input [7:0] A;
output [7:0] X = A * 8'd 6;
output [7:0] Y = A * 8'd 8;
endmodule
read_verilog mulshift_test.v
hierarchy -check -top test
techmap -map sym_mul_map.v \
-map mulshift_map.v;;
show -prefix mulshift -format dot -notitle -lib sym_mul_cells.v
Handling shorted inputs¶
The special parameters
_TECHMAP_BITS_CONNMAP_
and_TECHMAP_CONNMAP_<port-name>_
can be used to handle shorted inputs.Each bit of the port correlates to an
_TECHMAP_BITS_CONNMAP_
bits wide number in_TECHMAP_CONNMAP_<port-name>_
.Each unique signal bit is assigned its own number. Identical fields in the
_TECHMAP_CONNMAP_<port-name>_
parameters mean shorted signal bits.The numbers 0-3 are reserved for
0
,1
,x
, andz
respectively.Example use-cases:
Detecting shared clock or control signals in memory interfaces.
In some cases this can be used for for optimization.
Example:
module \$add (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;
parameter _TECHMAP_BITS_CONNMAP_ = 0;
parameter _TECHMAP_CONNMAP_A_ = 0;
parameter _TECHMAP_CONNMAP_B_ = 0;
wire _TECHMAP_FAIL_ = A_WIDTH != B_WIDTH || B_WIDTH < Y_WIDTH ||
_TECHMAP_CONNMAP_A_ != _TECHMAP_CONNMAP_B_;
assign Y = A << 1;
endmodule
module test (A, B, X, Y);
input [7:0] A, B;
output [7:0] X = A + B;
output [7:0] Y = A + A;
endmodule
read_verilog addshift_test.v
hierarchy -check -top test
techmap -map addshift_map.v;;
show -prefix addshift -format dot -notitle
Notes on using techmap¶
Don’t use positional cell parameters in map modules.
You can use the
$__
-prefix for internal cell types to avoid collisions with the user-namespace. But always use two underscores or the internal consistency checker will trigger on these cells.Techmap has two major use cases:
Creating good logic-level representation of arithmetic functions. This also means using dedicated hardware resources such as half- and full-adder cells in ASICS or dedicated carry logic in FPGAs.
Mapping of coarse-grain resources such as block memory or DSP cells.