aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwhitequark <whitequark@whitequark.org>2020-06-09 07:26:13 +0000
committerwhitequark <whitequark@whitequark.org>2020-06-09 07:26:13 +0000
commitef4e1594470b46eab6f311998511a5eee22a96d3 (patch)
tree493fa7e235a288f357f0708c38a576355f4fb3d9
parent4351194e8ce94e7078b67a20e5fc92777d6cb3e6 (diff)
downloadyosys-ef4e1594470b46eab6f311998511a5eee22a96d3.tar.gz
yosys-ef4e1594470b46eab6f311998511a5eee22a96d3.tar.bz2
yosys-ef4e1594470b46eab6f311998511a5eee22a96d3.zip
cxxrtl: ignore cell input signedness when it is irrelevant.
Before this commit, Verilog expressions like `x && 1` would result in references to `logic_and_us` in generated CXXRTL code, which would not compile. After this commit, since cells like that actually behave the same regardless of signedness attributes, the signedness is ignored, which also reduces the template instantiation pressure.
-rw-r--r--backends/cxxrtl/cxxrtl.h76
-rw-r--r--backends/cxxrtl/cxxrtl_backend.cc23
2 files changed, 35 insertions, 64 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index 30f4667c5..c988c9e80 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -829,73 +829,55 @@ constexpr T max(const T &a, const T &b) {
// Logic operations
template<size_t BitsY, size_t BitsA>
-value<BitsY> not_u(const value<BitsA> &a) {
- return a.template zcast<BitsY>().bit_not();
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> not_s(const value<BitsA> &a) {
- return a.template scast<BitsY>().bit_not();
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> logic_not_u(const value<BitsA> &a) {
+value<BitsY> logic_not(const value<BitsA> &a) {
return value<BitsY> { a ? 0u : 1u };
}
-template<size_t BitsY, size_t BitsA>
-value<BitsY> logic_not_s(const value<BitsA> &a) {
- return value<BitsY> { a ? 0u : 1u };
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+value<BitsY> logic_and(const value<BitsA> &a, const value<BitsB> &b) {
+ return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
}
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_and_u(const value<BitsA> &a) {
- return value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+value<BitsY> logic_or(const value<BitsA> &a, const value<BitsB> &b) {
+ return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
}
+// Reduction operations
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_and_s(const value<BitsA> &a) {
+value<BitsY> reduce_and(const value<BitsA> &a) {
return value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };
}
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_or_u(const value<BitsA> &a) {
- return value<BitsY> { a ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_or_s(const value<BitsA> &a) {
+value<BitsY> reduce_or(const value<BitsA> &a) {
return value<BitsY> { a ? 1u : 0u };
}
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xor_u(const value<BitsA> &a) {
- return value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xor_s(const value<BitsA> &a) {
+value<BitsY> reduce_xor(const value<BitsA> &a) {
return value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };
}
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xnor_u(const value<BitsA> &a) {
+value<BitsY> reduce_xnor(const value<BitsA> &a) {
return value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };
}
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xnor_s(const value<BitsA> &a) {
- return value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };
+value<BitsY> reduce_bool(const value<BitsA> &a) {
+ return value<BitsY> { a ? 1u : 0u };
}
+// Bitwise operations
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_bool_u(const value<BitsA> &a) {
- return value<BitsY> { a ? 1u : 0u };
+value<BitsY> not_u(const value<BitsA> &a) {
+ return a.template zcast<BitsY>().bit_not();
}
template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_bool_s(const value<BitsA> &a) {
- return value<BitsY> { a ? 1u : 0u };
+value<BitsY> not_s(const value<BitsA> &a) {
+ return a.template scast<BitsY>().bit_not();
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
@@ -939,26 +921,6 @@ value<BitsY> xnor_ss(const value<BitsA> &a, const value<BitsB> &b) {
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_and_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_and_ss(const value<BitsA> &a, const value<BitsB> &b) {
- return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_or_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_or_ss(const value<BitsA> &a, const value<BitsB> &b) {
- return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
value<BitsY> shl_uu(const value<BitsA> &a, const value<BitsB> &b) {
return a.template zcast<BitsY>().template shl(b);
}
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index bf01b263a..2646f9371 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -192,6 +192,13 @@ bool is_binary_cell(RTLIL::IdString type)
ID($add), ID($sub), ID($mul), ID($div), ID($mod));
}
+bool is_extending_cell(RTLIL::IdString type)
+{
+ return !type.in(
+ ID($logic_not), ID($logic_and), ID($logic_or),
+ ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool));
+}
+
bool is_elidable_cell(RTLIL::IdString type)
{
return is_unary_cell(type) || is_binary_cell(type) || type.in(
@@ -907,17 +914,19 @@ struct CxxrtlWorker {
{
// Unary cells
if (is_unary_cell(cell->type)) {
- f << cell->type.substr(1) << '_' <<
- (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
- "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
+ f << cell->type.substr(1);
+ if (is_extending_cell(cell->type))
+ f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u');
+ f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
dump_sigspec_rhs(cell->getPort(ID::A));
f << ")";
// Binary cells
} else if (is_binary_cell(cell->type)) {
- f << cell->type.substr(1) << '_' <<
- (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
- (cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u') <<
- "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
+ f << cell->type.substr(1);
+ if (is_extending_cell(cell->type))
+ f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
+ (cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u');
+ f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
dump_sigspec_rhs(cell->getPort(ID::A));
f << ", ";
dump_sigspec_rhs(cell->getPort(ID::B));