From fdfc18be91123e2939f134dafc12e1e0c1a82f7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 01:23:36 -0700 Subject: [PATCH] Carry in/out to be the last input/output for chains to be preserved --- backends/aiger/xaiger.cc | 38 +++++++++++++++++++++++++++++++++++ frontends/aiger/aigerparse.cc | 38 +++++++++++++++++++++++++++++++++++ techlibs/xilinx/abc.box | 23 ++++++++++++--------- techlibs/xilinx/cells_sim.v | 4 ++-- 4 files changed, 91 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf696bfd6..25de7daba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -298,6 +298,8 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); + pool 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 diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 8d7588f88..915c53a1b 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -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 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) { diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box index b3972ddb3..6e9e1faf6 100644 --- a/techlibs/xilinx/abc.box +++ b/techlibs/xilinx/abc.box @@ -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 diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 29c79f689..120370860 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -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]; -- 2.30.2