Proper arith for Anlogic and use standard pass
authorMiodrag Milanovic <mmicko@gmail.com>
Mon, 12 Aug 2019 18:19:54 +0000 (20:19 +0200)
committerMiodrag Milanovic <mmicko@gmail.com>
Mon, 12 Aug 2019 18:21:36 +0000 (20:21 +0200)
techlibs/anlogic/Makefile.inc
techlibs/anlogic/anlogic_determine_init.cc [deleted file]
techlibs/anlogic/anlogic_fixcarry.cc [new file with mode: 0644]
techlibs/anlogic/arith_map.v
techlibs/anlogic/synth_anlogic.cc

index 67cf9cf103bc4dff9cfc7721ed0b1ef4445a197c..9426b5ca545345547e228bfbcba2453edceedea1 100644 (file)
@@ -1,7 +1,7 @@
 
 OBJS += techlibs/anlogic/synth_anlogic.o
 OBJS += techlibs/anlogic/anlogic_eqn.o
-OBJS += techlibs/anlogic/anlogic_determine_init.o
+OBJS += techlibs/anlogic/anlogic_fixcarry.o
 
 $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
 $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
diff --git a/techlibs/anlogic/anlogic_determine_init.cc b/techlibs/anlogic/anlogic_determine_init.cc
deleted file mode 100644 (file)
index c4089da..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  yosys -- Yosys Open SYnthesis Suite
- *
- *  Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
- *
- *  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.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct AnlogicDetermineInitPass : public Pass {
-       AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
-       void help() YS_OVERRIDE
-       {
-               log("\n");
-               log("    anlogic_determine_init [selection]\n");
-               log("\n");
-               log("Determine the init value of cells that doesn't allow unknown init value.\n");
-               log("\n");
-       }
-
-       Const determine_init(Const init)
-       {
-               for (int i = 0; i < GetSize(init); i++) {
-                       if (init[i] != State::S0 && init[i] != State::S1)
-                               init[i] = State::S0;
-               }
-
-               return init;
-       }
-
-       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
-       {
-               log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n");
-
-               extra_args(args, args.size(), design);
-
-               int cnt = 0;
-               for (auto module : design->selected_modules())
-               {
-                       for (auto cell : module->selected_cells())
-                       {
-                               if (cell->type == "\\EG_LOGIC_DRAM16X4")
-                               {
-                                       cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
-                                       cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
-                                       cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
-                                       cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
-                                       cnt++;
-                               }
-                       }
-               }
-               log_header(design, "Updated %d cells with determined init value.\n", cnt);
-       }
-} AnlogicDetermineInitPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc
new file mode 100644 (file)
index 0000000..87164d3
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2019  Miodrag Milanovic <miodrag@symbioticeda.com>
+ *
+ *  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.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+       if (GetSize(sig) == 0)
+               return State::S0;
+       return sig[0];
+}
+
+static void fix_carry_chain(Module *module)
+{
+       SigMap sigmap(module);
+
+       pool<SigBit> ci_bits;
+       dict<SigBit, SigBit> mapping_bits;
+
+       for (auto cell : module->cells())
+       {
+               if (cell->type == "\\AL_MAP_ADDER") {
+                       if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
+                       SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
+                       SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));
+                       if (bit_i0 == State::S0 && bit_i1== State::S0) {
+                               SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+                               SigSpec o = cell->getPort("\\o");
+                               if (GetSize(o) == 2) {
+                                       SigBit bit_o = o[0];
+                                       ci_bits.insert(bit_ci);                         
+                                       mapping_bits[bit_ci] = bit_o;                           
+                               }
+                       }
+               }
+       }
+       vector<Cell*> adders_to_fix_cells;
+       for (auto cell : module->cells())
+       {
+               if (cell->type == "\\AL_MAP_ADDER") {
+                       if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue;
+                       SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+                       SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a"));
+                       SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b"));                  
+                       SigBit canonical_bit = sigmap(bit_ci);
+                       if (!ci_bits.count(canonical_bit))
+                               continue;                       
+                       if (bit_i0 == State::S0 && bit_i1== State::S0) 
+                               continue;
+
+                       adders_to_fix_cells.push_back(cell);
+                       log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell));
+               }
+       }
+
+       for (auto cell : adders_to_fix_cells)
+       {
+               SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c"));
+               SigBit canonical_bit = sigmap(bit_ci);
+               auto bit = mapping_bits.at(canonical_bit);
+               log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell));
+               Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER");
+               SigBit new_bit = module->addWire(NEW_ID);
+               SigBit dummy_bit = module->addWire(NEW_ID);
+               SigSpec bits;
+               bits.append(dummy_bit);
+               bits.append(new_bit);
+               c->setParam("\\ALUTYPE", Const("ADD_CARRY"));
+               c->setPort("\\a", bit);
+               c->setPort("\\b", State::S0);
+               c->setPort("\\c", State::S0);
+               c->setPort("\\o", bits);
+               
+               cell->setPort("\\c", new_bit);
+       }
+       
+}
+
+struct AnlogicCarryFixPass : public Pass {
+       AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { }
+       void help() YS_OVERRIDE
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    anlogic_fixcarry [options] [selection]\n");
+               log("\n");
+               log("Add Anlogic adders to fix carry chain if needed.\n");
+               log("\n");
+       }
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       {
+               log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n");
+               
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               Module *module = design->top_module();
+
+               if (module == nullptr)
+                       log_cmd_error("No top module found.\n");
+
+               fix_carry_chain(module);                
+       }
+} AnlogicCarryFixPass;
+
+PRIVATE_NAMESPACE_END
index 6d6a7ca3754bebbb2a7b543e4d280a62de718ba9..d783b0212b19d166985eebff97e84760d7022353 100644 (file)
@@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
        output [Y_WIDTH-1:0] X, Y;
 
        input CI, BI;
