@@ -413,9 +413,10 @@ dbSet<dbITerm> dbModNet::getITerms() const
413413 return dbSet<dbITerm>(_mod_net, _block->_module_modnet_iterm_itr );
414414}
415415
416- unsigned dbModNet::connectionCount ()
416+ unsigned dbModNet::connectionCount () const
417417{
418- return (getITerms ().size () + getBTerms ().size () + getModITerms ().size ());
418+ return (getITerms ().size () + getBTerms ().size () + getModITerms ().size ()
419+ + getModBTerms ().size ());
419420}
420421
421422dbNet* dbModNet::findRelatedNet () const
@@ -490,6 +491,144 @@ dbNet* dbModNet::findRelatedNet() const
490491 return nullptr ;
491492}
492493
494+ void dbModNet::checkSanity () const
495+ {
496+ utl::Logger* logger = getImpl ()->getLogger ();
497+ std::vector<std::string> drvr_info_list;
498+
499+ // Find BTerm drivers
500+ for (dbBTerm* bterm : getBTerms ()) {
501+ if (bterm->getSigType ().isSupply ()) {
502+ continue ;
503+ }
504+
505+ if (bterm->getIoType () == dbIoType::INPUT
506+ || bterm->getIoType () == dbIoType::INOUT) {
507+ dbBlock* block = bterm->getBlock ();
508+ dbModule* parent_module = block->getTopModule ();
509+ drvr_info_list.push_back (fmt::format ( // NOLINT(misc-include-cleaner)
510+ " \n - bterm: '{}' (block: '{}', parent_module: '{}')" ,
511+ bterm->getName (),
512+ (block) ? block->getConstName () : " null" ,
513+ (parent_module) ? parent_module->getName () : " null" ));
514+ }
515+ }
516+
517+ // Find ITerm drivers
518+ for (dbITerm* iterm : getITerms ()) {
519+ if (iterm->getSigType ().isSupply ()) {
520+ continue ;
521+ }
522+
523+ if (iterm->getIoType () == dbIoType::OUTPUT
524+ || iterm->getIoType () == dbIoType::INOUT) {
525+ dbInst* inst = iterm->getInst ();
526+ dbMaster* master = inst->getMaster ();
527+ dbModule* parent_module = inst->getModule ();
528+ dbBlock* block = inst->getBlock ();
529+ drvr_info_list.push_back (fmt::format ( // NOLINT(misc-include-cleaner)
530+ " \n - iterm: '{}' (block: '{}', parent_module: '{}', master: '{}')" ,
531+ iterm->getName (),
532+ (block) ? block->getConstName () : " null" ,
533+ (parent_module) ? parent_module->getName () : " null" ,
534+ (master) ? master->getConstName () : " null" ));
535+ }
536+ }
537+
538+ // Find ModBTerm drivers
539+ for (dbModBTerm* modbterm : getModBTerms ()) {
540+ if (modbterm->getSigType ().isSupply ()) {
541+ continue ;
542+ }
543+
544+ if (modbterm->getIoType () == dbIoType::INPUT
545+ || modbterm->getIoType () == dbIoType::INOUT) {
546+ drvr_info_list.push_back (
547+ // NOLINTNEXTLINE(misc-include-cleaner)
548+ fmt::format (" \n - modbterm: '{}'" , modbterm->getHierarchicalName ()));
549+ }
550+ }
551+
552+ // Find ModITerm drivers
553+ for (dbModITerm* moditerm : getModITerms ()) {
554+ if (dbModBTerm* child_bterm = moditerm->getChildModBTerm ()) {
555+ if (child_bterm->getSigType ().isSupply ()) {
556+ continue ;
557+ }
558+
559+ if (child_bterm->getIoType () == dbIoType::OUTPUT
560+ || child_bterm->getIoType () == dbIoType::INOUT) {
561+ drvr_info_list.push_back (
562+ // NOLINTNEXTLINE(misc-include-cleaner)
563+ fmt::format (" \n - moditerm: '{}'" ,
564+ moditerm->getHierarchicalName ()));
565+ }
566+ }
567+ }
568+
569+ size_t drvr_count = drvr_info_list.size ();
570+ if (drvr_count > 1 ) {
571+ // Multiple drivers found.
572+ logger->warn (utl::ODB,
573+ 481 , // Reusing error code from dbNet
574+ " SanityCheck: dbModNet '{}' has multiple drivers: {}" ,
575+ getHierarchicalName (),
576+ fmt::join (drvr_info_list, " " ));
577+ }
578+
579+ const uint term_count = connectionCount ();
580+
581+ // No driver
582+ if (drvr_count == 0 && term_count > 0 ) {
583+ logger->warn (utl::ODB,
584+ 482 ,
585+ " SanityCheck: dbModNet '{}' has no driver." ,
586+ getHierarchicalName ());
587+ }
588+
589+ const uint iterm_count = getITerms ().size ();
590+ const uint bterm_count = getBTerms ().size ();
591+ const uint moditerm_count = getModITerms ().size ();
592+ const uint modbterm_count = getModBTerms ().size ();
593+
594+ if (term_count < 2 ) {
595+ // A net connected to 1 terminal
596+ if (iterm_count == 1
597+ && (*(getITerms ().begin ()))->getIoType () == dbIoType::OUTPUT) {
598+ return ; // OK: Unconnected output pin
599+ }
600+ if (bterm_count == 1
601+ && (*(getBTerms ().begin ()))->getIoType () == dbIoType::INPUT) {
602+ return ; // OK: Unconnected input port
603+ }
604+ if (moditerm_count == 1 ) {
605+ dbModITerm* moditerm = *(getModITerms ().begin ());
606+ if (dbModBTerm* child_bterm = moditerm->getChildModBTerm ()) {
607+ if (child_bterm->getIoType () == dbIoType::OUTPUT) {
608+ return ; // OK: Unconnected output pin on module instance
609+ }
610+ }
611+ }
612+ if (modbterm_count == 1 ) {
613+ dbModBTerm* modbterm = *(getModBTerms ().begin ());
614+ if (modbterm->getIoType () == dbIoType::INPUT) {
615+ return ; // OK: Unconnected input port on module
616+ }
617+ }
618+
619+ logger->warn (utl::ODB,
620+ 483 ,
621+ " SanityCheck: dbModNet '{}' is dangling. It has less than 2 "
622+ " connections (# of ITerms = {}, # of BTerms = {}, # of "
623+ " ModITerms = {}, # of ModBTerms = {})." ,
624+ getHierarchicalName (),
625+ iterm_count,
626+ bterm_count,
627+ moditerm_count,
628+ modbterm_count);
629+ }
630+ }
631+
493632// User Code End dbModNetPublicMethods
494633} // namespace odb
495634 // Generator Code End Cpp
0 commit comments