summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Altherr <kc8apf@kc8apf.net>2016-01-31 09:07:21 -0800
committerRick Altherr <kc8apf@kc8apf.net>2016-01-31 09:20:16 -0800
commit3c48de8e218ff70f4b5f8e42a6794a48354ea062 (patch)
tree8e81ca35b190f2ed0f1f3e9e65caac6660527fc6
parent0265d7b1006e0946eb4635d73a6d49d31b3e4235 (diff)
rtlil: Improve performance of SigSpec::extract(SigSpec, SigSpec*)
Converting to a pool<SigBit> is fairly expensive due to inserts somewhat frequently causing rehashing. Instead, walk through the pattern SigSpec directly on a chunk-by-chunk basis and apply it to this SigSpec's individual bits. Using chunks for the pattern minimizes the number of iterations in the outer loop.
-rw-r--r--kernel/rtlil.cc33
1 files changed, 31 insertions, 2 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index ee0f44a3..1f3f7899 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -2777,8 +2777,37 @@ void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigS
RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const
{
- pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_pool();
- return extract(pattern_bits, other);
+ if (other)
+ cover("kernel.rtlil.sigspec.extract_other");
+ else
+ cover("kernel.rtlil.sigspec.extract");
+
+ log_assert(other == NULL || width_ == other->width_);
+
+ RTLIL::SigSpec ret;
+ std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector();
+
+ for (auto& pattern_chunk : pattern.chunks()) {
+ if (other) {
+ std::vector<RTLIL::SigBit> bits_other = other->to_sigbit_vector();
+ for (int i = 0; i < width_; i++)
+ if (bits_match[i].wire &&
+ bits_match[i].wire == pattern_chunk.wire &&
+ bits_match[i].offset >= pattern_chunk.offset &&
+ bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width)
+ ret.append_bit(bits_other[i]);
+ } else {
+ for (int i = 0; i < width_; i++)
+ if (bits_match[i].wire &&
+ bits_match[i].wire == pattern_chunk.wire &&
+ bits_match[i].offset >= pattern_chunk.offset &&
+ bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width)
+ ret.append_bit(bits_match[i]);
+ }
+ }
+
+ ret.check();
+ return ret;
}
RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const