@@ -237,17 +237,51 @@ using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell
237
237
template <typename T>
238
238
class SigSet <T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};
239
239
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
+
240
276
/* *
241
277
* SigMap wraps a union-find "database"
242
278
* to map SigBits of a module to canonical representative SigBits.
243
279
* SigBits that are connected share a set in the underlying database.
244
280
* If a SigBit has a const state (impl: bit.wire is nullptr),
245
281
* it's promoted to a representative.
246
282
*/
247
- struct SigMap
283
+ struct SigMap final : public SigMapView
248
284
{
249
- mfp<SigBit> database;
250
-
251
285
SigMap (RTLIL::Module *module = NULL )
252
286
{
253
287
if (module != NULL )
@@ -320,45 +354,115 @@ struct SigMap
320
354
321
355
inline void add (Wire *wire) { return add (RTLIL::SigSpec (wire)); }
322
356
323
- // Modify bit to its representative
324
- void apply ( RTLIL::SigBit &bit ) const
357
+ // All non-const bits
358
+ RTLIL::SigSpec allbits ( ) const
325
359
{
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;
327
365
}
366
+ };
328
367
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)
330
383
{
331
- for ( auto &bit : sig)
332
- apply (bit );
384
+ database. swap (other. database );
385
+ values. swap (other. values );
333
386
}
334
387
335
- RTLIL::SigBit operator ()(RTLIL::SigBit bit) const
388
+ void clear ()
336
389
{
337
- apply (bit );
338
- return bit ;
390
+ database. clear ( );
391
+ values. clear () ;
339
392
}
340
393
341
- RTLIL::SigSpec operator ()(RTLIL::SigSpec sig) const
394
+ // Rebuild SigMap for all connections in module
395
+ void set (RTLIL::Module *module )
342
396
{
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 );
345
407
}
346
408
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)
348
411
{
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
+ }
352
434
}
353
435
354
- // All non-const bits
355
- RTLIL::SigSpec allbits () const
436
+ void addVal (const RTLIL::SigBit &bit, const Val &val)
356
437
{
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;
362
466
}
363
467
};
364
468
0 commit comments