Skip to content

Commit 2654bd5

Browse files
committed
Compute is_port in AbcPass without iterating through all cells and wires in the module every time we run ABC.
This does not scale when we run ABC thousands of times in a single AbcPass.
1 parent ac8259b commit 2654bd5

File tree

5 files changed

+256
-83
lines changed

5 files changed

+256
-83
lines changed

kernel/ffinit.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ YOSYS_NAMESPACE_BEGIN
2727

2828
struct FfInitVals
2929
{
30-
const SigMap *sigmap;
30+
const SigMapView *sigmap;
3131
dict<SigBit, std::pair<State,SigBit>> initbits;
3232

33-
void set(const SigMap *sigmap_, RTLIL::Module *module)
33+
void set(const SigMapView *sigmap_, RTLIL::Module *module)
3434
{
3535
sigmap = sigmap_;
3636
initbits.clear();
@@ -126,7 +126,7 @@ struct FfInitVals
126126
initbits.clear();
127127
}
128128

129-
FfInitVals (const SigMap *sigmap, RTLIL::Module *module)
129+
FfInitVals (const SigMapView *sigmap, RTLIL::Module *module)
130130
{
131131
set(sigmap, module);
132132
}

kernel/ffmerge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ YOSYS_NAMESPACE_BEGIN
5858

5959
struct FfMergeHelper
6060
{
61-
const SigMap *sigmap;
61+
const SigMapView *sigmap;
6262
RTLIL::Module *module;
6363
FfInitVals *initvals;
6464

kernel/hashlib.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,8 @@ class mfp
13531353
return p;
13541354
}
13551355

1356-
// Merge sets if the given indices belong to different sets
1356+
// Merge sets if the given indices belong to different sets.
1357+
// Makes ifind(j) the root of the merged set.
13571358
void imerge(int i, int j)
13581359
{
13591360
i = ifind(i);

kernel/sigtools.h

Lines changed: 130 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -237,17 +237,51 @@ using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell
237237
template<typename T>
238238
class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};
239239

240+
struct SigMapView
241+
{
242+
mfp<SigBit> database;
243+
244+
// Modify bit to its representative
245+
void apply(RTLIL::SigBit &bit) const
246+
{
247+
bit = database.find(bit);
248+
}
249+
250+
void apply(RTLIL::SigSpec &sig) const
251+
{
252+
for (auto &bit : sig)
253+
apply(bit);
254+
}
255+
256+
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
257+
{
258+
apply(bit);
259+
return bit;
260+
}
261+
262+
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
263+
{
264+
apply(sig);
265+
return sig;
266+
}
267+
268+
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
269+
{
270+
SigSpec sig(wire);
271+
apply(sig);
272+
return sig;
273+
}
274+
};
275+
240276
/**
241277
* SigMap wraps a union-find "database"
242278
* to map SigBits of a module to canonical representative SigBits.
243279
* SigBits that are connected share a set in the underlying database.
244280
* If a SigBit has a const state (impl: bit.wire is nullptr),
245281
* it's promoted to a representative.
246282
*/
247-
struct SigMap
283+
struct SigMap final : public SigMapView
248284
{
249-
mfp<SigBit> database;
250-
251285
SigMap(RTLIL::Module *module = NULL)
252286
{
253287
if (module != NULL)
@@ -320,45 +354,115 @@ struct SigMap
320354

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

323-
// Modify bit to its representative
324-
void apply(RTLIL::SigBit &bit) const
357+
// All non-const bits
358+
RTLIL::SigSpec allbits() const
325359
{
326-
bit = database.find(bit);
360+
RTLIL::SigSpec sig;
361+
for (const auto &bit : database)
362+
if (bit.wire != nullptr)
363+
sig.append(bit);
364+
return sig;
327365
}
366+
};
328367

329-
void apply(RTLIL::SigSpec &sig) const
368+
/**
369+
* SiValgMap wraps a union-find "database" to map SigBits of a module to
370+
* canonical representative SigBits plus some optional Val value associated with the bits.
371+
* Val has a commutative, associative, idempotent operator|=, a default constructor
372+
* which constructs an identity element, and a copy constructor.
373+
* SigBits that are connected share a set in the underlying database;
374+
* the associated value is the "sum" of all the values associated with the contributing bits.
375+
* If any of the SigBits in a set are a constant, the canonical SigBit is a constant.
376+
*/
377+
template <class Val>
378+
struct SigValMap final : public SigMapView
379+
{
380+
dict<SigBit, Val> values;
381+
382+
void swap(SigValMap<Val> &other)
330383
{
331-
for (auto &bit : sig)
332-
apply(bit);
384+
database.swap(other.database);
385+
values.swap(other.values);
333386
}
334387

335-
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
388+
void clear()
336389
{
337-
apply(bit);
338-
return bit;
390+
database.clear();
391+
values.clear();
339392
}
340393

341-
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
394+
// Rebuild SigMap for all connections in module
395+
void set(RTLIL::Module *module)
342396
{
343-
apply(sig);
344-
return sig;
397+
int bitcount = 0;
398+
for (auto &it : module->connections())
399+
bitcount += it.first.size();
400+
401+
database.clear();
402+
values.clear();
403+
database.reserve(bitcount);
404+
405+
for (auto &it : module->connections())
406+
add(it.first, it.second);
345407
}
346408

347-
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
409+
// Add connections from "from" to "to", bit-by-bit.
410+
void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to)
348411
{
349-
SigSpec sig(wire);
350-
apply(sig);
351-
return sig;
412+
log_assert(GetSize(from) == GetSize(to));
413+
414+
for (int i = 0; i < GetSize(from); i++)
415+
{
416+
int bfi = database.lookup(from[i]);
417+
int bti = database.lookup(to[i]);
418+
if (bfi == bti) {
419+
continue;
420+
}
421+
422+
const RTLIL::SigBit &bf = database[bfi];
423+
const RTLIL::SigBit &bt = database[bti];
424+
if (bf.wire == nullptr) {
425+
// bf is constant so make it the canonical representative.
426+
database.imerge(bti, bfi);
427+
merge_value(bt, bf);
428+
} else {
429+
// Make bt the canonical representative.
430+
database.imerge(bfi, bti);
431+
merge_value(bf, bt);
432+
}
433+
}
352434
}
353435

354-
// All non-const bits
355-
RTLIL::SigSpec allbits() const
436+
void addVal(const RTLIL::SigBit &bit, const Val &val)
356437
{
357-
RTLIL::SigSpec sig;
358-
for (const auto &bit : database)
359-
if (bit.wire != nullptr)
360-
sig.append(bit);
361-
return sig;
438+
values[database.find(bit)] |= val;
439+
}
440+
441+
void addVal(const RTLIL::SigSpec &sig, const Val &val)
442+
{
443+
for (const auto &bit : sig)
444+
addVal(bit, val);
445+
}
446+
447+
Val apply_and_get_value(RTLIL::SigBit &bit) const
448+
{
449+
bit = database.find(bit);
450+
auto it = values.find(bit);
451+
return it == values.end() ? Val() : it->second;
452+
}
453+
454+
private:
455+
void merge_value(const RTLIL::SigBit &from, const RTLIL::SigBit &to)
456+
{
457+
auto it = values.find(from);
458+
if (it == values.end()) {
459+
return;
460+
}
461+
// values[to] could resize the underlying `entries` so
462+
// finish using `it` first.
463+
Val v = it->second;
464+
values.erase(it);
465+
values[to] |= v;
362466
}
363467
};
364468

0 commit comments

Comments
 (0)