diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 3fc6ccb8e..dc52ca5fa 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -455,102 +455,8 @@ endmodule // Multiply // -------------------------------------------------------- -module \$__acc_set (acc_new, value); - parameter WIDTH = 1; - output reg [2*WIDTH-1:0] acc_new; - input [WIDTH-1:0] value; - - wire [1023:0] _TECHMAP_DO_ = "proc;;;"; - - integer k; - always @* begin - for (k = 0; k < WIDTH; k = k+1) begin - acc_new[2*k +: 2] = value[k]; - end - end -endmodule - -module \$__acc_add (acc_new, acc_old, value); - parameter WIDTH = 1; - output reg [2*WIDTH-1:0] acc_new; - input [2*WIDTH-1:0] acc_old; - input [WIDTH-1:0] value; - - wire [1023:0] _TECHMAP_DO_ = "proc; simplemap; opt -purge"; - - integer k; - reg a, b, c; - - always @* begin - for (k = 0; k < WIDTH; k = k+1) begin - a = acc_old[2*k]; - b = k ? acc_old[2*k-1] : 1'b0; - c = value[k]; - acc_new[2*k] = (a ^ b) ^ c; - acc_new[2*k+1] = (a & b) | ((a ^ b) & c); - end - end -endmodule - -module \$__acc_get (value, acc); - parameter WIDTH = 1; - output reg [WIDTH-1:0] value; - input [2*WIDTH-1:0] acc; - - wire [1023:0] _TECHMAP_DO_ = "proc;;;"; - - integer k; - - always @* begin - // at the end of the multiplier chain the carry-save accumulator - // should also have propagated all carries. thus we just need to - // copy the even bits from the carry accumulator to the output. - for (k = 0; k < WIDTH; k = k+1) begin - value[k] = acc[2*k]; - end - end -endmodule - -module \$__acc_mul (A, B, Y); - parameter WIDTH = 1; - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "proc;;"; - - integer i; - reg [WIDTH-1:0] x; - reg [2*WIDTH-1:0] y; - - (* via_celltype = "\\$__acc_set acc_new" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [2*WIDTH-1:0] acc_set; - input [WIDTH-1:0] value; - endfunction - - (* via_celltype = "\\$__acc_add acc_new" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [2*WIDTH-1:0] acc_add; - input [2*WIDTH-1:0] acc_old; - input [WIDTH-1:0] value; - endfunction - - (* via_celltype = "\\$__acc_get value" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [WIDTH-1:0] acc_get; - input [2*WIDTH-1:0] acc; - endfunction - - always @* begin - x = B; - y = acc_set(A[0] ? x : 1'b0); - for (i = 1; i < WIDTH; i = i+1) begin - x = {x[WIDTH-2:0], 1'b0}; - y = acc_add(y, A[i] ? x : 1'b0); - end - end - - assign Y = acc_get(y); +(* techmap_maccmap *) +module \$macc ; endmodule module \$mul (A, B, Y); @@ -566,105 +472,25 @@ module \$mul (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt -purge"; - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + localparam [ 3:0] CONFIG_WIDTH_BITS = 15; + localparam [ 0:0] CONFIG_IS_SIGNED = A_SIGNED && B_SIGNED; + localparam [ 0:0] CONFIG_DO_SUBTRACT = 0; + localparam [14:0] CONFIG_A_WIDTH = A_WIDTH; + localparam [14:0] CONFIG_B_WIDTH = B_WIDTH; - \$__acc_mul #( - .WIDTH(Y_WIDTH) + \$macc #( + .CONFIG({CONFIG_B_WIDTH, CONFIG_A_WIDTH, CONFIG_DO_SUBTRACT, CONFIG_IS_SIGNED, CONFIG_WIDTH_BITS}), + .CONFIG_WIDTH(15 + 15 + 2 + 4), + .A_WIDTH(B_WIDTH + A_WIDTH), + .B_WIDTH(0), + .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_buf), - .B(B_buf), + .A({B, A}), + .B(), .Y(Y) ); endmodule -module \$macc (A, B, Y); - parameter A_WIDTH = 0; - parameter B_WIDTH = 0; - parameter Y_WIDTH = 0; - parameter CONFIG = 4'b0000; - parameter CONFIG_WIDTH = 4; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output reg [Y_WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; - - localparam integer num_bits = CONFIG[3:0]; - localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); - localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; - - function [2*num_ports*num_abits-1:0] get_port_offsets; - input [CONFIG_WIDTH-1:0] cfg; - integer i, cursor; - begin - cursor = 0; - get_port_offsets = 0; - for (i = 0; i < num_ports; i = i+1) begin - get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; - get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; - end - end - endfunction - - localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); - - `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) - `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) - `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) - `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) - `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) - `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) - - integer i, j; - reg [Y_WIDTH-1:0] tmp_a, tmp_b; - - always @* begin - Y = 0; - for (i = 0; i < num_ports; i = i+1) - begin - tmp_a = 0; - tmp_b = 0; - - for (j = 0; j < `PORT_SIZE_A; j = j+1) - tmp_a[j] = A[`PORT_OFFSET_A + j]; - - if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) - for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) - tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; - - for (j = 0; j < `PORT_SIZE_B; j = j+1) - tmp_b[j] = A[`PORT_OFFSET_B + j]; - - if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) - for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) - tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; - - if (`PORT_SIZE_B > 0) - tmp_a = tmp_a * tmp_b; - - if (`PORT_DO_SUBTRACT) - Y = Y - tmp_a; - else - Y = Y + tmp_a; - end - for (i = 0; i < B_WIDTH; i = i+1) begin - Y = Y + B[i]; - end - end - - `undef PORT_IS_SIGNED - `undef PORT_DO_SUBTRACT - `undef PORT_SIZE_A - `undef PORT_SIZE_B - `undef PORT_OFFSET_A - `undef PORT_OFFSET_B -endmodule - // -------------------------------------------------------- // Divide and Modulo