Merge remote-tracking branch 'origin/eddie/opt_rmdff' into xc7mux

This commit is contained in:
Eddie Hung 2019-05-23 13:37:53 -07:00
commit 68359bcd6f
8 changed files with 120 additions and 20 deletions

View File

@ -449,8 +449,10 @@ struct FirrtlWorker
string primop;
bool always_uint = false;
if (cell->type == "$not") primop = "not";
else if (cell->type == "$neg") primop = "neg";
else if (cell->type == "$logic_not") {
else if (cell->type == "$neg") {
primop = "neg";
is_signed = true; // Result of "neg" is signed (an SInt).
} else if (cell->type == "$logic_not") {
primop = "eq";
a_expr = stringf("%s, UInt(0)", a_expr.c_str());
}
@ -562,6 +564,7 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shl";
b_expr = std::to_string(b_sig.as_int());
} else {
primop = "dshl";
// Convert from FIRRTL left shift semantics.
@ -575,6 +578,7 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shr";
b_expr = std::to_string(b_sig.as_int());
} else {
primop = "dshr";
}

View File

@ -57,11 +57,15 @@ void AigerReader::parse_aiger()
// Optional values
B = C = J = F = 0;
for (auto &i : std::array<std::reference_wrapper<unsigned>,4>{B, C, J, F}) {
if (f.peek() != ' ') break;
if (!(f >> i))
log_error("Invalid AIGER header\n");
}
if (f.peek() != ' ') goto end_of_header;
if (!(f >> B)) log_error("Invalid AIGER header\n");
if (f.peek() != ' ') goto end_of_header;
if (!(f >> C)) log_error("Invalid AIGER header\n");
if (f.peek() != ' ') goto end_of_header;
if (!(f >> J)) log_error("Invalid AIGER header\n");
if (f.peek() != ' ') goto end_of_header;
if (!(f >> F)) log_error("Invalid AIGER header\n");
end_of_header:
std::string line;
std::getline(f, line); // Ignore up to start of next line, as standard

View File

@ -320,12 +320,10 @@ class SubCircuit::SolverWorker
static int numberOfPermutations(const std::vector<std::string> &list)
{
int numPermutations = 1;
for (int i = 0; i < int(list.size()); i++) {
assert(numPermutations < maxPermutationsLimit);
numPermutations *= i+1;
}
return numPermutations;
constexpr size_t mappedPermutationsSize = 10;
constexpr int mappedPermutations[mappedPermutationsSize] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
assert(list.size() < mappedPermutationsSize);
return mappedPermutations[list.size()];
}
static void permutateVectorToMap(std::map<std::string, std::string> &map, const std::vector<std::string> &list, int idx)

View File

@ -260,8 +260,8 @@ delete_dlatch:
bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
{
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r;
RTLIL::Const val_cp, val_rp, val_rv;
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
RTLIL::Const val_cp, val_rp, val_rv, val_ep;
if (dff->type == "$_FF_") {
sig_d = dff->getPort("\\D");
@ -285,6 +285,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
val_rv = RTLIL::Const(dff->type[8] == '1', 1);
}
else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" &&
(dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == 'N' || dff->type[8] == 'P')) {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\C");
sig_e = dff->getPort("\\E");
val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
val_ep = RTLIL::Const(dff->type[7] == 'P', 1);
}
else if (dff->type == "$ff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
@ -295,6 +305,14 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
}
else if (dff->type == "$dffe") {
sig_e = dff->getPort("\\EN");
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1);
}
else if (dff->type == "$adff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
@ -320,6 +338,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
}
if (sig_e.size()) {
if (!sig_e.is_fully_const())
return false;
if (sig_e != val_ep) {
if (has_init)
mod->connect(sig_q, val_init);
goto delete_dff;
}
}
if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) {
std::set<RTLIL::Cell*> muxes;
mux_drivers.find(sig_d, muxes);
@ -489,7 +517,8 @@ struct OptRmdffPass : public Pass {
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
"$ff", "$dff", "$adff"))
"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
"$ff", "$dff", "$dffe", "$adff"))
dff_list.push_back(cell->name);
if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))

View File