-       output CO;
+       output [Y_WIDTH-1:0] CO;
+   
+       wire CIx;
+       wire [Y_WIDTH-1:0] COx;
 
        wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
 
@@ -41,15 +44,16 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
 
        wire [Y_WIDTH-1:0] AA = A_buf;
        wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
-       wire [Y_WIDTH+1:0] COx;
-       wire [Y_WIDTH+2:0] C = {COx, CI};
+       wire [Y_WIDTH-1:0] C = { COx, CIx };
 
     wire dummy;
     AL_MAP_ADDER #(
        .ALUTYPE("ADD_CARRY"))
     adder_cin  (
-        .a(C[0]),
-        .o({COx[0], dummy})
+        .a(CI),
+               .b(1'b0),
+               .c(1'b0),
+        .o({CIx, dummy})
        );
 
        genvar i;
@@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
         ) adder_i (
             .a(AA[i]),
             .b(BB[i]),
-            .c(C[i+1]),
-            .o({COx[i+1],Y[i]})
+            .c(C[i]),
+            .o({COx[i],Y[i]})
         );
-         end: slice
+
+               wire cout;
+               AL_MAP_ADDER #(
+                       .ALUTYPE("ADD"))
+               adder_cout  (
+                       .a(1'b0),
+                       .b(1'b0),
+                       .c(COx[i]),
+                       .o({cout, CO[i]})
+               );
+         end: slice      
        endgenerate
-       /* End implementation */
-       AL_MAP_ADDER #(
-               .ALUTYPE("ADD"))
-       adder_cout  (
-               .c(C[Y_WIDTH+1]),
-               .o(COx[Y_WIDTH+1])
-       );                              
-       assign CO = COx[Y_WIDTH+1];
-       assign X = AA ^ BB;
+
+   /* End implementation */
+   assign X = AA ^ BB;
 endmodule
\ No newline at end of file
index 620bf39650f750d9cd42cfc8418ef3132bfa0888..b87fc8566e2fa815ad4e90784e06686b38e54005 100644 (file)
@@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
                {
                        run("memory_bram -rules +/anlogic/drams.txt");
                        run("techmap -map +/anlogic/drams_map.v");
-                       run("anlogic_determine_init");
+                       run("setundef -zero -params t:EG_LOGIC_DRAM16X4");
                }
 
                if (check_label("fine"))
@@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass
                {
                        run("techmap -map +/anlogic/cells_map.v");
                        run("clean");
+               }
+               
+               if (check_label("map_anlogic"))
+               {
+                       run("anlogic_fixcarry");
                        run("anlogic_eqn");
                }