Renamed "stdcells.v" to "techmap.v"
authorClifford Wolf <clifford@clifford.at>
Thu, 31 Jul 2014 00:32:00 +0000 (02:32 +0200)
committerClifford Wolf <clifford@clifford.at>
Thu, 31 Jul 2014 00:32:00 +0000 (02:32 +0200)
CHECKLISTS
README
manual/CHAPTER_Techmap.tex
passes/techmap/.gitignore
passes/techmap/Makefile.inc
passes/techmap/techmap.cc
techlibs/common/Makefile.inc
techlibs/common/simcells.v
techlibs/common/stdcells.v [deleted file]
techlibs/common/techmap.v [new file with mode: 0644]

index 8a149a539935bcdd60a3767983fdd69465ae2feb..3a06e61e07ff647a743b67795fb4a2cd18de30c8 100644 (file)
@@ -124,7 +124,7 @@ Things to do right away:
        - Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
        - Add to InternalCellChecker::check() in kernel/rtlil.cc
        - Add to techlibs/common/simlib.v
-       - Add to techlibs/common/stdcells.v
+       - Add to techlibs/common/techmap.v
 
 Things to do after finalizing the cell interface:
 
diff --git a/README b/README
index 4384cfbdd50753db4b41f94c88452f7dd96b36be..1e0ade91c2f0202d1299219b37a2e2a8ecc07c1a 100644 (file)
--- a/README
+++ b/README
@@ -304,8 +304,7 @@ Roadmap / Large-scale TODOs
    - yosys-bigsim: https://github.com/cliffordwolf/yosys-bigsim
 
 - Technology mapping for real-world applications
-   - Add bit-wise const-folding via cell parameters to techmap pass
-   - Rewrite current stdcells.v techmap rules (modular and clean)
+   - Rewrite current techmap.v rules (modular and clean)
    - Improve Xilinx FGPA synthesis (RAMB, CARRY4, SLR, etc.)
 
 - Implement SAT-based formal equivialence checker
index be74c35675e9ae821f1f360d0e15cc4806b4dbb7..26632d0b5dbea58661259b80f58b3f4049646548 100644 (file)
@@ -27,7 +27,7 @@ cells with the provided implementation.
 
 When no map file is provided, {\tt techmap} uses a built-in map file that
 maps the Yosys RTL cell types to the internal gate library used by Yosys.
-The curious reader may find this map file as {\tt techlibs/common/stdcells.v} in
+The curious reader may find this map file as {\tt techlibs/common/techmap.v} in
 the Yosys source tree.
 
 Additional features have been added to {\tt techmap} to allow for conditional
index ca9d3942cca97efbb1f254e2be54e64dae7bf1a7..e6dcc6bc0008ea104a53d29f3e52984e31720c8b 100644 (file)
@@ -1 +1 @@
-stdcells.inc
+techmap.inc
index e54c018aab72cd6607c26d4e3e65d866ee9c3204..b49259a8a83b15a354c1d19a38757891331a519e 100644 (file)
@@ -10,16 +10,16 @@ OBJS += passes/techmap/hilomap.o
 OBJS += passes/techmap/extract.o
 endif
 
-GENFILES += passes/techmap/stdcells.inc
+GENFILES += passes/techmap/techmap.inc
 
-passes/techmap/stdcells.inc: techlibs/common/stdcells.v
+passes/techmap/techmap.inc: techlibs/common/techmap.v
        $(P) echo "// autogenerated from $<" > $@.new
        $(Q) echo "static char stdcells_code[] = {" >> $@.new
        $(Q) od -v -td1 -An $< | $(SED) -e 's/[0-9][0-9]*/&,/g' >> $@.new
        $(Q) echo "0};" >> $@.new
        $(Q) mv $@.new $@
 
-passes/techmap/techmap.o: passes/techmap/stdcells.inc
+passes/techmap/techmap.o: passes/techmap/techmap.inc
 
 TARGETS += yosys-filterlib
 GENFILES += passes/techmap/filterlib.o
