Skip to content
Merged
6 changes: 3 additions & 3 deletions kernel/ffinit.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ YOSYS_NAMESPACE_BEGIN

struct FfInitVals
{
const SigMap *sigmap;
const SigMapView *sigmap;
dict<SigBit, std::pair<State,SigBit>> initbits;

void set(const SigMap *sigmap_, RTLIL::Module *module)
void set(const SigMapView *sigmap_, RTLIL::Module *module)
{
sigmap = sigmap_;
initbits.clear();
Expand Down Expand Up @@ -126,7 +126,7 @@ struct FfInitVals
initbits.clear();
}

FfInitVals (const SigMap *sigmap, RTLIL::Module *module)
FfInitVals (const SigMapView *sigmap, RTLIL::Module *module)
{
set(sigmap, module);
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/ffmerge.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ YOSYS_NAMESPACE_BEGIN

struct FfMergeHelper
{
const SigMap *sigmap;
const SigMapView *sigmap;
RTLIL::Module *module;
FfInitVals *initvals;

Expand Down
3 changes: 2 additions & 1 deletion kernel/hashlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,8 @@ class mfp
return p;
}

// Merge sets if the given indices belong to different sets
// Merge sets if the given indices belong to different sets.
// Makes ifind(j) the root of the merged set.
void imerge(int i, int j)
{
i = ifind(i);
Expand Down
156 changes: 130 additions & 26 deletions kernel/sigtools.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,17 +237,51 @@ using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell
template<typename T>
class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};

struct SigMapView
{
mfp<SigBit> database;

// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
}

void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
apply(bit);
}

RTLIL::SigBit operator()(RTLIL::SigBit bit) const
{
apply(bit);
return bit;
}

RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}

RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
SigSpec sig(wire);
apply(sig);
return sig;
}
};

/**
* SigMap wraps a union-find "database"
* to map SigBits of a module to canonical representative SigBits.
* SigBits that are connected share a set in the underlying database.
* If a SigBit has a const state (impl: bit.wire is nullptr),
* it's promoted to a representative.
*/
struct SigMap
struct SigMap final : public SigMapView
{
mfp<SigBit> database;

SigMap(RTLIL::Module *module = NULL)
{
if (module != NULL)
Expand Down Expand Up @@ -320,45 +354,115 @@ struct SigMap

inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); }

// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
// All non-const bits
RTLIL::SigSpec allbits() const
{
bit = database.find(bit);
RTLIL::SigSpec sig;
for (const auto &bit : database)
if (bit.wire != nullptr)
sig.append(bit);
return sig;
}
};

void apply(RTLIL::SigSpec &sig) const
/**
* SiValgMap wraps a union-find "database" to map SigBits of a module to
* canonical representative SigBits plus some optional Val value associated with the bits.
* Val has a commutative, associative, idempotent operator|=, a default constructor
* which constructs an identity element, and a copy constructor.
* SigBits that are connected share a set in the underlying database;
* the associated value is the "sum" of all the values associated with the contributing bits.
* If any of the SigBits in a set are a constant, the canonical SigBit is a constant.
*/
template <class Val>
struct SigValMap final : public SigMapView
{
dict<SigBit, Val> values;

void swap(SigValMap<Val> &other)
{
for (auto &bit : sig)
apply(bit);
database.swap(other.database);
values.swap(other.values);
}

RTLIL::SigBit operator()(RTLIL::SigBit bit) const
void clear()
{
apply(bit);
return bit;
database.clear();
values.clear();
}

RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
// Rebuild SigMap for all connections in module
void set(RTLIL::Module *module)
{
apply(sig);
return sig;
int bitcount = 0;
for (auto &it : module->connections())
bitcount += it.first.size();

database.clear();
values.clear();
database.reserve(bitcount);

for (auto &it : module->connections())
add(it.first, it.second);
}

RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
// Add connections from "from" to "to", bit-by-bit.
void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to)
{
SigSpec sig(wire);
apply(sig);
return sig;
log_assert(GetSize(from) == GetSize(to));

for (int i = 0; i < GetSize(from); i++)
{
int bfi = database.lookup(from[i]);
int bti = database.lookup(to[i]);
if (bfi == bti) {
continue;
}

const RTLIL::SigBit &bf = database[bfi];
const RTLIL::SigBit &bt = database[bti];
if (bf.wire == nullptr) {
// bf is constant so make it the canonical representative.
database.imerge(bti, bfi);
merge_value(bt, bf);
} else {
// Make bt the canonical representative.
database.imerge(bfi, bti);
merge_value(bf, bt);
}
}
}

// All non-const bits
RTLIL::SigSpec allbits() const
void addVal(const RTLIL::SigBit &bit, const Val &val)
{
RTLIL::SigSpec sig;
for (const auto &bit : database)
if (bit.wire != nullptr)
sig.append(bit);
return sig;
values[database.find(bit)] |= val;
}

void addVal(const RTLIL::SigSpec &sig, const Val &val)
{
for (const auto &bit : sig)
addVal(bit, val);
}

Val apply_and_get_value(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
auto it = values.find(bit);
return it == values.end() ? Val() : it->second;
}

private:
void merge_value(const RTLIL::SigBit &from, const RTLIL::SigBit &to)
{
auto it = values.find(from);
if (it == values.end()) {
return;
}
// values[to] could resize the underlying `entries` so
// finish using `it` first.
Val v = it->second;
values.erase(it);
values[to] |= v;
}
};

Expand Down
Loading
Loading