diff options
-rw-r--r-- | kernel/rtlil.cc | 109 | ||||
-rw-r--r-- | kernel/rtlil.h | 34 |
2 files changed, 119 insertions, 24 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a0aa8b659..2bd79df7d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -840,6 +840,15 @@ RTLIL::SigChunk::SigChunk(RTLIL::State bit, int width) offset = 0; } +RTLIL::SigChunk::SigChunk(RTLIL::SigBit bit) +{ + wire = bit.wire; + if (wire == NULL) + data = RTLIL::Const(bit.data); + offset = bit.offset; + width = 1; +} + RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const { RTLIL::SigChunk ret; @@ -927,14 +936,34 @@ RTLIL::SigSpec::SigSpec(const std::string &str) RTLIL::SigSpec::SigSpec(int val, int width) { chunks.push_back(RTLIL::SigChunk(val, width)); - this->width = chunks.back().width; + this->width = width; check(); } RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width) { chunks.push_back(RTLIL::SigChunk(bit, width)); - this->width = chunks.back().width; + this->width = width; + check(); +} + +RTLIL::SigSpec::SigSpec(RTLIL::SigBit bit, int width) +{ + if (bit.wire == NULL) + chunks.push_back(RTLIL::SigChunk(bit.data, width)); + else + for (int i = 0; i < width; i++) + chunks.push_back(bit); + this->width = width; + check(); +} + +RTLIL::SigSpec::SigSpec(std::vector<RTLIL::SigBit> bits) +{ + chunks.reserve(bits.size()); + for (auto &bit : bits) + chunks.push_back(bit); + this->width = bits.size(); check(); } @@ -1100,29 +1129,23 @@ restart: RTLIL::SigSpec RTLIL::SigSpec::extract(RTLIL::SigSpec pattern, RTLIL::SigSpec *other) const { - int pos = 0; - RTLIL::SigSpec ret; - pattern.sort_and_unify(); assert(other == NULL || width == other->width); - for (size_t i = 0; i < chunks.size(); i++) { - const RTLIL::SigChunk &ch1 = chunks[i]; - if (chunks[i].wire != NULL) - for (size_t j = 0; j < pattern.chunks.size(); j++) { - RTLIL::SigChunk &ch2 = pattern.chunks[j]; - assert(ch2.wire != NULL); - if (ch1.wire == ch2.wire) { - int lower = std::max(ch1.offset, ch2.offset); - int upper = std::min(ch1.offset + ch1.width, ch2.offset + ch2.width); - if (lower < upper) { - if (other) - ret.append(other->extract(pos+lower-ch1.offset, upper-lower)); - else - ret.append(extract(pos+lower-ch1.offset, upper-lower)); - } - } - } - pos += chunks[i].width; + + std::set<RTLIL::SigBit> pat = pattern.to_sigbit_set(); + std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector(); + RTLIL::SigSpec ret; + + if (other) { + std::vector<RTLIL::SigBit> bits_other = other ? other->to_sigbit_vector() : bits_match; + for (int i = 0; i < width; i++) + if (bits_match[i].wire && pat.count(bits_match[i])) + ret.append_bit(bits_other[i]); + } else { + for (int i = 0; i < width; i++) + if (bits_match[i].wire && pat.count(bits_match[i])) + ret.append_bit(bits_match[i]); } + ret.check(); return ret; } @@ -1234,7 +1257,26 @@ void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) chunks.push_back(signal.chunks[i]); width += signal.chunks[i].width; } - check(); + // check(); +} + +void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) +{ + if (chunks.size() == 0) + chunks.push_back(bit); + else + if (bit.wire == NULL) + if (chunks.back().wire == NULL) + chunks.back().data.bits.push_back(bit.data); + else + chunks.push_back(bit); + else + if (chunks.back().wire == bit.wire && chunks.back().offset + chunks.back().width == bit.offset) + chunks.back().width++; + else + chunks.push_back(bit); + width++; + // check(); } bool RTLIL::SigSpec::combine(RTLIL::SigSpec signal, RTLIL::State freeState, bool override) @@ -1469,6 +1511,25 @@ bool RTLIL::SigSpec::match(std::string pattern) const return true; } +std::set<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_set() const +{ + std::set<RTLIL::SigBit> sigbits; + for (auto &c : chunks) + for (int i = 0; i < c.width; i++) + sigbits.insert(RTLIL::SigBit(c, i)); + return sigbits; +} + +std::vector<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_vector() const +{ + std::vector<RTLIL::SigBit> sigbits; + sigbits.reserve(width); + for (auto &c : chunks) + for (int i = 0; i < c.width; i++) + sigbits.push_back(RTLIL::SigBit(c, i)); + return sigbits; +} + static void sigspec_parse_split(std::vector<std::string> &tokens, const std::string &text, char sep) { size_t start = 0, end = 0; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c8f6b370f..52bf6e809 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -58,6 +58,7 @@ namespace RTLIL struct Memory; struct Cell; struct SigChunk; + struct SigBit; struct SigSpec; struct CaseRule; struct SwitchRule; @@ -309,6 +310,7 @@ struct RTLIL::SigChunk { SigChunk(const std::string &str); SigChunk(int val, int width = 32); SigChunk(RTLIL::State bit, int width = 1); + SigChunk(RTLIL::SigBit bit); RTLIL::SigChunk extract(int offset, int length) const; bool operator <(const RTLIL::SigChunk &other) const; bool operator ==(const RTLIL::SigChunk &other) const; @@ -316,6 +318,28 @@ struct RTLIL::SigChunk { static bool compare(const RTLIL::SigChunk &a, const RTLIL::SigChunk &b); }; +struct RTLIL::SigBit { + RTLIL::Wire *wire; + RTLIL::State data; + int offset; + SigBit() : wire(NULL), data(RTLIL::State::S0), offset(0) { } + SigBit(RTLIL::State bit) : wire(NULL), data(bit), offset(0) { } + SigBit(RTLIL::Wire *wire) : wire(wire), data(RTLIL::State::S0), offset(0) { assert(!wire || wire->width == 1); } + SigBit(RTLIL::Wire *wire, int offset) : wire(wire), data(RTLIL::State::S0), offset(offset) { } + SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire), data(chunk.wire ? RTLIL::State::S0 : chunk.data.bits[0]), offset(chunk.offset) { assert(chunk.width == 1); } + SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire), data(chunk.wire ? RTLIL::State::S0 : chunk.data.bits[index]), offset(chunk.wire ? chunk.offset + index : 0) { } + SigBit(const RTLIL::SigSpec &sig); + bool operator <(const RTLIL::SigBit &other) const { + return (wire != other.wire) ? (wire < other.wire) : wire ? (offset < other.offset) : (data < other.data); + } + bool operator ==(const RTLIL::SigBit &other) const { + return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data)); + } + bool operator !=(const RTLIL::SigBit &other) const { + return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); + } +}; + struct RTLIL::SigSpec { std::vector<RTLIL::SigChunk> chunks; // LSB at index 0 int width; @@ -326,6 +350,8 @@ struct RTLIL::SigSpec { SigSpec(const std::string &str); SigSpec(int val, int width = 32); SigSpec(RTLIL::State bit, int width = 1); + SigSpec(RTLIL::SigBit bit, int width = 1); + SigSpec(std::vector<RTLIL::SigBit> bits); void expand(); void optimize(); void sort(); @@ -341,6 +367,7 @@ struct RTLIL::SigSpec { void remove(int offset, int length); RTLIL::SigSpec extract(int offset, int length) const; void append(const RTLIL::SigSpec &signal); + void append_bit(const RTLIL::SigBit &bit); bool combine(RTLIL::SigSpec signal, RTLIL::State freeState = RTLIL::State::Sz, bool override = false); void extend(int width, bool is_signed = false); void extend_u0(int width, bool is_signed = false); @@ -357,10 +384,17 @@ struct RTLIL::SigSpec { std::string as_string() const; RTLIL::Const as_const() const; bool match(std::string pattern) const; + std::set<RTLIL::SigBit> to_sigbit_set() const; + std::vector<RTLIL::SigBit> to_sigbit_vector() const; static bool parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); }; +inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { + assert(sig.width == 1 && sig.chunks.size() == 1); + *this = SigBit(sig.chunks[0]); +} + struct RTLIL::CaseRule { std::vector<RTLIL::SigSpec> compare; std::vector<RTLIL::SigSig> actions; |