index 50936af0eeaa2e60a3fd7ccf241e8a18d3ed4a71..2aa59e61bde06362fd77c016a800f03ff8874f77 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "passes/techmap/stdcells.inc"
+#include "passes/techmap/techmap.inc"
 
 // see simplemap.cc
 extern void simplemap_get_mappers(std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
@@ -790,7 +790,7 @@ struct TechmapPass : public Pass {
                RTLIL::Design *map = new RTLIL::Design;
                if (map_files.empty()) {
                        FILE *f = fmemopen(stdcells_code, strlen(stdcells_code), "rt");
-                       Frontend::frontend_call(map, f, "<stdcells.v>", verilog_frontend);
+                       Frontend::frontend_call(map, f, "<techmap.v>", verilog_frontend);
                        fclose(f);
                } else
                        for (auto &fn : map_files)
index a76d1a079d79dc9c4e741ad9c52ab0a4e0a64c2f..2be27b9202bd6d10ad94a5e7e5faa5f6924b1c5b 100644 (file)
@@ -5,7 +5,7 @@ techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib.
        $(P) cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new
        $(Q) mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v
 
-EXTRA_TARGETS += share/simlib.v share/simcells.v share/blackbox.v share/pmux2mux.v
+EXTRA_TARGETS += share/simlib.v share/simcells.v share/techmap.v share/blackbox.v share/pmux2mux.v
 
 share/simlib.v: techlibs/common/simlib.v
        $(P) mkdir -p share
@@ -15,6 +15,10 @@ share/simcells.v: techlibs/common/simcells.v
        $(P) mkdir -p share
        $(Q) cp techlibs/common/simcells.v share/simcells.v
 
+share/techmap.v: techlibs/common/techmap.v
+       $(P) mkdir -p share
+       $(Q) cp techlibs/common/techmap.v share/techmap.v
+
 share/blackbox.v: techlibs/common/blackbox.v
        $(P) mkdir -p share
        $(Q) cp techlibs/common/blackbox.v share/blackbox.v
index 5ecec7891708ff447e20eb790489f23317da00b5..d492c2f15fcea81c8474e44db3f3e4a81b4ad2cb 100644 (file)
@@ -21,7 +21,7 @@
  *
  *  This verilog library contains simple simulation models for the internal
  *  logic cells ($_INV_ , $_AND_ , ...) that are generated by the default technology
- *  mapper (see "stdcells.v" in this directory) and expected by the "abc" pass.
+ *  mapper (see "techmap.v" in this directory) and expected by the "abc" pass.
  *
  */
 
diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v
deleted file mode 100644 (file)
index 5465286..0000000
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- *  yosys -- Yosys Open SYnthesis Suite
- *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  
- *  Permission to use, copy, modify, and/or distribute this software for any
- *  purpose with or without fee is hereby granted, provided that the above
- *  copyright notice and this permission notice appear in all copies.
- *  
- *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- *  ---
- *
- *  The internal logic cell technology mapper.
- *
- *  This verilog library contains the mapping of internal cells (e.g. $not with
- *  variable bit width) to the internal logic cells (such as the single bit $_INV_ 
- *  gate). Usually this logic network is then mapped to the actual technology
- *  using e.g. the "abc" pass.
- *
- *  Note that this library does not map $mem cells. They must be mapped to logic
- *  and $dff cells using the "memory_map" pass first. (Or map it to custom cells,
- *  which is of course highly recommended for larger memories.)
- *
- */
-
-`define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
-`define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
-
-
-// --------------------------------------------------------
-// Use simplemap for trivial cell types
-// --------------------------------------------------------
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$pos $bu0" *)
-module simplemap_buffers;
-endmodule
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$not $and $or $xor $xnor" *)
-module simplemap_bool_ops;
-endmodule
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *)
-module simplemap_reduce_ops;
-endmodule
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$logic_not $logic_and $logic_or" *)
-module simplemap_logic_ops;
-endmodule
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$slice $concat $mux" *)
-module simplemap_various;
-endmodule
-
-(* techmap_simplemap *)
-(* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *)
-module simplemap_registers;
-endmodule
-
-
-// --------------------------------------------------------
-// Trivial substitutions
-// --------------------------------------------------------
-
-module \$neg (A, Y);
-       parameter A_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       input [A_WIDTH-1:0] A;
-       output [Y_WIDTH-1:0] Y;
-
-       \$sub #(
-               .A_SIGNED(A_SIGNED),
-               .B_SIGNED(A_SIGNED),
-               .A_WIDTH(1),
-               .B_WIDTH(A_WIDTH),
-               .Y_WIDTH(Y_WIDTH)
-       ) _TECHMAP_REPLACE_ (
-               .A(1'b0),
-               .B(A),
-               .Y(Y)
-       );
-endmodule
-
-module \$ge (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;
-
-       \$le #(
-               .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
-
-module \$gt (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;
-
-       \$lt #(
-               .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
-
-
-// --------------------------------------------------------
-// Shift operators
-// --------------------------------------------------------
-
-(* techmap_celltype = "$shr $shl $sshl $sshr" *)
-module shift_ops_shr_shl_sshl_sshr (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       parameter _TECHMAP_CELLTYPE_ = "";
-       localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl";
-       localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr";
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH);
-       localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH);
-
-       wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
-       wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;";
-
-       integer i;
-       reg [WIDTH-1:0] buffer;
-       reg overflow;
-
-       always @* begin
-               overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0;
-               buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A};
-
-               for (i = 0; i < BB_WIDTH; i = i+1)
-                       if (B[i]) begin
-                               if (shift_left)
-                                       buffer = {buffer, (2**i)'b0};
-                               else if (2**i < WIDTH)
-                                       buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]};
-                               else
-                                       buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}};
-                       end
-       end
-
-       assign Y = buffer;
-endmodule
-
-(* techmap_celltype = "$shift $shiftx" *)
-module shift_shiftx (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;
-
-       localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
-       localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
-
-       parameter _TECHMAP_CELLTYPE_ = "";
-       localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx;
-
-       wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
-       wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;";
-
-       integer i;
-       reg [WIDTH-1:0] buffer;
-       reg overflow;
-
-       always @* begin
-               overflow = 0;
-               buffer = {WIDTH{extbit}};
-               buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A;
-
-               if (B_WIDTH > BB_WIDTH) begin
-                       if (B_SIGNED) begin
-                               for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
-                                       if (B[i] != B[BB_WIDTH-1])
-                                               overflow = 1;
-                       end else
-                               overflow = |B[B_WIDTH-1:BB_WIDTH];
-                       if (overflow)
-                               buffer = {WIDTH{extbit}};
-               end
-
-               for (i = BB_WIDTH-1; i >= 0; i = i-1)
-                       if (B[i]) begin
-                               if (B_SIGNED && i == BB_WIDTH-1)
-                                       buffer = {buffer, {2**i{extbit}}};
-                               else if (2**i < WIDTH)
-                                       buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
-                               else
-                                       buffer = {WIDTH{extbit}};
-                       end
-       end
-
-       assign Y = buffer;
-endmodule
-
-
-// --------------------------------------------------------
-// ALU Infrastructure
-// --------------------------------------------------------
-
-module \$__fulladd (A, B, C, X, Y);
-       // {X, Y} = A + B + C
-       input A, B, C;
-       output X, Y;
-
-       // {t1, t2} = A + B
-       wire t1, t2, t3;
-
-       \$_AND_ gate1 ( .A(A),  .B(B),  .Y(t1) );
-       \$_XOR_ gate2 ( .A(A),  .B(B),  .Y(t2) );
-       \$_AND_ gate3 ( .A(t2), .B(C),  .Y(t3) ); 
-       \$_XOR_ gate4 ( .A(t2), .B(C),  .Y(Y)  );
-       \$_OR_  gate5 ( .A(t1), .B(t3), .Y(X)  );
-endmodule
-
-module \$__alu (A, B, Cin, Y, Cout, Csign);
-       parameter WIDTH = 1;
-
-       input [WIDTH-1:0] A, B;
-       input Cin;
-
-       output [WIDTH-1:0] Y;
-       output Cout, Csign;
-
-       wire [WIDTH:0] carry;
-       assign carry[0] = Cin;
-       assign Cout = carry[WIDTH];
-       assign Csign = carry[WIDTH-1];
-
-       genvar i;
-       generate
-               for (i = 0; i < WIDTH; i = i + 1) begin:V
-                       \$__fulladd adder (
-                               .A(A[i]),
-                               .B(B[i]),
-                               .C(carry[i]),
-                               .X(carry[i+1]),
-                               .Y(Y[i])
-                       );
-               end
-       endgenerate
-endmodule
-
-
-// --------------------------------------------------------
-// Compare cells
-// --------------------------------------------------------
-
-module \$lt (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf, Y_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       \$__alu #(
-               .WIDTH(WIDTH)
-       ) alu (
-               .A(A_buf),
-               .B(~B_buf),
-               .Cin(1'b1),
-               .Y(Y_buf),
-               .Cout(carry),
-               .Csign(carry_sign)
-       );
-
-       // ALU flags
-       wire cf, of, zf, sf;
-       assign cf = !carry;
-       assign of = carry ^ carry_sign;
-       assign zf = ~|Y_buf;
-       assign sf = Y_buf[WIDTH-1];
-
-       generate
-               if (A_SIGNED && B_SIGNED) begin
-                       assign Y = of != sf;
-               end else begin
-                       assign Y = cf;
-               end
-       endgenerate
-endmodule
-
-module \$le (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf, Y_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       \$__alu #(
-               .WIDTH(WIDTH)
-       ) alu (
-               .A(A_buf),
-               .B(~B_buf),
-               .Cin(1'b1),
-               .Y(Y_buf),
-               .Cout(carry),
-               .Csign(carry_sign)
-       );
-
-       // ALU flags
-       wire cf, of, zf, sf;
-       assign cf = !carry;
-       assign of = carry ^ carry_sign;
-       assign zf = ~|Y_buf;
-       assign sf = Y_buf[WIDTH-1];
-
-       generate
-               if (A_SIGNED && B_SIGNED) begin
-                       assign Y = zf || (of != sf);
-               end else begin
-                       assign Y = zf || cf;
-               end
-       endgenerate
-endmodule
-
-
-// --------------------------------------------------------
-// Add and Subtract
-// --------------------------------------------------------
-
-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;
-
-       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));
-
-       \$__alu #(
-               .WIDTH(Y_WIDTH)
-       ) alu (
-               .A(A_buf),
-               .B(B_buf),
-               .Cin(1'b0),
-               .Y(Y)
-       );
-endmodule
-
-module \$sub (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 [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));
-
-       \$__alu #(
-               .WIDTH(Y_WIDTH)
-       ) alu (
-               .A(A_buf),
-               .B(~B_buf),
-               .Cin(1'b1),
-               .Y(Y)
-       );
-endmodule
-
-
-// --------------------------------------------------------
-// Multiply
-// --------------------------------------------------------
-
-module \$__arraymul (A, B, Y);
-       parameter WIDTH = 8;
-       input [WIDTH-1:0] A, B;
-       output [WIDTH-1:0] Y;
-
-       wire [WIDTH*WIDTH-1:0] partials;
-
-       genvar i;
-       assign partials[WIDTH-1 : 0] = A[0] ? B : 0;
-       generate for (i = 1; i < WIDTH; i = i+1) begin:gen
-               assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)];
-       end endgenerate
-
-       assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)];
-endmodule
-
-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 [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));
-
-       \$__arraymul #(
-               .WIDTH(Y_WIDTH)
-       ) arraymul (
-               .A(A_buf),
-               .B(B_buf),
-               .Y(Y)
-       );
-endmodule
-
-
-// --------------------------------------------------------
-// Divide and Modulo
-// --------------------------------------------------------
-
-module \$__div_mod_u (A, B, Y, R);
-       parameter WIDTH = 1;
-
-       input [WIDTH-1:0] A, B;
-       output [WIDTH-1:0] Y, R;
-
-       wire [WIDTH*WIDTH-1:0] chaindata;
-       assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)];
-
-       genvar i;
-       generate begin
-               for (i = 0; i < WIDTH; i=i+1) begin:stage
-                       wire [WIDTH-1:0] stage_in;
-
-                       if (i == 0) begin:cp
-                               assign stage_in = A;
-                       end else begin:cp
-                               assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH];
-                       end
-
-                       assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}};
-                       assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in;
-               end
-       end endgenerate
-endmodule
-
-module \$__div_mod (A, B, Y, R);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH =
-                       A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH :
-                       B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y, R;
-
-       wire [WIDTH-1:0] A_buf, B_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u;
-       assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf;
-       assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf;
-
-       \$__div_mod_u #(
-               .WIDTH(WIDTH)
-       ) div_mod_u (
-               .A(A_buf_u),
-               .B(B_buf_u),
-               .Y(Y_u),
-               .R(R_u)
-       );
-
-       assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u;
-       assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u;
-endmodule
-
-module \$div (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;
-
-       \$__div_mod #(
-               .A_SIGNED(A_SIGNED),
-               .B_SIGNED(B_SIGNED),
-               .A_WIDTH(A_WIDTH),
-               .B_WIDTH(B_WIDTH),
-               .Y_WIDTH(Y_WIDTH)
-       ) div_mod (
-               .A(A),
-               .B(B),
-               .Y(Y)
-       );
-endmodule
-
-module \$mod (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;
-
-       \$__div_mod #(
-               .A_SIGNED(A_SIGNED),
-               .B_SIGNED(B_SIGNED),
-               .A_WIDTH(A_WIDTH),
-               .B_WIDTH(B_WIDTH),
-               .Y_WIDTH(Y_WIDTH)
-       ) div_mod (
-               .A(A),
-               .B(B),
-               .R(Y)
-       );
-endmodule
-
-
-// --------------------------------------------------------
-// Power
-// --------------------------------------------------------
-
-module \$pow (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_ = 1;
-endmodule
-
-
-// --------------------------------------------------------
-// Equal and Not-Equal
-// --------------------------------------------------------
-
-module \$eq (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf;
-       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       assign Y = ~|(A_buf ^ B_buf);
-endmodule
-
-module \$ne (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf;
-       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       assign Y = |(A_buf ^ B_buf);
-endmodule
-
-module \$eqx (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       assign Y = ~|(A_buf ^ B_buf);
-endmodule
-
-module \$nex (A, B, Y);
-       parameter A_SIGNED = 0;
-       parameter B_SIGNED = 0;
-       parameter A_WIDTH = 1;
-       parameter B_WIDTH = 1;
-       parameter Y_WIDTH = 1;
-
-       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
-
-       input [A_WIDTH-1:0] A;
-       input [B_WIDTH-1:0] B;
-       output [Y_WIDTH-1:0] Y;
-
-       wire carry, carry_sign;
-       wire [WIDTH-1:0] A_buf, B_buf;
-       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
-       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
-
-       assign Y = |(A_buf ^ B_buf);
-endmodule
-
-
-// --------------------------------------------------------
-// Parallel Multiplexers
-// --------------------------------------------------------
-
-module \$pmux (A, B, S, Y);
-       parameter WIDTH = 1;
-       parameter S_WIDTH = 1;
-
-       input [WIDTH-1:0] A;
-       input [WIDTH*S_WIDTH-1:0] B;
-       input [S_WIDTH-1:0] S;
-       output [WIDTH-1:0] Y;
-
-       wire [WIDTH-1:0] Y_B;
-
-       genvar i, j;
-       generate
-               wire [WIDTH*S_WIDTH-1:0] B_AND_S;
-               for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND
-                       assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}};
-               end:B_AND
-               for (i = 0; i < WIDTH; i = i + 1) begin:B_OR
-                       wire [S_WIDTH-1:0] B_AND_BITS;
-                       for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT
-                               assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i];
-                       end:B_AND_BITS_COLLECT
-                       assign Y_B[i] = |B_AND_BITS;
-               end:B_OR
-       endgenerate
-
-       assign Y = |S ? Y_B : A;
-endmodule
-
-module \$safe_pmux (A, B, S, Y);
-       parameter WIDTH = 1;
-       parameter S_WIDTH = 1;
-
-       input [WIDTH-1:0] A;
-       input [WIDTH*S_WIDTH-1:0] B;
-       input [S_WIDTH-1:0] S;
-       output [WIDTH-1:0] Y;
-
-       wire [S_WIDTH-1:0] status_found_first;
-       wire [S_WIDTH-1:0] status_found_second;
-
-       genvar i;
-       generate
-               for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1
-                       wire pre_first;
-                       if (i > 0) begin:GEN2
-                               assign pre_first = status_found_first[i-1];
-                       end:GEN2 else begin:GEN3
-                               assign pre_first = 0;
-                       end:GEN3
-                       assign status_found_first[i] = pre_first | S[i];
-                       assign status_found_second[i] = pre_first & S[i];
-               end:GEN1
-       endgenerate
-
-       \$pmux #(
-               .WIDTH(WIDTH),
-               .S_WIDTH(S_WIDTH)
-       ) pmux_cell (
-               .A(A),
-               .B(B),
-               .S(S & {S_WIDTH{~|status_found_second}}),
-               .Y(Y)
-       );
-endmodule
-
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
new file mode 100644 (file)
index 0000000..5465286
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *  
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *  ---
+ *
+ *  The internal logic cell technology mapper.
+ *
+ *  This verilog library contains the mapping of internal cells (e.g. $not with
+ *  variable bit width) to the internal logic cells (such as the single bit $_INV_ 
+ *  gate). Usually this logic network is then mapped to the actual technology
+ *  using e.g. the "abc" pass.
+ *
+ *  Note that this library does not map $mem cells. They must be mapped to logic
+ *  and $dff cells using the "memory_map" pass first. (Or map it to custom cells,
+ *  which is of course highly recommended for larger memories.)
+ *
+ */
+
+`define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+`define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
+
+
+// --------------------------------------------------------
+// Use simplemap for trivial cell types
+// --------------------------------------------------------
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$pos $bu0" *)
+module simplemap_buffers;
+endmodule
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$not $and $or $xor $xnor" *)
+module simplemap_bool_ops;
+endmodule
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *)
+module simplemap_reduce_ops;
+endmodule
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$logic_not $logic_and $logic_or" *)
+module simplemap_logic_ops;
+endmodule
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$slice $concat $mux" *)
+module simplemap_various;
+endmodule
+
+(* techmap_simplemap *)
+(* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *)
+module simplemap_registers;
+endmodule
+
+
+// --------------------------------------------------------
+// Trivial substitutions
+// --------------------------------------------------------
+
+module \$neg (A, Y);
+       parameter A_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       input [A_WIDTH-1:0] A;
+       output [Y_WIDTH-1:0] Y;
+
+       \$sub #(
+               .A_SIGNED(A_SIGNED),
+               .B_SIGNED(A_SIGNED),
+               .A_WIDTH(1),
+               .B_WIDTH(A_WIDTH),
+               .Y_WIDTH(Y_WIDTH)
+       ) _TECHMAP_REPLACE_ (
+               .A(1'b0),
+               .B(A),
+               .Y(Y)
+       );
+endmodule
+
+module \$ge (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;
+
+       \$le #(
+               .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
+
+module \$gt (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;
+
+       \$lt #(
+               .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
+
+
+// --------------------------------------------------------
+// Shift operators
+// --------------------------------------------------------
+
+(* techmap_celltype = "$shr $shl $sshl $sshr" *)
+module shift_ops_shr_shl_sshl_sshr (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       parameter _TECHMAP_CELLTYPE_ = "";
+       localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl";
+       localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr";
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH);
+       localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH);
+
+       wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
+       wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;";
+
+       integer i;
+       reg [WIDTH-1:0] buffer;
+       reg overflow;
+
+       always @* begin
+               overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0;
+               buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A};
+
+               for (i = 0; i < BB_WIDTH; i = i+1)
+                       if (B[i]) begin
+                               if (shift_left)
+                                       buffer = {buffer, (2**i)'b0};
+                               else if (2**i < WIDTH)
+                                       buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]};
+                               else
+                                       buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}};
+                       end
+       end
+
+       assign Y = buffer;
+endmodule
+
+(* techmap_celltype = "$shift $shiftx" *)
+module shift_shiftx (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;
+
+       localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
+       localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
+
+       parameter _TECHMAP_CELLTYPE_ = "";
+       localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx;
+
+       wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
+       wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;";
+
+       integer i;
+       reg [WIDTH-1:0] buffer;
+       reg overflow;
+
+       always @* begin
+               overflow = 0;
+               buffer = {WIDTH{extbit}};
+               buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A;
+
+               if (B_WIDTH > BB_WIDTH) begin
+                       if (B_SIGNED) begin
+                               for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
+                                       if (B[i] != B[BB_WIDTH-1])
+                                               overflow = 1;
+                       end else
+                               overflow = |B[B_WIDTH-1:BB_WIDTH];
+                       if (overflow)
+                               buffer = {WIDTH{extbit}};
+               end
+
+               for (i = BB_WIDTH-1; i >= 0; i = i-1)
+                       if (B[i]) begin
+                               if (B_SIGNED && i == BB_WIDTH-1)
+                                       buffer = {buffer, {2**i{extbit}}};
+                               else if (2**i < WIDTH)
+                                       buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
+                               else
+                                       buffer = {WIDTH{extbit}};
+                       end
+       end
+
+       assign Y = buffer;
+endmodule
+
+
+// --------------------------------------------------------
+// ALU Infrastructure
+// --------------------------------------------------------
+
+module \$__fulladd (A, B, C, X, Y);
+       // {X, Y} = A + B + C
+       input A, B, C;
+       output X, Y;
+
+       // {t1, t2} = A + B
+       wire t1, t2, t3;
+
+       \$_AND_ gate1 ( .A(A),  .B(B),  .Y(t1) );
+       \$_XOR_ gate2 ( .A(A),  .B(B),  .Y(t2) );
+       \$_AND_ gate3 ( .A(t2), .B(C),  .Y(t3) ); 
+       \$_XOR_ gate4 ( .A(t2), .B(C),  .Y(Y)  );
+       \$_OR_  gate5 ( .A(t1), .B(t3), .Y(X)  );
+endmodule
+
+module \$__alu (A, B, Cin, Y, Cout, Csign);
+       parameter WIDTH = 1;
+
+       input [WIDTH-1:0] A, B;
+       input Cin;
+
+       output [WIDTH-1:0] Y;
+       output Cout, Csign;
+
+       wire [WIDTH:0] carry;
+       assign carry[0] = Cin;
+       assign Cout = carry[WIDTH];
+       assign Csign = carry[WIDTH-1];
+
+       genvar i;
+       generate
+               for (i = 0; i < WIDTH; i = i + 1) begin:V
+                       \$__fulladd adder (
+                               .A(A[i]),
+                               .B(B[i]),
+                               .C(carry[i]),
+                               .X(carry[i+1]),
+                               .Y(Y[i])
+                       );
+               end
+       endgenerate
+endmodule
+
+
+// --------------------------------------------------------
+// Compare cells
+// --------------------------------------------------------
+
+module \$lt (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf, Y_buf;
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       \$__alu #(
+               .WIDTH(WIDTH)
+       ) alu (
+               .A(A_buf),
+               .B(~B_buf),
+               .Cin(1'b1),
+               .Y(Y_buf),
+               .Cout(carry),
+               .Csign(carry_sign)
+       );
+
+       // ALU flags
+       wire cf, of, zf, sf;
+       assign cf = !carry;
+       assign of = carry ^ carry_sign;
+       assign zf = ~|Y_buf;
+       assign sf = Y_buf[WIDTH-1];
+
+       generate
+               if (A_SIGNED && B_SIGNED) begin
+                       assign Y = of != sf;
+               end else begin
+                       assign Y = cf;
+               end
+       endgenerate
+endmodule
+
+module \$le (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf, Y_buf;
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       \$__alu #(
+               .WIDTH(WIDTH)
+       ) alu (
+               .A(A_buf),
+               .B(~B_buf),
+               .Cin(1'b1),
+               .Y(Y_buf),
+               .Cout(carry),
+               .Csign(carry_sign)
+       );
+
+       // ALU flags
+       wire cf, of, zf, sf;
+       assign cf = !carry;
+       assign of = carry ^ carry_sign;
+       assign zf = ~|Y_buf;
+       assign sf = Y_buf[WIDTH-1];
+
+       generate
+               if (A_SIGNED && B_SIGNED) begin
+                       assign Y = zf || (of != sf);
+               end else begin
+                       assign Y = zf || cf;
+               end
+       endgenerate
+endmodule
+
+
+// --------------------------------------------------------
+// Add and Subtract
+// --------------------------------------------------------
+
+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;
+
+       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));
+
+       \$__alu #(
+               .WIDTH(Y_WIDTH)
+       ) alu (
+               .A(A_buf),
+               .B(B_buf),
+               .Cin(1'b0),
+               .Y(Y)
+       );
+endmodule
+
+module \$sub (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 [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));
+
+       \$__alu #(
+               .WIDTH(Y_WIDTH)
+       ) alu (
+               .A(A_buf),
+               .B(~B_buf),
+               .Cin(1'b1),
+               .Y(Y)
+       );
+endmodule
+
+
+// --------------------------------------------------------
+// Multiply
+// --------------------------------------------------------
+
+module \$__arraymul (A, B, Y);
+       parameter WIDTH = 8;
+       input [WIDTH-1:0] A, B;
+       output [WIDTH-1:0] Y;
+
+       wire [WIDTH*WIDTH-1:0] partials;
+
+       genvar i;
+       assign partials[WIDTH-1 : 0] = A[0] ? B : 0;
+       generate for (i = 1; i < WIDTH; i = i+1) begin:gen
+               assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)];
+       end endgenerate
+
+       assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)];
+endmodule
+
+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 [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));
+
+       \$__arraymul #(
+               .WIDTH(Y_WIDTH)
+       ) arraymul (
+               .A(A_buf),
+               .B(B_buf),
+               .Y(Y)
+       );
+endmodule
+
+
+// --------------------------------------------------------
+// Divide and Modulo
+// --------------------------------------------------------
+
+module \$__div_mod_u (A, B, Y, R);
+       parameter WIDTH = 1;
+
+       input [WIDTH-1:0] A, B;
+       output [WIDTH-1:0] Y, R;
+
+       wire [WIDTH*WIDTH-1:0] chaindata;
+       assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)];
+
+       genvar i;
+       generate begin
+               for (i = 0; i < WIDTH; i=i+1) begin:stage
+                       wire [WIDTH-1:0] stage_in;
+
+                       if (i == 0) begin:cp
+                               assign stage_in = A;
+                       end else begin:cp
+                               assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH];
+                       end
+
+                       assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}};
+                       assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in;
+               end
+       end endgenerate
+endmodule
+
+module \$__div_mod (A, B, Y, R);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH =
+                       A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH :
+                       B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y, R;
+
+       wire [WIDTH-1:0] A_buf, B_buf;
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u;
+       assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf;
+       assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf;
+
+       \$__div_mod_u #(
+               .WIDTH(WIDTH)
+       ) div_mod_u (
+               .A(A_buf_u),
+               .B(B_buf_u),
+               .Y(Y_u),
+               .R(R_u)
+       );
+
+       assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u;
+       assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u;
+endmodule
+
+module \$div (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;
+
+       \$__div_mod #(
+               .A_SIGNED(A_SIGNED),
+               .B_SIGNED(B_SIGNED),
+               .A_WIDTH(A_WIDTH),
+               .B_WIDTH(B_WIDTH),
+               .Y_WIDTH(Y_WIDTH)
+       ) div_mod (
+               .A(A),
+               .B(B),
+               .Y(Y)
+       );
+endmodule
+
+module \$mod (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;
+
+       \$__div_mod #(
+               .A_SIGNED(A_SIGNED),
+               .B_SIGNED(B_SIGNED),
+               .A_WIDTH(A_WIDTH),
+               .B_WIDTH(B_WIDTH),
+               .Y_WIDTH(Y_WIDTH)
+       ) div_mod (
+               .A(A),
+               .B(B),
+               .R(Y)
+       );
+endmodule
+
+
+// --------------------------------------------------------
+// Power
+// --------------------------------------------------------
+
+module \$pow (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_ = 1;
+endmodule
+
+
+// --------------------------------------------------------
+// Equal and Not-Equal
+// --------------------------------------------------------
+
+module \$eq (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf;
+       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       assign Y = ~|(A_buf ^ B_buf);
+endmodule
+
+module \$ne (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf;
+       \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       assign Y = |(A_buf ^ B_buf);
+endmodule
+
+module \$eqx (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf;
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       assign Y = ~|(A_buf ^ B_buf);
+endmodule
+
+module \$nex (A, B, Y);
+       parameter A_SIGNED = 0;
+       parameter B_SIGNED = 0;
+       parameter A_WIDTH = 1;
+       parameter B_WIDTH = 1;
+       parameter Y_WIDTH = 1;
+
+       localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+       input [A_WIDTH-1:0] A;
+       input [B_WIDTH-1:0] B;
+       output [Y_WIDTH-1:0] Y;
+
+       wire carry, carry_sign;
+       wire [WIDTH-1:0] A_buf, B_buf;
+       \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+       \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+       assign Y = |(A_buf ^ B_buf);
+endmodule
+
+
+// --------------------------------------------------------
+// Parallel Multiplexers
+// --------------------------------------------------------
+
+module \$pmux (A, B, S, Y);
+       parameter WIDTH = 1;
+       parameter S_WIDTH = 1;
+
+       input [WIDTH-1:0] A;
+       input [WIDTH*S_WIDTH-1:0] B;
+       input [S_WIDTH-1:0] S;
+       output [WIDTH-1:0] Y;
+
+       wire [WIDTH-1:0] Y_B;
+
+       genvar i, j;
+       generate
+               wire [WIDTH*S_WIDTH-1:0] B_AND_S;
+               for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND
+                       assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}};
+               end:B_AND
+               for (i = 0; i < WIDTH; i = i + 1) begin:B_OR
+                       wire [S_WIDTH-1:0] B_AND_BITS;
+                       for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT
+                               assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i];
+                       end:B_AND_BITS_COLLECT
+                       assign Y_B[i] = |B_AND_BITS;
+               end:B_OR
+       endgenerate
+
+       assign Y = |S ? Y_B : A;
+endmodule
+
+module \$safe_pmux (A, B, S, Y);
+       parameter WIDTH = 1;
+       parameter S_WIDTH = 1;
+
+       input [WIDTH-1:0] A;
+       input [WIDTH*S_WIDTH-1:0] B;
+       input [S_WIDTH-1:0] S;
+       output [WIDTH-1:0] Y;
+
+       wire [S_WIDTH-1:0] status_found_first;
+       wire [S_WIDTH-1:0] status_found_second;
+
+       genvar i;
+       generate
+               for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1
+                       wire pre_first;
+                       if (i > 0) begin:GEN2
+                               assign pre_first = status_found_first[i-1];
+                       end:GEN2 else begin:GEN3
+                               assign pre_first = 0;
+                       end:GEN3
+                       assign status_found_first[i] = pre_first | S[i];
+                       assign status_found_second[i] = pre_first & S[i];
+               end:GEN1
+       endgenerate
+
+       \$pmux #(
+               .WIDTH(WIDTH),
+               .S_WIDTH(S_WIDTH)
+       ) pmux_cell (
+               .A(A),
+               .B(B),
+               .S(S & {S_WIDTH{~|status_found_second}}),
+               .Y(Y)
+       );
+endmodule
+