summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-11-07 16:53:28 +0100
committerClifford Wolf <clifford@clifford.at>2013-11-07 16:53:28 +0100
commit0e1661f84e99f1d4a487e7a432b05a6cb2071714 (patch)
tree9862950a7c92069d88e590da6d0a97bf7b7eb95f
parented4bcd52e5d7ab466a4bcd87ae787f1ab7c70fb7 (diff)
Fixed type of sign extension in opt_const $eq/$ne handling
-rw-r--r--kernel/rtlil.cc16
-rw-r--r--kernel/rtlil.h1
-rw-r--r--passes/opt/opt_const.cc18
3 files changed, 26 insertions, 9 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index d64a37bb..4388acb1 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -940,6 +940,22 @@ void RTLIL::SigSpec::extend(int width, bool is_signed)
optimize();
}
+void RTLIL::SigSpec::extend_un0(int width, bool is_signed)
+{
+ if (this->width > width)
+ remove(width, this->width - width);
+
+ if (this->width < width) {
+ RTLIL::SigSpec padding = this->width > 0 ? extract(this->width - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0);
+ if (!is_signed)
+ padding = RTLIL::SigSpec(RTLIL::State::S0);
+ while (this->width < width)
+ append(padding);
+ }
+
+ optimize();
+}
+
void RTLIL::SigSpec::check() const
{
int w = 0;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 6cb471b5..376a09ab 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -342,6 +342,7 @@ struct RTLIL::SigSpec {
void append(const RTLIL::SigSpec &signal);
bool combine(RTLIL::SigSpec signal, RTLIL::State freeState = RTLIL::State::Sz, bool override = false);
void extend(int width, bool is_signed = false);
+ void extend_un0(int width, bool is_signed = false);
void check() const;
bool operator <(const RTLIL::SigSpec &other) const;
bool operator ==(const RTLIL::SigSpec &other) const;
diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc
index b04ed9e7..f20181f1 100644
--- a/passes/opt/opt_const.cc
+++ b/passes/opt/opt_const.cc
@@ -151,8 +151,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (cell->parameters["\\A_WIDTH"].as_int() != cell->parameters["\\B_WIDTH"].as_int()) {
int width = std::max(cell->parameters["\\A_WIDTH"].as_int(), cell->parameters["\\B_WIDTH"].as_int());
- a.extend(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
- b.extend(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
+ a.extend_un0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
+ b.extend_un0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
}
RTLIL::SigSpec new_a, new_b;
@@ -168,6 +168,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
new_b.append(b.chunks[i]);
}
+ if (new_a.width == 0) {
+ RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type == "$eq" ? RTLIL::State::S1 : RTLIL::State::S0);
+ new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
+ replace_cell(module, cell, "empty", "\\Y", new_y);
+ goto next_cell;
+ }
+
if (new_a.width != a.width) {
new_a.optimize();
new_b.optimize();
@@ -176,13 +183,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
cell->parameters["\\A_WIDTH"] = new_a.width;
cell->parameters["\\B_WIDTH"] = new_b.width;
}
-
- if (new_a.width == 0) {
- RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type == "$eq" ? RTLIL::State::S1 : RTLIL::State::S0);
- new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
- replace_cell(module, cell, "empty", "\\Y", new_y);
- goto next_cell;
- }
}
if ((cell->type == "$eq" || cell->type == "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 &&