Added SigBit struct and refactored RTLIL::SigSpec::extract
authorClifford Wolf <clifford@clifford.at>
Fri, 22 Nov 2013 03:07:13 +0000 (04:07 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 22 Nov 2013 03:07:13 +0000 (04:07 +0100)
kernel/rtlil.cc
kernel/rtlil.h

index a0aa8b65939fd5d21e4406fcd862e42a7e9326fa..2bd79df7d800cb43361e4a2333af57c9166c2d11 100644 (file)
@@ -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;
index c8f6b370f352ad5eb8faef7fecd0ce66c78b9e16..52bf6e8092154df80c145fca5a3d108d33555c4b 100644 (file)
@@ -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;