@ -29,6 +29,7 @@ PRIVATE_NAMESPACE_BEGIN
struct WreduceConfig
{
pool<IdString> supported_cell_types;
bool keepdc = false;
WreduceConfig()
{
@ -82,7 +83,7 @@ struct WreduceWorker
SigBit ref = sig_a[i];
for (int k = 0; k < GetSize(sig_s); k++) {
if (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx && ref != sig_b[k*GetSize(sig_a) + i])
if ((config->keepdc || (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx)) && ref != sig_b[k*GetSize(sig_a) + i])
goto no_match_ab;
if (sig_b[k*GetSize(sig_a) + i] != Sx)
ref = sig_b[k*GetSize(sig_a) + i];
@ -497,6 +498,9 @@ struct WreducePass : public Pass {
log(" Do not change the width of memory address ports. Use this options in\n");
log(" flows that use the 'memory_memx' pass.\n");
log("\n");
log(" -keepdc\n");
log(" Do not optimize explicit don't-care values.\n");
log("\n");
}
void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
{
@ -511,6 +515,10 @@ struct WreducePass : public Pass {
opt_memx = true;
continue;
}
if (args[argidx] == "-keepdc") {
config.keepdc = true;
continue;
}
break;
}
extra_args(args, argidx, design);

View File

@ -195,9 +195,11 @@ struct PrepPass : public ScriptPass
run(nokeepdc ? "opt" : "opt -keepdc");
if (!ifxmode) {
if (help_mode)
run("wreduce [-memx]");
else
run("wreduce -keepdc [-memx]");
else if (nokeepdc)
run(memxmode ? "wreduce -memx" : "wreduce");
else
run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc");
}
if (!nomemmode) {
run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));

30
tests/various/opt_rmdff.v Normal file
View File

@ -0,0 +1,30 @@
module opt_rmdff_test (input C, input D, input E, output reg [16:0] Q);
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove0 (.CLK(C), .D(D), .EN(1'b0), .Q(Q[0]));
initial Q[1] = 1'b1;
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove1 (.CLK(C), .D(D), .EN(1'b0), .Q(Q[1]));
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) remove2 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[2]));
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(1)) keep2 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[2]));
initial Q[3] = 1'b0;
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(1)) keep3 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[3]));
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove4 (.CLK(C), .D(D), .EN(1'b1), .Q(Q[4]));
\$dffe #(.WIDTH(1), .CLK_POLARITY(1), .EN_POLARITY(0)) remove5 (.CLK(C), .D(D), .EN(1'bx), .Q(Q[5]));
initial Q[6] = 1'b0;
\$dffe #(.WIDTH(1), .CLK_POLARITY(0), .EN_POLARITY(0)) keep6 (.CLK(C), .D(D), .EN(E), .Q(Q[6]));
\$_DFFE_PP_ remove7 (.C(C), .D(D), .E(1'b0), .Q(Q[7]));
initial Q[8] = 1'b1;
\$_DFFE_PP_ remove8 (.C(C), .D(D), .E(1'b0), .Q(Q[8]));
\$_DFFE_PP_ remove9 (.C(C), .D(D), .E(1'bx), .Q(Q[9]));
\$_DFFE_PP_ keep10 (.C(C), .D(D), .E(1'b1), .Q(Q[10]));
initial Q[11] = 1'b0;
\$_DFFE_PP_ keep11 (.C(C), .D(D), .E(1'b1), .Q(Q[11]));
\$_DFFE_NN_ remove12 (.C(C), .D(D), .E(1'b1), .Q(Q[12]));
initial Q[13] = 1'b1;
\$_DFFE_NN_ remove13 (.C(C), .D(D), .E(1'b1), .Q(Q[13]));
\$_DFFE_NN_ remove14 (.C(C), .D(D), .E(1'bx), .Q(Q[14]));
\$_DFFE_NN_ keep15 (.C(C), .D(D), .E(1'b0), .Q(Q[15]));
initial Q[16] = 1'b0;
\$_DFFE_NN_ keep16 (.C(C), .D(D), .E(1'b0), .Q(Q[16]));
endmodule

View File

@ -0,0 +1,25 @@
read_verilog -icells opt_rmdff.v
prep
design -stash gold
read_verilog -icells opt_rmdff.v
opt_rmdff
select -assert-count 0 c:remove*
select -assert-min 7 c:keep*
prep
design -stash gate
design -import gold -as gold
design -import gate -as gate
equiv_make gold gate equiv
hierarchy -top equiv
equiv_simple -undef
equiv_status -assert
design -load gold
stat
design -load gate
stat