SigSpec refactoring: rewrote some RTLIL::SigSpec methods to use unpacked form

This commit is contained in:
Clifford Wolf 2014-07-22 22:26:30 +02:00
parent a97be0828a
commit fd4cbe6275
1 changed files with 114 additions and 183 deletions

View File

@ -1566,27 +1566,13 @@ RTLIL::SigSpec RTLIL::SigSpec::optimized() const
void RTLIL::SigSpec::sort() void RTLIL::SigSpec::sort()
{ {
pack(); unpack();
expand(); std::sort(bits_.begin(), bits_.end());
std::sort(chunks_.begin(), chunks_.end());
optimize();
} }
void RTLIL::SigSpec::sort_and_unify() void RTLIL::SigSpec::sort_and_unify()
{ {
pack(); *this = this->to_sigbit_set();
expand();
std::sort(chunks_.begin(), chunks_.end());
for (size_t i = 1; i < chunks_.size(); i++) {
RTLIL::SigChunk &ch1 = chunks_[i-1];
RTLIL::SigChunk &ch2 = chunks_[i];
if (ch1 == ch2) {
chunks_.erase(chunks_.begin()+i);
width_ -= chunks_[i].width;
i--;
}
}
optimize();
} }
void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with) void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
@ -1596,36 +1582,26 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec
void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const
{ {
pack(); unpack();
pattern.pack(); pattern.unpack();
with.pack(); with.unpack();
if (other != NULL) assert(other != NULL);
other->pack(); assert(width_ == other->width_);
other->unpack();
int pos = 0, restart_pos = 0; assert(pattern.width_ == with.width_);
assert(other == NULL || width_ == other->width_);
for (size_t i = 0; i < chunks_.size(); i++) { std::map<RTLIL::SigBit, RTLIL::SigBit> pattern_map;
restart: for (int i = 0; i < SIZE(pattern.bits_); i++)
const RTLIL::SigChunk &ch1 = chunks_[i]; if (pattern.bits_[i].wire != NULL)
if (chunks_[i].wire != NULL && pos >= restart_pos) pattern_map[pattern.bits_[i]] = with.bits_[i];
for (size_t j = 0, poff = 0; j < pattern.chunks_.size(); j++) {
const RTLIL::SigChunk &ch2 = pattern.chunks_[j]; for (int i = 0; i < SIZE(bits_); i++)
assert(ch2.wire != NULL); if (pattern_map.count(bits_[i]))
if (ch1.wire == ch2.wire) { other->bits_[i] = pattern_map.at(bits_[i]);
int lower = std::max(ch1.offset, ch2.offset);
int upper = std::min(ch1.offset + ch1.width, ch2.offset + ch2.width); other->check();
if (lower < upper) {
restart_pos = pos+upper-ch1.offset;
other->replace(pos+lower-ch1.offset, with.extract(poff+lower-ch2.offset, upper-lower));
goto restart;
}
}
poff += ch2.width;
}
pos += chunks_[i].width;
}
check();
} }
void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern) void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern)
@ -1641,36 +1617,32 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other
void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other)
{ {
pack(); unpack();
pattern.pack();
if (other != NULL) if (other != NULL) {
other->pack(); assert(width_ == other->width_);
other->unpack();
int pos = 0;
assert(other == NULL || width_ == other->width_);
for (size_t i = 0; i < chunks_.size(); i++) {
restart:
const RTLIL::SigChunk &ch1 = chunks_[i];
if (chunks_[i].wire != NULL)
for (size_t j = 0; j < pattern.chunks_.size(); j++) {
const 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)
other->remove(pos+lower-ch1.offset, upper-lower);
remove(pos+lower-ch1.offset, upper-lower);
if (i == chunks_.size())
break;
goto restart;
}
}
}
pos += chunks_[i].width;
} }
std::set<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_set();
std::vector<RTLIL::SigBit> new_bits, new_other_bits;
for (int i = 0; i < SIZE(bits_); i++) {
if (bits_[i].wire != NULL && pattern_bits.count(bits_[i]))
continue;
if (other != NULL)
new_other_bits.push_back(other->bits_[i]);
new_bits.push_back(bits_[i]);
}
bits_.swap(new_bits);
width_ = SIZE(bits_);
if (other != NULL) {
other->bits_.swap(new_other_bits);
other->width_ = SIZE(other->bits_);
}
check(); check();
} }
@ -1705,109 +1677,54 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(RTLIL::SigSpec pattern, RTLIL::SigSpec *o
void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with) void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with)
{ {
pack(); unpack();
with.pack(); with.unpack();
int pos = 0;
assert(offset >= 0); assert(offset >= 0);
assert(with.width_ >= 0); assert(with.width_ >= 0);
assert(offset+with.width_ <= width_); assert(offset+with.width_ <= width_);
remove(offset, with.width_);
for (size_t i = 0; i < chunks_.size(); i++) { for (int i = 0; i < with.width_; i++)
if (pos == offset) { bits_.at(offset + i) = with.bits_.at(i);
chunks_.insert(chunks_.begin()+i, with.chunks_.begin(), with.chunks_.end());
width_ += with.width_;
check();
return;
}
pos += chunks_[i].width;
}
assert(pos == offset);
chunks_.insert(chunks_.end(), with.chunks_.begin(), with.chunks_.end());
width_ += with.width_;
check(); check();
} }
void RTLIL::SigSpec::remove_const() void RTLIL::SigSpec::remove_const()
{ {
pack(); unpack();
for (size_t i = 0; i < chunks_.size(); i++) {
if (chunks_[i].wire != NULL) std::vector<RTLIL::SigBit> new_bits;
continue; new_bits.reserve(width_);
width_ -= chunks_[i].width;
chunks_.erase(chunks_.begin() + (i--)); for (auto &bit : bits_)
} if (bit.wire != NULL)
new_bits.push_back(bit);
bits_.swap(new_bits);
width_ = bits_.size();
check(); check();
} }
void RTLIL::SigSpec::remove(int offset, int length) void RTLIL::SigSpec::remove(int offset, int length)
{ {
pack(); unpack();
int pos = 0;
assert(offset >= 0); assert(offset >= 0);
assert(length >= 0); assert(length >= 0);
assert(offset+length <= width_); assert(offset + length <= width_);
for (size_t i = 0; i < chunks_.size(); i++) {
int orig_width = chunks_[i].width; bits_.erase(bits_.begin() + offset, bits_.begin() + offset + length);
if (pos+chunks_[i].width > offset && pos < offset+length) { width_ = bits_.size();
int off = offset - pos;
int len = length;
if (off < 0) {
len += off;
off = 0;
}
if (len > chunks_[i].width-off)
len = chunks_[i].width-off;
RTLIL::SigChunk lsb_chunk = chunks_[i].extract(0, off);
RTLIL::SigChunk msb_chunk = chunks_[i].extract(off+len, chunks_[i].width-off-len);
if (lsb_chunk.width == 0 && msb_chunk.width == 0) {
chunks_.erase(chunks_.begin()+i);
i--;
} else if (lsb_chunk.width == 0 && msb_chunk.width != 0) {
chunks_[i] = msb_chunk;
} else if (lsb_chunk.width != 0 && msb_chunk.width == 0) {
chunks_[i] = lsb_chunk;
} else if (lsb_chunk.width != 0 && msb_chunk.width != 0) {
chunks_[i] = lsb_chunk;
chunks_.insert(chunks_.begin()+i+1, msb_chunk);
i++;
} else
assert(0);
width_ -= len;
}
pos += orig_width;
}
check(); check();
} }
RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
{ {
pack(); unpack();
int pos = 0; return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length);
RTLIL::SigSpec ret;
assert(offset >= 0);
assert(length >= 0);
assert(offset+length <= width_);
for (size_t i = 0; i < chunks_.size(); i++) {
if (pos+chunks_[i].width > offset && pos < offset+length) {
int off = offset - pos;
int len = length;
if (off < 0) {
len += off;
off = 0;
}
if (len > chunks_[i].width-off)
len = chunks_[i].width-off;
ret.chunks_.push_back(chunks_[i].extract(off, len));
ret.width_ += len;
offset += len;
length -= len;
}
pos += chunks_[i].width;
}
assert(length == 0);
ret.check();
return ret;
} }
void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)
@ -1819,27 +1736,34 @@ void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)
chunks_.push_back(signal.chunks_[i]); chunks_.push_back(signal.chunks_[i]);
width_ += signal.chunks_[i].width; width_ += signal.chunks_[i].width;
} }
// check(); // check();
} }
void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit) void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit)
{ {
pack(); if (packed())
if (chunks_.size() == 0) {
chunks_.push_back(bit); if (chunks_.size() == 0)
else chunks_.push_back(bit);
if (bit.wire == NULL)
if (chunks_.back().wire == NULL) {
chunks_.back().data.bits.push_back(bit.data);
chunks_.back().width++;
} else
chunks_.push_back(bit);
else else
if (chunks_.back().wire == bit.wire && chunks_.back().offset + chunks_.back().width == bit.offset) if (bit.wire == NULL)
chunks_.back().width++; if (chunks_.back().wire == NULL) {
chunks_.back().data.bits.push_back(bit.data);
chunks_.back().width++;
} else
chunks_.push_back(bit);
else else
chunks_.push_back(bit); if (chunks_.back().wire == bit.wire && chunks_.back().offset + chunks_.back().width == bit.offset)
chunks_.back().width++;
else
chunks_.push_back(bit);
}
else
bits_.push_back(bit);
width_++; width_++;
// check(); // check();
} }
@ -1911,23 +1835,30 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
void RTLIL::SigSpec::check() const void RTLIL::SigSpec::check() const
{ {
pack(); if (packed())
{
int w = 0; int w = 0;
for (size_t i = 0; i < chunks_.size(); i++) { for (size_t i = 0; i < chunks_.size(); i++) {
const RTLIL::SigChunk chunk = chunks_[i]; const RTLIL::SigChunk chunk = chunks_[i];
if (chunk.wire == NULL) { if (chunk.wire == NULL) {
assert(chunk.offset == 0); assert(chunk.offset == 0);
assert(chunk.data.bits.size() == (size_t)chunk.width); assert(chunk.data.bits.size() == (size_t)chunk.width);
} else { } else {
assert(chunk.offset >= 0); assert(chunk.offset >= 0);
assert(chunk.width >= 0); assert(chunk.width >= 0);
assert(chunk.offset + chunk.width <= chunk.wire->width); assert(chunk.offset + chunk.width <= chunk.wire->width);
assert(chunk.data.bits.size() == 0); assert(chunk.data.bits.size() == 0);
}
w += chunk.width;
} }
w += chunk.width; assert(w == width_);
assert(bits_.empty());
}
else
{
assert(width_ == SIZE(bits_));
assert(chunks_.empty());
} }
assert(w == width_);
} }
bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const