Carry in/out to be the last input/output for chains to be preserved
authorEddie Hung <eddie@fpgeh.com>
Thu, 30 May 2019 08:23:36 +0000 (01:23 -0700)
committerEddie Hung <eddie@fpgeh.com>
Thu, 30 May 2019 08:23:36 +0000 (01:23 -0700)
backends/aiger/xaiger.cc
frontends/aiger/aigerparse.cc
techlibs/xilinx/abc.box
techlibs/xilinx/cells_sim.v

index bf696bfd6a2041a666256f017e9971b2af5b7266..25de7dababd132b15116bcbc6ec7f9f85a1c1dd6 100644 (file)
@@ -298,6 +298,8 @@ struct XAigerWriter
                                        for (auto user_cell : it.second)
                                                toposort.edge(driver_cell, user_cell);
 
+                       pool<RTLIL::Module*> abc_carry_modules;
+
                        toposort.sort();
                        for (auto cell_name : toposort.sorted) {
                                RTLIL::Cell *cell = module->cell(cell_name);
@@ -305,6 +307,42 @@ struct XAigerWriter
                                if (!box_module || !box_module->attributes.count("\\abc_box_id"))
                                        continue;
 
+                               if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) {
+                                       RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr;
+                                       RTLIL::Wire* last_in = nullptr, *last_out = nullptr;
+                                       for (const auto &port_name : box_module->ports) {
+                                               RTLIL::Wire* w = box_module->wire(port_name);
+                                               log_assert(w);
+                                               if (w->port_input) {
+                                                       if (w->attributes.count("\\abc_carry_in")) {
+                                                               log_assert(!carry_in);
+                                                               carry_in = w;
+                                                       }
+                                                       log_assert(!last_in || last_in->port_id < w->port_id);
+                                                       last_in = w;
+                                               }
+                                               if (w->port_output) {
+                                                       if (w->attributes.count("\\abc_carry_out")) {
+                                                               log_assert(!carry_out);
+                                                               carry_out = w;
+                                                       }
+                                                       log_assert(!last_out || last_out->port_id < w->port_id);
+                                                       last_out = w;
+                                               }
+                                       }
+
+                                       if (carry_in) {
+                                               log_assert(last_in);
+                                               std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]);
+                                               std::swap(carry_in->port_id, last_in->port_id);
+                                       }
+                                       if (carry_out) {
+                                               log_assert(last_out);
+                                               std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]);
+                                               std::swap(carry_out->port_id, last_out->port_id);
+                                       }
+                               }
+
                                // Fully pad all unused input connections of this box cell with S0
                                // Fully pad all undriven output connections of this box cell with anonymous wires
                                // NB: Assume box_module->ports are sorted alphabetically
index 8d7588f8843b1c274e9073d91ddba36a4f5dba87..915c53a1bd6b8a634e5006b29098fb018ef3c6e9 100644 (file)
@@ -549,6 +549,7 @@ void AigerReader::post_process()
         std::string type, symbol;
         int variable, index;
         int pi_count = 0, ci_count = 0, co_count = 0;
+        pool<RTLIL::Module*> abc_carry_modules;
         while (mf >> type >> variable >> index >> symbol) {
             RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
             if (type == "input") {
@@ -646,6 +647,43 @@ void AigerReader::post_process()
                     module->rename(cell, escaped_s);
                     RTLIL::Module* box_module = design->module(cell->type);
                     log_assert(box_module);
+
+                    if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) {
+                        RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr;
+                        RTLIL::Wire* last_in = nullptr, *last_out = nullptr;
+                        for (const auto &port_name : box_module->ports) {
+                            RTLIL::Wire* w = box_module->wire(port_name);
+                            log_assert(w);
+                            if (w->port_input) {
+                                if (w->attributes.count("\\abc_carry_in")) {
+                                    log_assert(!carry_in);
+                                    carry_in = w;
+                                }
+                                log_assert(!last_in || last_in->port_id < w->port_id);
+                                last_in = w;
+                            }
+                            if (w->port_output) {
+                                if (w->attributes.count("\\abc_carry_out")) {
+                                    log_assert(!carry_out);
+                                    carry_out = w;
+                                }
+                                log_assert(!last_out || last_out->port_id < w->port_id);
+                                last_out = w;
+                            }
+                        }
+
+                        if (carry_in != last_in) {
+                            std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]);
+                            std::swap(carry_in->port_id, last_in->port_id);
+                        }
+                        if (carry_out != last_out) {
+                            log_assert(last_out);
+                            std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]);
+                            std::swap(carry_out->port_id, last_out->port_id);
+                        }
+                    }
+
+
                     // NB: Assume box_module->ports are sorted alphabetically
                     //     (as RTLIL::Module::fixup_ports() would do)
                     for (auto port_name : box_module->ports) {
index b3972ddb3a0f04ede2b67c9ce7ace9430fb6d6eb..6e9e1faf65f18604c7eb708ccf839bd6c631f760 100644 (file)
@@ -12,17 +12,20 @@ MUXF8 2 1 3 1
 104 94 273
 
 # CARRY4 + CARRY4_[ABCD]X
-# Inputs: CI CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3
-# Outputs: CO0 CO1 CO2 CO3 O0 O1 O2 O3
+# Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI
+# Outputs:  O0 O1 O2 O3 CO0 CO1 CO2 CO3
+#   (NB: carry chain input/output must be last input/output,
+#        swapped with what normally would have been the last
+#        output, here: CI <-> S, CO <-> O
 CARRY4 3 1 10 8
-271 536 379 -   -   -   340 -   -   -
-157 494 465 445 -   -   433 469 -   -
-228 592 540 520 356 -   512 548 292 -
-114 580 526 507 398 385 508 528 378 380
-222 482 -   -   -   -   223 -   -   -
-334 598 407 -   -   -   400 205 -   -
-239 584 556 537 -   -   523 558 226 -
-313 642 615 596 438 -   582 618 330 227
+223 -   -   -   482 -   -   -   -   222
+400 205 -   -   598 407 -   -   -   334
+523 558 226 -   584 556 537 -   -   239
+582 618 330 227 642 615 596 438 -   313
+340 -   -   -   536 379 -   -   -   271
+433 469 -   -   494 465 445 -   -   157
+512 548 292 -   592 540 520 356 -   228
+508 528 378 380 580 526 507 398 385 114
 
 # SLICEM/A6LUT
 # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE
index 29c79f68999dbce3b72c43844b59f4bb1ef1501a..120370860f236dad3ad4dee8f6bece9906cca407 100644 (file)
@@ -173,8 +173,8 @@ module XORCY(output O, input CI, LI);
   assign O = CI ^ LI;
 endmodule
 
-(* abc_box_id = 3, lib_whitebox *)
-module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
+(* abc_box_id = 3, lib_whitebox, abc_carry *)
+module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S);
   assign O = S ^ {CO[2:0], CI | CYINIT};
   assign CO[0] = S[0] ? CI | CYINIT : DI[0];
   assign CO[1] = S[1] ? CO[0] : DI[1];