Add tests, perform more transformations
diff --git a/passes/pmgen/xilinx_dff.cc b/passes/pmgen/xilinx_dff.cc index bf0c735..c09b272 100644 --- a/passes/pmgen/xilinx_dff.cc +++ b/passes/pmgen/xilinx_dff.cc
@@ -54,7 +54,8 @@ for (auto module : design->selected_modules()) { xilinx_dff_pm pm(module, module->selected_cells()); - pm.run_xilinx_dff(); + pm.run_xilinx_r(); + pm.run_xilinx_ce(); } } } XilinxDffPass;
diff --git a/passes/pmgen/xilinx_dff.pmg b/passes/pmgen/xilinx_dff.pmg index 4de25c3..9ca8731 100644 --- a/passes/pmgen/xilinx_dff.pmg +++ b/passes/pmgen/xilinx_dff.pmg
@@ -1,9 +1,10 @@ -pattern xilinx_dff +pattern xilinx_r match fd - select fd->type.in(\FDRE) + select fd->type.in(\FDRE, \FDRE_1) select port(fd, \R).is_fully_zero() select port(fd, \CE).is_fully_ones() + select !param(fd, \IS_R_INVERTED, State::S0).as_bool() /* TODO */ endmatch match lut @@ -12,15 +13,73 @@ endmatch code - if (lut->type == \LUT2) { - if (param(lut, \INIT) == Const::from_string("0010")) { - fd->setPort(\D, port(lut, \I0)); - fd->setPort(\R, port(lut, \I1)); - } - else if (param(lut, \INIT) == Const::from_string("0100")) { - fd->setPort(\R, port(lut, \I0)); - fd->setPort(\D, port(lut, \I1)); - } + if (param(lut, \INIT) == Const::from_string("0010")) { + fd->setPort(\D, port(lut, \I0)); + fd->setPort(\R, port(lut, \I1)); } - else log_abort(); + else if (param(lut, \INIT) == Const::from_string("0100")) { + fd->setPort(\R, port(lut, \I0)); + fd->setPort(\D, port(lut, \I1)); + } + else if (param(lut, \INIT) == Const::from_string("1110")) { + if (fd->type == \FDRE) { + fd->type = \FDSE; + fd->unsetParam(\IS_R_INVERTED); + fd->setParam(\IS_S_INVERTED, State::S0); + } + else if (fd->type == \FDRE_1) { + fd->type = \FDSE_1; + } + else log_abort(); + fd->setPort(\D, port(lut, \I0)); + fd->setPort(\S, port(lut, \I1)); + fd->unsetParam(\IS_R_INVERTED); + fd->unsetPort(\R); + } +endcode + + +pattern xilinx_ce + +match fd + select fd->type.in(\FDRE, \FDRE_1, \FDSE, \FDSE_1, \FDCE, \FDCE_1, \FDPE, \FDPE_1) + select port(fd, \CE).is_fully_ones() +endmatch + +match lut + select lut->type.in(\LUT3) + index <SigSpec> port(lut, \O) === port(fd, \D) +endmatch + +code + if (param(lut, \INIT) == Const::from_string("11011000")) { + fd->setPort(\CE, port(lut, \I0)); + fd->setPort(\D, port(lut, \I1)); + fd->setPort(\Q, port(lut, \I2)); + } + else if (param(lut, \INIT) == Const::from_string("11100100")) { + fd->setPort(\CE, port(lut, \I0)); + fd->setPort(\Q, port(lut, \I1)); + fd->setPort(\D, port(lut, \I2)); + } + else if (param(lut, \INIT) == Const::from_string("11100010")) { + fd->setPort(\Q, port(lut, \I0)); + fd->setPort(\CE, port(lut, \I1)); + fd->setPort(\D, port(lut, \I2)); + } + else if (param(lut, \INIT) == Const::from_string("11001010")) { + fd->setPort(\Q, port(lut, \I0)); + fd->setPort(\D, port(lut, \I1)); + fd->setPort(\CE, port(lut, \I2)); + } + else if (param(lut, \INIT) == Const::from_string("10101100")) { + fd->setPort(\D, port(lut, \I0)); + fd->setPort(\Q, port(lut, \I1)); + fd->setPort(\CE, port(lut, \I2)); + } + else if (param(lut, \INIT) == Const::from_string("10111000")) { + fd->setPort(\D, port(lut, \I0)); + fd->setPort(\CE, port(lut, \I1)); + fd->setPort(\Q, port(lut, \I2)); + } endcode
diff --git a/tests/arch/xilinx/xilinx_dff.ys b/tests/arch/xilinx/xilinx_dff.ys new file mode 100644 index 0000000..695c28b --- /dev/null +++ b/tests/arch/xilinx/xilinx_dff.ys
@@ -0,0 +1,62 @@ +read_verilog <<EOT +module top(input c, d, r, output reg q); +always @(posedge c) + if (r) q <= 1'b0; + else q <= d; +endmodule +EOT +proc +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx +design -load postopt +cd top +select -assert-count 1 t:FDRE +select -assert-none t:* t:FDRE %d t:BUFG %d + + +design -reset +read_verilog <<EOT +module top(input c, d, r, e, output reg q); +always @(posedge c) begin + if (e) q <= d; + if (r) q <= 1'b0; +end +endmodule +EOT +proc +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx +design -load postopt +cd top +select -assert-count 1 t:FDRE +select -assert-none t:* t:FDRE %d t:BUFG %d + + +design -reset +read_verilog <<EOT +module top(input c, d, s, output reg q); +always @(posedge c) + if (s) q <= 1'b1; + else q <= d; +endmodule +EOT +proc +equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx +design -load postopt +cd top +select -assert-count 1 t:FDSE +select -assert-none t:* t:FDSE %d t:BUFG %d + + +design -reset +read_verilog <<EOT +module top(input c, d, e, clr, output reg q); +always @(posedge c or posedge clr) + if (clr) q <= 1'b0; + else if (e) q <= d; +endmodule +EOT +proc +equiv_opt -assert -map +/xilinx/cells_sim.v -multiclock synth_xilinx +design -load postopt +cd top +select -assert-count 1 t:FDCE +select -assert-none t:* t:FDCE %d t:BUFG %d