aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2019-05-23 13:37:53 -0700
committerEddie Hung <eddie@fpgeh.com>2019-05-23 13:37:53 -0700
commit68359bcd6f1ded0dffa12f0d1e2288e433fd83e7 (patch)
tree6cbf1976a4a7ca510e7330c8f6d09603d9dc9446
parentae89e6ab26d2d87a604e20ebc14dcda8c9901585 (diff)
parent5ac7e38d0aab1c73150accd9befbccc5398b8e42 (diff)
downloadyosys-68359bcd6f1ded0dffa12f0d1e2288e433fd83e7.tar.gz
yosys-68359bcd6f1ded0dffa12f0d1e2288e433fd83e7.tar.bz2
yosys-68359bcd6f1ded0dffa12f0d1e2288e433fd83e7.zip
Merge remote-tracking branch 'origin/eddie/opt_rmdff' into xc7mux
-rw-r--r--backends/firrtl/firrtl.cc10
-rw-r--r--frontends/aiger/aigerparse.cc14
-rw-r--r--libs/subcircuit/subcircuit.cc10
-rw-r--r--passes/opt/opt_rmdff.cc35
-rw-r--r--passes/opt/wreduce.cc10
-rw-r--r--techlibs/common/prep.cc6
-rw-r--r--tests/various/opt_rmdff.v30
-rw-r--r--tests/various/opt_rmdff.ys25
8 files changed, 120 insertions, 20 deletions
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index fe6bdb8f6..1c7a7351f 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -146,7 +146,7 @@ struct FirrtlWorker
if (!mask.is_fully_def())
this->ena = SigSpec(RTLIL::Const(1));
}
- string gen_read(const char * /* indent */) {
+ string gen_read(const char * /* indent */) {
log_error("gen_read called on write_port: %s\n", name.c_str());
return stringf("gen_read called on write_port: %s\n", name.c_str());
}
@@ -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";
}
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 8b3fa6536..94bfdfa3e 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -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
diff --git a/libs/subcircuit/subcircuit.cc b/libs/subcircuit/subcircuit.cc
index 7c7236833..e8361a67e 100644
--- a/libs/subcircuit/subcircuit.cc
+++ b/libs/subcircuit/subcircuit.cc
@@ -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)
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index e8570f0eb..3cb8e2b1e 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -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_"))
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 96a77c119..cfe4b4067 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -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);
diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc
index 86fb4d6c6..cdd21c3b3 100644
--- a/techlibs/common/prep.cc
+++ b/techlibs/common/prep.cc
@@ -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" : ""));
diff --git a/tests/various/opt_rmdff.v b/tests/various/opt_rmdff.v
new file mode 100644
index 000000000..224b8d418
--- /dev/null
+++ b/tests/various/opt_rmdff.v
@@ -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
diff --git a/tests/various/opt_rmdff.ys b/tests/various/opt_rmdff.ys
new file mode 100644
index 000000000..fffffb4b5
--- /dev/null
+++ b/tests/various/opt_rmdff.ys
@@ -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