3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-13 01:16:16 +00:00

sigspec: more hell

This commit is contained in:
Emil J. Tywoniak 2024-07-17 16:00:02 +02:00
parent 5beba35600
commit b8e363bf9a
2 changed files with 275 additions and 199 deletions

View file

@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <iostream>
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
@ -2423,6 +2424,7 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth
RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type) RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type)
{ {
RTLIL::Cell *cell = new RTLIL::Cell; RTLIL::Cell *cell = new RTLIL::Cell;
// std::cout << "alloc " << (long long)cell << " called " << cell->name.c_str() << "\n";
cell->name = name; cell->name = name;
cell->type = type; cell->type = type;
add(cell); add(cell);
@ -3441,7 +3443,6 @@ RTLIL::Wire::Wire()
port_output = false; port_output = false;
upto = false; upto = false;
is_signed = false; is_signed = false;
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
RTLIL::Wire::get_all_wires()->insert(std::pair<unsigned int, RTLIL::Wire*>(hashidx_, this)); RTLIL::Wire::get_all_wires()->insert(std::pair<unsigned int, RTLIL::Wire*>(hashidx_, this));
#endif #endif
@ -3785,14 +3786,10 @@ bool RTLIL::SigChunk::operator !=(const RTLIL::SigChunk &other) const
} }
RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts) RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.list"); cover("kernel.rtlil.sigspec.init.list");
width_ = 0;
hash_ = 0;
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
log_assert(parts.size() > 0); log_assert(parts.size() > 0);
auto ie = parts.begin(); auto ie = parts.begin();
auto it = ie + parts.size() - 1; auto it = ie + parts.size() - 1;
@ -3801,149 +3798,114 @@ RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
} }
RTLIL::SigSpec::SigSpec(const RTLIL::Const &value) RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.const"); cover("kernel.rtlil.sigspec.init.const");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(value); chunks_.emplace_back(value);
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(RTLIL::Const &&value) RTLIL::SigSpec::SigSpec(RTLIL::Const &&value)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.const.move"); cover("kernel.rtlil.sigspec.init.const.move");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(std::move(value)); chunks_.emplace_back(std::move(value));
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk) RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.chunk"); cover("kernel.rtlil.sigspec.init.chunk");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(chunk); chunks_.emplace_back(chunk);
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk) RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.chunk.move"); cover("kernel.rtlil.sigspec.init.chunk.move");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(std::move(chunk)); chunks_.emplace_back(std::move(chunk));
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire) RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.wire"); cover("kernel.rtlil.sigspec.init.wire");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (wire->width != 0) { if (wire->width != 0) {
chunks_.emplace_back(wire); chunks_.emplace_back(wire);
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width) RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.wire_part"); cover("kernel.rtlil.sigspec.init.wire_part");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) { if (width != 0) {
chunks_.emplace_back(wire, offset, width); chunks_.emplace_back(wire, offset, width);
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(const std::string &str) RTLIL::SigSpec::SigSpec(const std::string &str)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.str"); cover("kernel.rtlil.sigspec.init.str");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (str.size() != 0) { if (str.size() != 0) {
chunks_.emplace_back(str); chunks_.emplace_back(str);
width_ = chunks_.back().width; width_ = chunks_.back().width;
} else {
width_ = 0;
} }
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(int val, int width) RTLIL::SigSpec::SigSpec(int val, int width)
: width_(width), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.int"); cover("kernel.rtlil.sigspec.init.int");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) if (width != 0)
chunks_.emplace_back(val, width); chunks_.emplace_back(val, width);
width_ = width;
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width) RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
: width_(width), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.state"); cover("kernel.rtlil.sigspec.init.state");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) if (width != 0)
chunks_.emplace_back(bit, width); chunks_.emplace_back(bit, width);
width_ = width;
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width) RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
: width_(width), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.bit"); cover("kernel.rtlil.sigspec.init.bit");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) { if (width != 0) {
if (bit.wire == NULL) if (bit.wire == NULL)
chunks_.emplace_back(bit.data, width); chunks_.emplace_back(bit.data, width);
@ -3951,109 +3913,91 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
chunks_.push_back(bit); chunks_.push_back(bit);
} }
width_ = width;
hash_ = 0;
check(); check();
} }
RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks) RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_chunks"); cover("kernel.rtlil.sigspec.init.stdvec_chunks");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
width_ = 0;
hash_ = 0;
for (const auto &c : chunks) for (const auto &c : chunks)
append(c); append(c);
check(); check();
} }
RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits) RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_bits"); cover("kernel.rtlil.sigspec.init.stdvec_bits");
packed_ = false; for (const auto &bit : bits)
(void)new (&this->bits_) std::vector<SigBit>(); append(bit);
width_ = 0; check();
hash_ = 0; }
RTLIL::SigSpec::SigSpec(const chunk_vec_type &chunks)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{
cover("kernel.rtlil.sigspec.init.mock_vec_chunks");
for (const auto &c : chunks)
append(c);
check();
}
RTLIL::SigSpec::SigSpec(const bit_vec_type &bits)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{
cover("kernel.rtlil.sigspec.init.mock_vec_bits");
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
} }
RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits) RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.pool_bits"); cover("kernel.rtlil.sigspec.init.pool_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0;
hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
} }
RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits) RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.stdset_bits"); cover("kernel.rtlil.sigspec.init.stdset_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0;
hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
} }
RTLIL::SigSpec::SigSpec(bool bit) RTLIL::SigSpec::SigSpec(bool bit)
: width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_)
{ {
cover("kernel.rtlil.sigspec.init.bool"); cover("kernel.rtlil.sigspec.init.bool");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0;
hash_ = 0;
append(SigBit(bit)); append(SigBit(bit));
check(); check();
} }
void RTLIL::SigSpec::switch_to_packed() const
{
// TODO change to debug asserts
// log_assert(!this->packed_);
// log_assert(bits_.size() == 0);
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
that->bits_.~vector();
that->packed_ = true;
(void)new (&that->chunks_) std::vector<SigChunk>();
}
void RTLIL::SigSpec::switch_to_unpacked() const
{
// TODO change to debug asserts
// log_assert(this->packed_);
// log_assert(chunks_.size() == 0);
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
that->chunks_.~vector();
that->packed_ = false;
(void)new (&that->bits_) std::vector<SigBit>();
}
void RTLIL::SigSpec::pack() const void RTLIL::SigSpec::pack() const
{ {
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
if (packed_ || that->bits_.empty()) if (that->bits_.empty())
return; return;
cover("kernel.rtlil.sigspec.convert.pack"); cover("kernel.rtlil.sigspec.convert.pack");
log_assert(that->chunks_.empty());
std::vector<RTLIL::SigBit> old_bits; HellVector old_bit_hell;
std::vector<RTLIL::SigChunk> new_chunks; old_bit_hell.swap(that->hell_);
old_bits.swap(that->bits_); HellVector::mock_vector<SigBit> old_bits(old_bit_hell);
RTLIL::SigChunk *last = NULL; RTLIL::SigChunk *last = NULL;
int last_end_offset = 0; int last_end_offset = 0;
@ -4070,14 +4014,11 @@ void RTLIL::SigSpec::pack() const
continue; continue;
} }
} }
new_chunks.push_back(bit); that->chunks_.push_back(bit);
last = &new_chunks.back(); last = &that->chunks_.back();
last_end_offset = bit.offset + 1; last_end_offset = bit.offset + 1;
} }
that->switch_to_packed();
that->chunks_.swap(new_chunks);
check(); check();
} }
@ -4085,21 +4026,19 @@ void RTLIL::SigSpec::unpack() const
{ {
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
if (!packed_ || that->chunks_.empty()) if (that->chunks_.empty())
return; return;
cover("kernel.rtlil.sigspec.convert.unpack"); cover("kernel.rtlil.sigspec.convert.unpack");
log_assert(that->bits_.empty());
std::vector<RTLIL::SigBit> new_bits; that->bits_.reserve(that->width_);
new_bits.reserve(that->width_);
for (auto &c : that->chunks_) for (auto &c : that->chunks_)
for (int i = 0; i < c.width; i++) for (int i = 0; i < c.width; i++)
new_bits.emplace_back(c, i); that->bits_.emplace_back(c, i);
that->chunks_.clear(); that->chunks_.clear();
that->hash_ = 0; that->hash_ = 0;
that->switch_to_unpacked();
that->bits_.swap(new_bits);
} }
void RTLIL::SigSpec::updhash() const void RTLIL::SigSpec::updhash() const
@ -4142,7 +4081,7 @@ void RTLIL::SigSpec::sort_and_unify()
// A copy of the bits vector is used to prevent duplicating the logic from // A copy of the bits vector is used to prevent duplicating the logic from
// SigSpec::SigSpec(std::vector<SigBit>). This incurrs an extra copy but // SigSpec::SigSpec(std::vector<SigBit>). This incurrs an extra copy but
// that isn't showing up as significant in profiles. // that isn't showing up as significant in profiles.
std::vector<SigBit> unique_bits = bits_; bit_vec_type unique_bits = bits_;
std::sort(unique_bits.begin(), unique_bits.end()); std::sort(unique_bits.begin(), unique_bits.end());
auto last = std::unique(unique_bits.begin(), unique_bits.end()); auto last = std::unique(unique_bits.begin(), unique_bits.end());
unique_bits.erase(last, unique_bits.end()); unique_bits.erase(last, unique_bits.end());
@ -4383,11 +4322,11 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLI
log_assert(other == NULL || width_ == other->width_); log_assert(other == NULL || width_ == other->width_);
RTLIL::SigSpec ret; RTLIL::SigSpec ret;
std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector(); bit_vec_type bits_match = to_sigbit_vector();
for (auto& pattern_chunk : pattern.chunks()) { for (auto& pattern_chunk : pattern.chunks()) {
if (other) { if (other) {
std::vector<RTLIL::SigBit> bits_other = other->to_sigbit_vector(); bit_vec_type bits_other = other->to_sigbit_vector();
for (int i = 0; i < width_; i++) for (int i = 0; i < width_; i++)
if (bits_match[i].wire && if (bits_match[i].wire &&
bits_match[i].wire == pattern_chunk.wire && bits_match[i].wire == pattern_chunk.wire &&
@ -4417,11 +4356,11 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const
log_assert(other == NULL || width_ == other->width_); log_assert(other == NULL || width_ == other->width_);
std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector(); bit_vec_type bits_match = to_sigbit_vector();
RTLIL::SigSpec ret; RTLIL::SigSpec ret;
if (other) { if (other) {
std::vector<RTLIL::SigBit> bits_other = other->to_sigbit_vector(); bit_vec_type bits_other = other->to_sigbit_vector();
for (int i = 0; i < width_; i++) for (int i = 0; i < width_; i++)
if (bits_match[i].wire && pattern.count(bits_match[i])) if (bits_match[i].wire && pattern.count(bits_match[i]))
ret.append(bits_other[i]); ret.append(bits_other[i]);
@ -4458,7 +4397,7 @@ void RTLIL::SigSpec::remove_const()
{ {
cover("kernel.rtlil.sigspec.remove_const.packed"); cover("kernel.rtlil.sigspec.remove_const.packed");
std::vector<RTLIL::SigChunk> new_chunks; chunk_vec_type new_chunks(hell_);
new_chunks.reserve(GetSize(chunks_)); new_chunks.reserve(GetSize(chunks_));
width_ = 0; width_ = 0;
@ -4480,7 +4419,7 @@ void RTLIL::SigSpec::remove_const()
{ {
cover("kernel.rtlil.sigspec.remove_const.unpacked"); cover("kernel.rtlil.sigspec.remove_const.unpacked");
std::vector<RTLIL::SigBit> new_bits; bit_vec_type new_bits(hell_);
new_bits.reserve(width_); new_bits.reserve(width_);
for (auto &bit : bits_) for (auto &bit : bits_)
@ -4679,6 +4618,7 @@ void RTLIL::SigSpec::check(Module *mod) const
w += chunk.width; w += chunk.width;
} }
log_assert(w == width_); log_assert(w == width_);
log_assert(bits_.empty());
} }
else else
{ {
@ -4689,7 +4629,9 @@ void RTLIL::SigSpec::check(Module *mod) const
if (bits_[i].wire != nullptr) if (bits_[i].wire != nullptr)
log_assert(bits_[i].wire->module == mod); log_assert(bits_[i].wire->module == mod);
} }
log_assert(width_ == GetSize(bits_)); log_assert(width_ == GetSize(bits_));
log_assert(chunks_.empty());
} }
} }
#endif #endif
@ -5022,7 +4964,7 @@ pool<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_pool() const
return sigbits; return sigbits;
} }
std::vector<RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_vector() const RTLIL::SigSpec::bit_vec_type RTLIL::SigSpec::to_sigbit_vector() const
{ {
cover("kernel.rtlil.sigspec.to_sigbit_vector"); cover("kernel.rtlil.sigspec.to_sigbit_vector");

View file

@ -843,6 +843,7 @@ struct RTLIL::SigSpecConstIterator
struct RTLIL::HellVector struct RTLIL::HellVector
{ {
private: private:
// TODO spend at least ten seconds thinking about alignment
std::vector<char> backing; std::vector<char> backing;
void dump() { void dump() {
std::cout << "Dumping, size is " << backing.size() << std::endl; std::cout << "Dumping, size is " << backing.size() << std::endl;
@ -853,119 +854,243 @@ struct RTLIL::HellVector
} }
} }
public: public:
// template <typename T>
// using iterator = T*;
// template <typename T>
// using const_iterator = T*;
template<typename T> class mock_vector;
template<typename T> class iterator { template<typename T> class iterator {
friend mock_vector<T>;
private: private:
HellVector *const parent; char* position;
int position;
public: public:
typedef std::bidirectional_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
typedef T value_type; typedef T value_type;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
typedef T* pointer; typedef T* pointer;
typedef T& reference; typedef T& reference;
iterator (HellVector* parent, int position) : parent(parent), position(position) {} iterator (char* position) : position(position) {}
T& operator* () { T& operator* () const {
char* as_char = &parent->backing[position * sizeof(T)]; return *(T*)position;
return *(T*)as_char; }
T* operator-> () const {
return (const T*)position;
}
iterator<T> operator+(size_t i) {
return iterator<T>((char*)((T*)position + i));
}
size_t operator-(iterator<T> other) {
return (size_t)(position - other.position) / sizeof(T);
}
iterator<T> operator-(size_t i) {
return iterator<T>(position - i * sizeof(T));
} }
iterator<T>& operator++() { iterator<T>& operator++() {
position += 1; position += sizeof(T);
return *this; return *this;
} }
iterator<T>& operator--() { iterator<T>& operator--() {
position -= 1; position -= sizeof(T);
return *this; return *this;
} }
iterator<T>& operator++(int) {
position += sizeof(T);
return *this;
}
iterator<T>& operator--(int) {
position -= sizeof(T);
return *this;
}
bool operator<(const iterator& other) const {
return position < other.position;
}
bool operator==(const iterator &other) const { bool operator==(const iterator &other) const {
return position == other.position; return position == other.position;
} }
bool operator!=(const iterator& other) const { bool operator!=(const iterator& other) const {
return !operator==(other); return !operator==(other);
} }
}; };
template<typename T> class const_iterator { template<typename T> class const_iterator {
friend mock_vector<T>;
private: private:
const HellVector *const parent; char* position;
int position;
public: public:
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
typedef T value_type; typedef T value_type;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
typedef T* pointer; typedef T* pointer;
typedef T& reference; typedef T& reference;
const_iterator (const HellVector* parent, int position) : parent(parent), position(position) {} const_iterator (char* position) : position(position) {}
const T& operator* () { const T& operator* () const {
const char* as_char = &parent->backing[position * sizeof(T)]; return *(const T*)position;
return *(const T*)as_char; }
const T* operator-> () const {
return (const T*)position;
}
const_iterator<T> operator+(size_t i) {
return const_iterator<T>((char*)((T*)position + i));
}
size_t operator-(const_iterator<T> other) {
return (size_t)(position - other.position) / sizeof(T);
}
const_iterator<T> operator-(size_t i) {
return const_iterator<T>(position - i * sizeof(T));
} }
const_iterator<T>& operator++() { const_iterator<T>& operator++() {
position += 1; position += sizeof(T);
return *this; return *this;
} }
const_iterator<T>& operator-() { const_iterator<T>& operator--() {
position -= 1; position -= sizeof(T);
return *this; return *this;
} }
const_iterator<T>& operator++(int) {
position += sizeof(T);
return *this;
}
const_iterator<T>& operator--(int) {
position -= sizeof(T);
return *this;
}
bool operator<(const const_iterator& other) const {
return position < other.position;
}
bool operator==(const const_iterator &other) const { bool operator==(const const_iterator &other) const {
return position == other.position; return position == other.position;
} }
bool operator!=(const const_iterator& other) const { bool operator!=(const const_iterator& other) const {
return !operator==(other); return !operator==(other);
} }
}; };
template <typename T>
using reverse_iterator = std::reverse_iterator<iterator<T>>;
template <typename T>
using const_reverse_iterator = std::reverse_iterator<const_iterator<T>>;
template<typename T> class mock_vector { template<typename T> class mock_vector {
const HellVector *const parent; HellVector& parent;
public: public:
mock_vector(HellVector* parent) {parent(parent)} mock_vector(HellVector& p) : parent(p) {}
void clear() { template<class... Args>
backing.clear(); T& emplace_back(Args&&... args) {
// TODO optimize this
push_back(T(std::forward<Args>(args)...));
return back();
} }
bool empty() const { void reserve(size_t n) {
return backing.empty(); parent.backing.reserve(sizeof(T) * n);
} }
template<typename T> iterator<T> begin() { void push_back(T t) {
return iterator<T>(this, 0); std::cout << "Pushing " << std::dec << sizeof(T) << " bytes" << std::endl;
auto size = parent.backing.size();
parent.backing.resize(size + sizeof(T));
memcpy((void*) &parent.backing[size], (void*) &t, sizeof(T));
// dump();
// parent.backing.push_back<T>(t);
} }
template<typename T> iterator<T> end() { T& operator[](size_t i) {
return iterator<T>(this, backing.size() / sizeof(T)); char* as_char = &parent.backing[i * sizeof(T)];
}
template<typename T> const_iterator<T> begin() const {
return const_iterator<T>(this, 0);
}
template<typename T> const_iterator<T> end() const {
return const_iterator<T>(this, backing.size() / sizeof(T));
}
template<typename T> T& at(int i) {
char* as_char = &parent->backing[i * sizeof(T)];
return *(T*)as_char; return *(T*)as_char;
} }
template<typename T> const T& at(int i) { const T& operator[](size_t i) const {
const char* as_char = &parent->backing[i * sizeof(T)]; const char* as_char = &parent.backing[i * sizeof(T)];
return *(const T*)as_char; return *(T*)as_char;
}
T& at(size_t i) {
if (i >= parent.backing.size() / sizeof(T))
throw std::out_of_range("HellVector::mock_vector.at(size_t i)");
return (*this)[i];
}
const T& at(size_t i) const {
if (i >= parent.backing.size() / sizeof(T))
throw std::out_of_range("HellVector::mock_vector.at(size_t i)");
return (*this)[i];
}
// Unlike with std::vector, this kind of signature doesn't provide a return value because I didn't feel like it
void erase(iterator<T> it) {
size_t position = it - begin();
(void)parent.backing.erase(parent.backing.begin() + position * sizeof(T), parent.backing.begin() + (position + 1) * sizeof(T));
}
void erase(const_iterator<T> it) {
size_t position = it - begin();
(void)parent.backing.erase(parent.backing.begin() + position * sizeof(T), parent.backing.begin() + (position + 1) * sizeof(T));
}
void erase(iterator<T> first_it, iterator<T> last_it) {
size_t first = first_it - begin();
size_t last = last_it - begin();
(void)parent.backing.erase(parent.backing.begin() + first * sizeof(T), parent.backing.begin() + last * sizeof(T));
}
void erase(const_iterator<T> first_it, const_iterator<T> last_it) {
size_t first = first_it - begin();
size_t last = last_it - begin();
(void)parent.backing.erase(parent.backing.begin() + first * sizeof(T), parent.backing.begin() + last * sizeof(T));
}
iterator<T> insert(iterator<T> pos_it, const T& value) {
size_t position = pos_it - begin();
// vector<char> allows us to use char* as iterators for the source range of the insert
auto backing_it = parent.backing.insert(parent.backing.begin() + (position * sizeof(T)), &value, &value + 1);
size_t ret_position = (backing_it - parent.backing.begin()) / sizeof(T);
return begin() + ret_position;
}
iterator<T> insert(iterator<T> pos_it, const_iterator<T> first_it, const_iterator<T> last_it) {
size_t backing_position = (pos_it - begin()) * sizeof(T);
// vector<char> allows us to use char* as iterators for the source range of the insert
auto backing_it = parent.backing.insert(parent.backing.begin() + backing_position, first_it.position, last_it.position);
size_t ret_position = (backing_it - parent.backing.begin()) / sizeof(T);
return begin() + ret_position;
}
void swap(mock_vector<T>& other) {
parent.backing.swap(other.parent.backing);
}
void clear() {
parent.backing.clear();
}
size_t size() const {
return parent.backing.size() / sizeof(T);
}
bool empty() const {
return parent.backing.empty();
}
iterator<T> begin() {
return iterator<T>(&parent.backing[0]);
}
iterator<T> end() {
return iterator<T>(&parent.backing[parent.backing.size()]);
}
const_iterator<T> begin() const {
return const_iterator<T>(&parent.backing[0]);
}
const_iterator<T> end() const {
return const_iterator<T>(&parent.backing[parent.backing.size()]);
}
reverse_iterator<T> rbegin() {
return reverse_iterator<T>(end());
}
reverse_iterator<T> rend() {
return reverse_iterator<T>(begin());
}
const_reverse_iterator<T> rbegin() const {
return const_reverse_iterator<T>(end());
}
const_reverse_iterator<T> rend() const {
return const_reverse_iterator<T>(begin());
}
T& front() {
return (*this)[0];
}
T& back() {
return (*this)[parent.backing.size() / sizeof(T) - 1];
}
const T& front() const {
return (*this)[0];
}
const T& back() const {
return (*this)[parent.backing.size() / sizeof(T) - 1];
} }
}; };
bool empty() const { void swap(HellVector& other) {
return backing.empty(); other.backing.swap(backing);
} }
template<typename T> size_t size() const {
return backing.size() / sizeof(T);
}
template<typename T> void push_back(T& thing) {
std::cout << "Pushing " << std::dec << sizeof(T) << " bytes" << std::endl;
auto size = backing.size();
backing.resize(size + sizeof(T));
memcpy((void*) &backing[size], (void*) &thing, sizeof(T));
// dump();
}
SigBit &bit(size_t position) const {
void* eee = (void*)(&backing[position * sizeof(SigBit)]);
return *(SigBit*) eee;
}
SigChunk &chunk(size_t position) const {
void* eee = (void*)(&backing[position * sizeof(SigChunk)]);
return *(SigChunk*) eee;
}
}; };
struct RTLIL::SigSpec struct RTLIL::SigSpec
@ -973,13 +1098,20 @@ struct RTLIL::SigSpec
private: private:
int width_; int width_;
bool packed_; bool packed_;
unsigned long hash_; mutable unsigned long hash_;
HellVector hell_; mutable HellVector hell_;
typedef HellVector::mock_vector<SigBit> bit_vec_type;
typedef HellVector::mock_vector<SigChunk> chunk_vec_type;
bit_vec_type bits_;
chunk_vec_type chunks_;
void pack() const; void pack() const;
void unpack() const; void unpack() const;
void switch_to_packed() const; void switch_to_packed();
void switch_to_unpacked() const; void switch_to_unpacked();
void updhash() const; void updhash() const;
inline bool packed() const { inline bool packed() const {
@ -987,7 +1119,7 @@ private:
} }
inline void inline_unpack() const { inline void inline_unpack() const {
if (packed_ && !hell_.empty()) if (packed_ && !chunks_.empty())
unpack(); unpack();
} }
@ -996,10 +1128,10 @@ private:
friend struct RTLIL::Module; friend struct RTLIL::Module;
public: public:
SigSpec() : width_(0), packed_(true), hash_(0), hell_(), bits_(&hell_), chunks_(&hell_) {} SigSpec() : width_(0), packed_(true), hash_(0), hell_(), bits_(hell_), chunks_(hell_) {}
// ~SigSpec() { if (packed_) chunks_.~vector(); else bits_.~vector(); } // ~SigSpec() { if (packed_) chunks_.~vector(); else bits_.~vector(); }
SigSpec(std::initializer_list<RTLIL::SigSpec> parts); SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
SigSpec(const Yosys::RTLIL::SigSpec &other) : width_(other.width_), packed_(other.packed_), hash_(other.hash_), hell_(other.hell_), bits_(&hell_), chunks_(&hell_) { check(); } SigSpec(const Yosys::RTLIL::SigSpec &other) : width_(other.width_), packed_(other.packed_), hash_(other.hash_), hell_(other.hell_), bits_(hell_), chunks_(hell_) { check(); }
SigSpec& operator=(const Yosys::RTLIL::SigSpec & other) SigSpec& operator=(const Yosys::RTLIL::SigSpec & other)
{ {
hell_ = other.hell_; hell_ = other.hell_;
@ -1022,6 +1154,8 @@ public:
SigSpec(const RTLIL::SigBit &bit, int width = 1); SigSpec(const RTLIL::SigBit &bit, int width = 1);
SigSpec(const std::vector<RTLIL::SigChunk> &chunks); SigSpec(const std::vector<RTLIL::SigChunk> &chunks);
SigSpec(const std::vector<RTLIL::SigBit> &bits); SigSpec(const std::vector<RTLIL::SigBit> &bits);
SigSpec(const chunk_vec_type &chunks);
SigSpec(const bit_vec_type &bits);
SigSpec(const pool<RTLIL::SigBit> &bits); SigSpec(const pool<RTLIL::SigBit> &bits);
SigSpec(const std::set<RTLIL::SigBit> &bits); SigSpec(const std::set<RTLIL::SigBit> &bits);
explicit SigSpec(bool bit); explicit SigSpec(bool bit);
@ -1031,19 +1165,19 @@ public:
return hash_; return hash_;
} }
HellVector::mock_vector<SigBit> bits_; inline const auto &chunks() const { pack(); return chunks_; }
HellVector::mock_vector<SigChunk> chunks_; inline const auto &bits() const { inline_unpack(); return bits_; }
inline int size() const { return width_; } inline int size() const { return width_; }
inline bool empty() const { return width_ == 0; } inline bool empty() const { return width_ == 0; }
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } inline RTLIL::SigBit &operator[](int index) { inline_unpack(); SigBit& bit = bits_.at(index); return bit; }
inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return chunks_.at(index); } inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); const SigBit& bit = bits_.at(index); return bit; }
inline auto begin() { HellVector::iterator<SigBit> it(&hell_, 0); return it; } inline auto begin() { return bits_.begin(); }
inline auto end() { HellVector::iterator<SigBit> it(&hell_, hell_.size<SigBit>()); return it; } inline auto end() { return bits_.end(); }
inline auto begin() const { HellVector::const_iterator<SigBit> it(&hell_, 0); return it; } inline auto begin() const { return bits_.begin(); }
inline auto end() const { HellVector::const_iterator<SigBit> it(&hell_, hell_.size<SigBit>()); return it; } inline auto end() const { return bits_.end(); }
// inline auto end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } // inline auto end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; }
// inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; } // inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
@ -1128,7 +1262,7 @@ public:
std::set<RTLIL::SigBit> to_sigbit_set() const; std::set<RTLIL::SigBit> to_sigbit_set() const;
pool<RTLIL::SigBit> to_sigbit_pool() const; pool<RTLIL::SigBit> to_sigbit_pool() const;
std::vector<RTLIL::SigBit> to_sigbit_vector() const; bit_vec_type to_sigbit_vector() const;
std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const; std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const;
dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const; dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const;
@ -1864,7 +1998,7 @@ inline unsigned int RTLIL::SigBit::hash() const {
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
log_assert(sig.size() == 1); log_assert(sig.size() == 1);
*this = SigBit(*sig.chunks()); *this = SigBit(sig.chunks().front());
} }
template<typename T> template<typename T>