@@ -4163,12 +4163,16 @@ void dbNetwork::accumulateFlatLoadPinsOnNet(
41634163 visitConnectedPins (net, rp, visited_nets);
41644164}
41654165
4166- void dbNetwork::AxiomCheck ()
4166+ // Use this API to check if flat & hier connectivities are ok
4167+ void dbNetwork::checkAxioms ()
41674168{
4168- dbSet<dbModNet> mod_nets = block ()->getModNets ();
4169- for (auto mod_net : mod_nets) {
4170- findRelatedDbNet (mod_net);
4171- }
4169+ checkSanityModBTerms ();
4170+ checkSanityModITerms ();
4171+ checkSanityModuleInsts ();
4172+ checkSanityModInstTerms ();
4173+ checkSanityUnusedModules ();
4174+ checkSanityTermConnectivity ();
4175+ checkSanityNetConnectivity ();
41724176}
41734177
41744178Net* dbNetwork::getFlatNet (Net* net) const
@@ -4186,4 +4190,184 @@ Net* dbNetwork::getFlatNet(Net* net) const
41864190 return dbToSta (db_net);
41874191}
41884192
4193+ void dbNetwork::checkSanityModBTerms ()
4194+ {
4195+ if (block_ == nullptr ) {
4196+ return ;
4197+ }
4198+ for (odb::dbModule* module : block_->getModules ()) {
4199+ std::set<std::string> bterm_names;
4200+ for (odb::dbModBTerm* bterm : module ->getModBTerms ()) {
4201+ const std::string bterm_name = bterm->getName ();
4202+ if (bterm_names.find (bterm_name) != bterm_names.end ()) {
4203+ logger_->error (
4204+ ORD,
4205+ 2036 ,
4206+ " SanityCheck: Duplicate dbModBTerm name '{}' in module '{}'." ,
4207+ bterm_name,
4208+ module ->getName ());
4209+ }
4210+ bterm_names.insert (bterm_name);
4211+ }
4212+ }
4213+ }
4214+
4215+ void sta::dbNetwork::checkSanityModITerms ()
4216+ {
4217+ if (block_ == nullptr ) {
4218+ return ;
4219+ }
4220+ for (odb::dbModInst* mod_inst : block_->getModInsts ()) {
4221+ std::set<std::string> iterm_names;
4222+ for (odb::dbModITerm* iterm : mod_inst->getModITerms ()) {
4223+ const std::string iterm_name = iterm->getName ();
4224+ if (iterm_names.find (iterm_name) != iterm_names.end ()) {
4225+ logger_->error (ORD,
4226+ 2037 ,
4227+ " SanityCheck: Duplicate dbModITerm name '{}' in module "
4228+ " instance '{}'." ,
4229+ iterm_name,
4230+ mod_inst->getName ());
4231+ }
4232+ iterm_names.insert (iterm_name);
4233+ }
4234+ }
4235+ }
4236+
4237+ void dbNetwork::checkSanityModuleInsts ()
4238+ {
4239+ for (odb::dbModule* module : block_->getModules ()) {
4240+ if (module ->getModInsts ().empty () && module ->getInsts ().empty ()) {
4241+ logger_->warn (ORD,
4242+ 2038 ,
4243+ " SanityCheck: Module '{}' has no instances." ,
4244+ module ->getHierarchicalName ());
4245+ }
4246+ }
4247+ }
4248+
4249+ void dbNetwork::checkSanityModInstTerms ()
4250+ {
4251+ for (odb::dbModInst* mod_inst : block_->getModInsts ()) {
4252+ odb::dbModule* master = mod_inst->getMaster ();
4253+ if (master) {
4254+ if (mod_inst->getModITerms ().size () != master->getModBTerms ().size ()) {
4255+ logger_->warn (
4256+ ORD,
4257+ 2042 ,
4258+ " SanityCheck: Module instance '{}' has {} ITerms, but its "
4259+ " master '{}' has {} BTerms." ,
4260+ mod_inst->getHierarchicalName (),
4261+ mod_inst->getModITerms ().size (),
4262+ master->getHierarchicalName (),
4263+ master->getModBTerms ().size ());
4264+ }
4265+ }
4266+ }
4267+ }
4268+
4269+ void dbNetwork::checkSanityUnusedModules ()
4270+ {
4271+ if (block_ == nullptr ) {
4272+ return ;
4273+ }
4274+
4275+ // 1. Collect all modules from the top block and its children.
4276+ // Unused modules may be placed in child blocks.
4277+ std::vector<odb::dbModule*> all_modules;
4278+ for (odb::dbModule* module : block_->getModules ()) {
4279+ all_modules.push_back (module );
4280+ }
4281+ for (odb::dbBlock* child_block : block_->getChildren ()) {
4282+ for (odb::dbModule* module : child_block->getModules ()) {
4283+ all_modules.push_back (module );
4284+ }
4285+ }
4286+
4287+ // 2. Create a set of all instantiated module masters.
4288+ std::set<odb::dbModule*> instantiated_masters;
4289+ for (odb::dbModule* module : all_modules) {
4290+ for (odb::dbModInst* mod_inst : module ->getModInsts ()) {
4291+ instantiated_masters.insert (mod_inst->getMaster ());
4292+ }
4293+ }
4294+
4295+ // 3. Iterate through all collected modules to check for usage.
4296+ odb::dbModule* top_module = block_->getTopModule ();
4297+ for (odb::dbModule* module : all_modules) {
4298+ // A module is unused if it's not the top module and it's not a master
4299+ // for any module instance.
4300+ if (module != top_module
4301+ && instantiated_masters.find (module ) == instantiated_masters.end ()) {
4302+ logger_->warn (
4303+ ORD,
4304+ 2043 ,
4305+ " SanityCheck: Module '{}' is defined but never instantiated." ,
4306+ module ->getName ());
4307+ }
4308+ }
4309+ }
4310+
4311+ void dbNetwork::checkSanityTermConnectivity ()
4312+ {
4313+ for (odb::dbBTerm* bterm : block_->getBTerms ()) {
4314+ if (bterm->getIoType () != dbIoType::INPUT && bterm->getNet () == nullptr ) {
4315+ logger_->error (
4316+ ORD,
4317+ 2040 ,
4318+ " SanityCheck: non-input BTerm '{}' is not connected to any net." ,
4319+ bterm->getName ());
4320+ }
4321+ }
4322+
4323+ for (odb::dbInst* inst : block_->getInsts ()) {
4324+ for (odb::dbITerm* iterm : inst->getITerms ()) {
4325+ if (iterm->getIoType () != dbIoType::OUTPUT
4326+ && iterm->getNet () == nullptr ) {
4327+ logger_->error (ORD,
4328+ 2041 ,
4329+ " SanityCheck: non-output ITerm '{}/{}' is not connected "
4330+ " to any net." ,
4331+ inst->getName (),
4332+ iterm->getMTerm ()->getName ());
4333+ }
4334+ }
4335+ }
4336+ }
4337+
4338+ void dbNetwork::checkSanityNetConnectivity ()
4339+ {
4340+ // Check for hier net and flat net connectivity
4341+ dbSet<dbModNet> mod_nets = block ()->getModNets ();
4342+ for (auto mod_net : mod_nets) {
4343+ findRelatedDbNet (mod_net);
4344+ }
4345+
4346+ // Check for incomplete flat net connections
4347+ for (odb::dbNet* net : block_->getNets ()) {
4348+ const auto iterm_count = net->getITerms ().size ();
4349+ const auto bterm_count = net->getBTerms ().size ();
4350+ if (iterm_count + bterm_count >= 2 ) {
4351+ continue ;
4352+ }
4353+
4354+ if (iterm_count == 1 ) {
4355+ odb::dbITerm* iterm = *(net->getITerms ().begin ());
4356+ if (iterm->getIoType () == odb::dbIoType::OUTPUT) {
4357+ continue ; // OK: Unconnected output pin
4358+ }
4359+ } else if (bterm_count == 1 ) { // This is a top level port
4360+ odb::dbBTerm* bterm = *(net->getBTerms ().begin ());
4361+ if (bterm->getIoType () == odb::dbIoType::INPUT) {
4362+ continue ; // OK: Unconnected input port
4363+ }
4364+ }
4365+
4366+ logger_->error (ORD,
4367+ 2039 ,
4368+ " SanityCheck: Net '{}' has less than 2 connections." ,
4369+ net->getName ());
4370+ }
4371+ }
4372+
41894373} // namespace sta
0 commit comments