mirror of
https://github.com/The-OpenROAD-Project/OpenSTA.git
synced 2026-05-30 00:24:12 +08:00
commit be70d30ae05665021254b0d7e69fb8d2f0a82890 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 17:04:49 2023 -0700 cmp Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4d4ef96948afe3d6a00c4521aeb5bc74274f5737 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 16:08:50 2023 -0700 rvo, const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit bb584e4264af2bea867b17d07e8d38c0e9eb0025 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 15:05:00 2023 -0700 const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a08fe558bca6b769b2728882258bd85aed990a27 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 14:57:33 2023 -0700 LibertyPortPair no ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4d3bd60c109d1ce9d0589d746f4968fa7bebd90d Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 14:13:07 2023 -0700 cleanup Signed-off-by: James Cherry <cherry@parallaxsw.com> commit dc25ff77771cfbe26f9318bad2b3c45879614783 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 14:06:13 2023 -0700 const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 06e81586ce11a0cc06948ed78fef99353077d69e Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 14:01:10 2023 -0700 sortByName Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9d8592aff5b246f83e47e1b94490e3cef8d8e119 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 11:57:17 2023 -0700 sort pred Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 462a8e14df8b561ddfc842addc62c4b8435b6347 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 11:09:57 2023 -0700 const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69f71505b684e88b22d395510429497e87bf1015 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 10:45:14 2023 -0700 flush ConstPortSeq Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 6429d578b78eac3fe7e99fcd67a120789932b2eb Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 09:19:15 2023 -0700 rm ConstNetSet Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f247930b16e40560b957a36af68947249ed1ef04 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 17 08:50:50 2023 -0700 sortPathNames Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4ca2b0e0af7252c7bcbc65cf141d0ce40634d329 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 10:14:05 2023 -0700 const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 3d18640d2ebc4aae3098c7e7242a554fcb64fd42 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 09:41:27 2023 -0700 set_input/ouput_delay -reference_pin Signed-off-by: James Cherry <cherry@parallaxsw.com> commit d4a0854dd2102f46f96a94fb9eb8749f1593a85f Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 09:13:46 2023 -0700 PinPairSet no malloc Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a6f1583fc6a856c5ecc0dcb15a1d8b1f61e30718 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 08:53:33 2023 -0700 no malloc for EdgePins Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c8e4b92e8b619109d6aa3c141c720646067ccb4b Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 06:31:08 2023 +0000 leak commit abab99e0fc3e466d914f6c1705aa08cdc204df51 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 16 06:07:36 2023 +0000 leaks commit d1913b554bb6e98b89673d80d2295f552eb4ffca Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 19:48:39 2023 -0700 LibertyCell::checkCornerCell Signed-off-by: James Cherry <cherry@parallaxsw.com> commit bcc172237d48deed647374f9592bac70bd2d5425 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 18:19:47 2023 -0700 rvo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8ef9800b87f5e5548055a13afc21397f28a6bcf7 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 18:07:46 2023 -0700 sdc net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit d7235abed04ced4e2d84e91bf9968e621268567d Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 16:00:27 2023 -0700 range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a22f91a3c54c644574339d1126821d9bc8045bd6 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 15:52:50 2023 -0700 range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 762615ce3de91d950eeaaa4680549a45b13e0e0a Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 15:42:19 2023 -0700 range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 7e0c531613d343d23f064c24873bf5a498f6f4ce Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 12:26:49 2023 -0700 rm removeLoadCaps, removeNetLoadCaps Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f2e88c6082e2d4605e9849348008bf4065401fc8 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 12:21:03 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit b5939666188c0b94dfe957e22bbd8a92f4786125 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 11:36:16 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a435081bafe10260743319f53a59cbe2ed0388b7 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 08:43:37 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit acfb247559db7b726d47f203613488df0f7add53 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 08:38:07 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 7541b71da92ea15085615988a1e6ea1d4d53d8d6 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 08:00:55 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit d033210132656ea68fa834228575b9def1d02d90 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 07:52:03 2023 -0700 sdc rm map ptrs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ca6e9ecb7821b83ab024c4fee6df8f7fc8fc2ce2 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 07:38:12 2023 -0700 instance_pvt_maps_ Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 631e4209b596386f5818045d521784db5239f58d Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 07:26:42 2023 -0700 rm GroupPathIterator Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 059c32afa87617fff530c9afa1ef8005a136739d Author: James Cherry <cherry@parallaxsw.com> Date: Sat Jan 14 20:07:44 2023 -0700 rm ClockIterator Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c65fe873a6a6696220bbb44c4ecac87d5ca978ac Author: James Cherry <cherry@parallaxsw.com> Date: Sat Jan 14 19:45:58 2023 -0700 rvo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ce15c9a0cc78915acddc2f03749573d989ae96d6 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 15 01:04:03 2023 +0000 leaks commit f97955a0c7e70b65ceb3f697ff47c0524a9b3cd4 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Jan 14 01:17:58 2023 +0000 leaks commit 7cdd65684adeb14e02827f5d93e7fab3b19af5dd Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 16:07:47 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ee97c7e50394a3927458e7ef09c5dbeb27719d15 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 11:52:48 2023 -0700 swig rm Tmp collections Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c49935da8704e41459280971b7645fccd97e3d13 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 11:18:36 2023 -0700 swig rm Tmp types Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4320b00ce700914843006f592126cd8cc1c4657a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 10:55:10 2023 -0700 swig rm TmpPinSet, TmpPinSeq Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ff6004910980c9b09b41f63a553a4481404cc539 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 10:45:06 2023 -0700 swig rm Tmp collections Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9a5bf5c1a3e5a6d2996b3ab327fa2f3015f2ff20 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 10:15:29 2023 -0700 swig rm one TmpPinSet Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f441116b56e23849485b2393b30e7086c33165a8 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 09:16:56 2023 -0700 leak Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 050b08df8618340b568d9cd41fd3d5f052e2c680 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 09:10:53 2023 -0700 leak Signed-off-by: James Cherry <cherry@parallaxsw.com> commit be8c17f3a715ab53140748dc1d94698209965cf9 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Jan 13 08:59:06 2023 -0700 leak Signed-off-by: James Cherry <cherry@parallaxsw.com> commit e43b82f8fb52eaeda90e3c7e76cf350ae6735ebd Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 18:57:49 2023 -0700 range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8db56209de7805ac2574fd2f76170bf68afd156d Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 18:08:54 2023 -0700 GroupPathSet net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cb7917f9827c2ea3afebd735cd4508405a0d77d4 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 12:00:15 2023 -0700 DataCheckLess net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit d9da3c62d7a76699c6ad62cebb1f5c39f89722fa Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 11:42:27 2023 -0700 rm hashPtr uses Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5bbea162bb1e023aba813598c7992c740ddf9d0b Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 11:30:12 2023 -0700 EdgePins has use net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit df38405e2ebaabdd7bbf99f3b19d78b25bd95720 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 09:51:38 2023 -0700 ExceptionPath hash use net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9a6dcfa54c54c9f50b14248a2449c70c20a0d977 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 08:56:49 2023 -0700 ClockInsertion, ClockLatency net id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit dbb6dc0b8c93812458df31e93f08e0dbd74e8105 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 08:34:03 2023 -0700 ExceptionStateSet obj id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 70b8721c48ec0816289ee09b664c332ee095875f Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 08:14:37 2023 -0700 ClockGroups cmp Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4c6c4ca191a99cd8541e106fec3202ee14968f39 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Jan 12 07:38:17 2023 -0700 ClockGroup typedef to ClockSet Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 66f425315e16deee5f00b05c0a505766e7afbf01 Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 20:32:38 2023 -0700 set cmps Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a94866c7828af5b6714e3e4fffc13bdaf5155c0e Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 19:08:09 2023 -0700 net use id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 6348320908f42ebb5262117182e13d0024f65537 Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 11:52:13 2023 -0700 exception id cmp Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 0edfca41b6d6408ac17f8dfe10e697c55146c1ef Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 10:47:02 2023 -0700 range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 44ad77985da9f0b9e7f4780e3f233c8d94fa7db7 Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 08:27:58 2023 -0700 non-ptr set cmp Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 36de7d88c3fa683465604a9e16b2fc1f6bc5fdd0 Author: James Cherry <cherry@parallaxsw.com> Date: Wed Jan 11 08:00:54 2023 -0700 range iteration Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4a31a2c8d9bdae58b09af8c05a64702ea3ac6c15 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 10 16:43:54 2023 -0700 tcl types Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 056a7447b494a4c8ecc9764650d78a5bed3d87e8 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 10 16:10:36 2023 -0700 tcl types Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 97239554c7625ba50ee729260f08eda7dec02365 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Jan 10 13:10:42 2023 -0700 use RVO Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c3247d8937d483102e3e1f2b69d7ac1d331ba9d4 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 22:41:20 2023 -0700 swig template seq's Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5431c06feb256adb46858819fcf5d513cfa6b5ec Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 20:50:24 2023 -0700 swig set in template Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 592ad641bf01d3beb862314a0d8986f66e258642 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 17:27:25 2023 -0700 network return containers Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c95f8b77e0d6bd5ffa5ba8102413c70883c756e1 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 12:15:37 2023 -0700 PinSeq const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 702e7f9ba2f901066a38f32e67b35602b6c7bbdf Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 12:02:29 2023 -0700 InstanceSeq const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 44fc25ba4a15e4ae570d74af27c9435872a126e0 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 12:01:45 2023 -0700 NetSeq const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 03b2725c81f5d52c33c875b55056c11d482144f1 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 11:33:18 2023 -0700 rm PortPair Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 3fb82a7344dc053171c9883a113764ba691ab827 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Jan 9 11:20:53 2023 -0700 PinSet id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 3dd31f027e15d40d62a11d0a88ef2a115f01fb73 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 8 15:03:33 2023 -0700 InstanceSet id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit a91dea5cc0af3bede36b3faed13adb05239ff907 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 8 11:40:15 2023 -0700 NetSet id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit b91e4b6410134eccae7969ddcfb0b27933b2e746 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 8 10:44:47 2023 -0700 CellSet, PortSet id Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 6f891f77fae5a6b19c1454a1a4b4e3dfae0b5c50 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 8 10:29:25 2023 -0700 network object sets Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eb8c627a57ecc6e7c5846a01d62b090ff91c08bf Author: James Cherry <cherry@parallaxsw.com> Date: Sun Jan 8 10:09:00 2023 -0700 PinSet1 Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8e864ecbdf87000fbb3c3097c39f06173c941e35 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Jan 7 17:13:03 2023 -0700 concrete network object id Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2113 lines
47 KiB
C++
2113 lines
47 KiB
C++
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2022, Parallax Software, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
#include "Network.hh"
|
|
|
|
#include "StringUtil.hh"
|
|
#include "PatternMatch.hh"
|
|
#include "Liberty.hh"
|
|
#include "PortDirection.hh"
|
|
#include "Corner.hh"
|
|
|
|
namespace sta {
|
|
|
|
Network::Network() :
|
|
default_liberty_(nullptr),
|
|
divider_('/'),
|
|
escape_('\\')
|
|
{
|
|
}
|
|
|
|
Network::~Network()
|
|
{
|
|
net_drvr_pin_map_.deleteContents();
|
|
}
|
|
|
|
void
|
|
Network::clear()
|
|
{
|
|
default_liberty_ = nullptr;
|
|
clearNetDrvrPinMap();
|
|
}
|
|
|
|
bool
|
|
Network::isLinked() const
|
|
{
|
|
return topInstance() != nullptr;
|
|
}
|
|
|
|
LibertyLibrary *
|
|
Network::libertyLibrary(const Cell *cell) const
|
|
{
|
|
return libertyCell(cell)->libertyLibrary();
|
|
}
|
|
|
|
LibertyLibrary *
|
|
Network::libertyLibrary(const Instance *instance) const
|
|
{
|
|
return libertyCell(instance)->libertyLibrary();
|
|
}
|
|
|
|
void
|
|
Network::readLibertyAfter(LibertyLibrary *)
|
|
{
|
|
}
|
|
|
|
LibertyCell *
|
|
Network::findLibertyCell(const char *name) const
|
|
{
|
|
LibertyLibraryIterator *iter = libertyLibraryIterator();
|
|
while (iter->hasNext()) {
|
|
LibertyLibrary *lib = iter->next();
|
|
LibertyCell *cell = lib->findLibertyCell(name);
|
|
if (cell) {
|
|
delete iter;
|
|
return cell;
|
|
}
|
|
}
|
|
delete iter;
|
|
return nullptr;
|
|
}
|
|
|
|
LibertyLibrary *
|
|
Network::defaultLibertyLibrary() const
|
|
{
|
|
return default_liberty_;
|
|
}
|
|
|
|
void
|
|
Network::setDefaultLibertyLibrary(LibertyLibrary *library)
|
|
{
|
|
default_liberty_ = library;
|
|
}
|
|
|
|
void
|
|
Network::checkLibertyCorners()
|
|
{
|
|
if (corners_->count() > 1) {
|
|
LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
|
|
LibertyCellSet cells;
|
|
while (lib_iter->hasNext()) {
|
|
LibertyLibrary *lib = lib_iter->next();
|
|
LibertyCellIterator cell_iter(lib);
|
|
while (cell_iter.hasNext()) {
|
|
LibertyCell *cell = cell_iter.next();
|
|
LibertyCell *link_cell = findLibertyCell(cell->name());
|
|
cells.insert(link_cell);
|
|
}
|
|
}
|
|
delete lib_iter;
|
|
|
|
for (LibertyCell *cell : cells)
|
|
LibertyLibrary::checkCorners(cell, corners_, report_);
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::checkNetworkLibertyCorners()
|
|
{
|
|
if (corners_->count() > 1) {
|
|
LibertyCellSet network_cells;
|
|
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
|
|
while (leaf_iter->hasNext()) {
|
|
const Instance *inst = leaf_iter->next();
|
|
LibertyCell *cell = libertyCell(inst);
|
|
if (cell)
|
|
network_cells.insert(cell);
|
|
}
|
|
delete leaf_iter;
|
|
|
|
for (LibertyCell *cell : network_cells)
|
|
LibertyLibrary::checkCorners(cell, corners_, report_);
|
|
}
|
|
}
|
|
|
|
// Only used by Sta::setMinLibrary so linear search is acceptable.
|
|
LibertyLibrary *
|
|
Network::findLibertyFilename(const char *filename)
|
|
{
|
|
LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
|
|
while (lib_iter->hasNext()) {
|
|
LibertyLibrary *lib = lib_iter->next();
|
|
if (stringEq(lib->filename(), filename)) {
|
|
delete lib_iter;
|
|
return lib;
|
|
}
|
|
}
|
|
delete lib_iter;
|
|
return nullptr;
|
|
}
|
|
|
|
LibertyCell *
|
|
Network::libertyCell(const Instance *instance) const
|
|
{
|
|
return libertyCell(cell(instance));
|
|
}
|
|
|
|
LibertyPort *
|
|
Network::libertyPort(const Pin *pin) const
|
|
{
|
|
Port *port = this->port(pin);
|
|
if (port)
|
|
return libertyPort(port);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
bool
|
|
Network::busIndexInRange(const Port *port,
|
|
int index)
|
|
{
|
|
int from_index = fromIndex(port);
|
|
int to_index = toIndex(port);
|
|
return (from_index <= to_index
|
|
&& index <= to_index
|
|
&& index >= from_index)
|
|
|| (from_index > to_index
|
|
&& index >= to_index
|
|
&& index <= from_index);
|
|
}
|
|
|
|
bool
|
|
Network::hasMembers(const Port *port) const
|
|
{
|
|
return isBus(port) || isBundle(port);
|
|
}
|
|
|
|
const char *
|
|
Network::pathName(const Instance *instance) const
|
|
{
|
|
InstanceSeq inst_path;
|
|
path(instance, inst_path);
|
|
size_t name_length = 0;
|
|
InstanceSeq::Iterator path_iter1(inst_path);
|
|
while (path_iter1.hasNext()) {
|
|
const Instance *inst = path_iter1.next();
|
|
name_length += strlen(name(inst)) + 1;
|
|
}
|
|
char *path_name = makeTmpString(name_length);
|
|
char *path_ptr = path_name;
|
|
// Top instance has null string name, so terminate the string here.
|
|
*path_name = '\0';
|
|
while (inst_path.size()) {
|
|
const Instance *inst = inst_path.back();
|
|
const char *inst_name = name(inst);
|
|
strcpy(path_ptr, inst_name);
|
|
path_ptr += strlen(inst_name);
|
|
inst_path.pop_back();
|
|
if (inst_path.size())
|
|
*path_ptr++ = pathDivider();
|
|
*path_ptr = '\0';
|
|
}
|
|
return path_name;
|
|
}
|
|
|
|
bool
|
|
Network::pathNameLess(const Instance *inst1,
|
|
const Instance *inst2) const
|
|
{
|
|
return pathNameCmp(inst1, inst2) < 0;
|
|
}
|
|
|
|
int
|
|
Network::pathNameCmp(const Instance *inst1,
|
|
const Instance *inst2) const
|
|
{
|
|
if (inst1 == nullptr && inst2)
|
|
return -1;
|
|
else if (inst1 && inst2 == nullptr)
|
|
return 1;
|
|
else if (inst1 == inst2)
|
|
return 0;
|
|
else {
|
|
InstanceSeq path1;
|
|
InstanceSeq path2;
|
|
path(inst1, path1);
|
|
path(inst2, path2);
|
|
while (!path1.empty() && !path2.empty()) {
|
|
const Instance *inst1 = path1.back();
|
|
const Instance *inst2 = path2.back();
|
|
int cmp = strcmp(name(inst1), name(inst2));
|
|
if (cmp != 0)
|
|
return cmp;
|
|
path1.pop_back();
|
|
path2.pop_back();
|
|
}
|
|
if (path1.empty() && !path2.empty())
|
|
return -1;
|
|
else if (path1.empty() && path2.empty())
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::path(const Instance *inst,
|
|
// Return value.
|
|
InstanceSeq &path) const
|
|
{
|
|
while (!isTopInstance(inst)) {
|
|
path.push_back(inst);
|
|
inst = parent(inst);
|
|
}
|
|
}
|
|
|
|
bool
|
|
Network::isTopInstance(const Instance *inst) const
|
|
{
|
|
return inst == topInstance();
|
|
}
|
|
|
|
bool
|
|
Network::isInside(const Instance *inst,
|
|
const Instance *hier_inst) const
|
|
{
|
|
while (inst) {
|
|
if (inst == hier_inst)
|
|
return true;
|
|
inst = parent(inst);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Network::isHierarchical(const Instance *instance) const
|
|
{
|
|
return !isLeaf(instance);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
const char *
|
|
Network::name(const Pin *pin) const
|
|
{
|
|
return pathName(pin);
|
|
}
|
|
|
|
const char *
|
|
Network::portName(const Pin *pin) const
|
|
{
|
|
return name(port(pin));
|
|
}
|
|
|
|
const char *
|
|
Network::pathName(const Pin *pin) const
|
|
{
|
|
const Instance *inst = instance(pin);
|
|
if (inst && inst != topInstance()) {
|
|
const char *inst_name = pathName(inst);
|
|
size_t inst_name_length = strlen(inst_name);
|
|
const char *port_name = portName(pin);
|
|
size_t port_name_length = strlen(port_name);
|
|
size_t path_name_length = inst_name_length + port_name_length + 2;
|
|
char *path_name = makeTmpString(path_name_length);
|
|
char *path_ptr = path_name;
|
|
strcpy(path_ptr, inst_name);
|
|
path_ptr += inst_name_length;
|
|
*path_ptr++ = pathDivider();
|
|
strcpy(path_ptr, port_name);
|
|
return path_name;
|
|
}
|
|
else
|
|
return portName(pin);
|
|
}
|
|
|
|
bool
|
|
Network::pathNameLess(const Pin *pin1,
|
|
const Pin *pin2) const
|
|
{
|
|
return pathNameCmp(pin1, pin2) < 0;
|
|
}
|
|
|
|
int
|
|
Network::pathNameCmp(const Pin *pin1,
|
|
const Pin *pin2) const
|
|
{
|
|
int inst_cmp = pathNameCmp(instance(pin1), instance(pin2));
|
|
if (inst_cmp == 0)
|
|
return strcmp(portName(pin1), portName(pin2));
|
|
else
|
|
return inst_cmp;
|
|
}
|
|
|
|
bool
|
|
Network::isInside(const Net *net,
|
|
const Instance *hier_inst) const
|
|
{
|
|
return isInside(instance(net), hier_inst);
|
|
}
|
|
|
|
bool
|
|
Network::isLeaf(const Pin *pin) const
|
|
{
|
|
return isLeaf(instance(pin));
|
|
}
|
|
|
|
bool
|
|
Network::isHierarchical(const Pin *pin) const
|
|
{
|
|
return (!isLeaf(pin) && !isTopLevelPort(pin));
|
|
}
|
|
|
|
bool
|
|
Network::isTopLevelPort(const Pin *pin) const
|
|
{
|
|
return (parent(instance(pin)) == nullptr);
|
|
}
|
|
|
|
bool
|
|
Network::isInside(const Pin *pin,
|
|
const Pin *hier_pin) const
|
|
{
|
|
return isInside(pin, instance(hier_pin));
|
|
}
|
|
|
|
bool
|
|
Network::isInside(const Pin *pin,
|
|
const Instance *hier_inst) const
|
|
{
|
|
return isInside(instance(pin), hier_inst);
|
|
}
|
|
|
|
bool
|
|
Network::pinLess(const Pin *pin1,
|
|
const Pin *pin2) const
|
|
{
|
|
return pathNameLess(pin1, pin2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
const char *
|
|
Network::pathName(const Net *net) const
|
|
{
|
|
const Instance *inst = instance(net);
|
|
if (inst && inst != topInstance()) {
|
|
const char *inst_name = pathName(inst);
|
|
size_t inst_name_length = strlen(inst_name);
|
|
const char *net_name = name(net);
|
|
size_t net_name_length = strlen(net_name);
|
|
size_t path_name_length = inst_name_length + net_name_length + 2;
|
|
char *path_name = makeTmpString(path_name_length);
|
|
char *path_ptr = path_name;
|
|
strcpy(path_ptr, inst_name);
|
|
path_ptr += inst_name_length;
|
|
*path_ptr++ = pathDivider();
|
|
strcpy(path_ptr, net_name);
|
|
return path_name;
|
|
}
|
|
else
|
|
return name(net);
|
|
}
|
|
|
|
bool
|
|
Network::pathNameLess(const Net *net1,
|
|
const Net *net2) const
|
|
{
|
|
return pathNameCmp(net1, net2) < 0;
|
|
}
|
|
|
|
int
|
|
Network::pathNameCmp(const Net *net1,
|
|
const Net *net2) const
|
|
{
|
|
int inst_cmp = pathNameCmp(instance(net1), instance(net2));
|
|
if (inst_cmp == 0)
|
|
return strcmp(name(net1), name(net2));
|
|
else
|
|
return inst_cmp;
|
|
}
|
|
|
|
Net *
|
|
Network::highestNetAbove(Net *net) const
|
|
{
|
|
Net *highest_net = net;
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = pin(term);
|
|
if (above_pin) {
|
|
Net *above_net = this->net(above_pin);
|
|
if (above_net) {
|
|
highest_net = highestNetAbove(above_net);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
delete term_iter;
|
|
return highest_net;
|
|
}
|
|
|
|
const Net *
|
|
Network::highestConnectedNet(Net *net) const
|
|
{
|
|
NetSet nets(this);
|
|
connectedNets(net, &nets);
|
|
const Net *highest_net = net;
|
|
int highest_level = hierarchyLevel(net);
|
|
NetSet::Iterator net_iter(nets);
|
|
while (net_iter.hasNext()) {
|
|
const Net *net1 = net_iter.next();
|
|
int level = hierarchyLevel(net1);
|
|
if (level < highest_level
|
|
|| (level == highest_level
|
|
&& stringLess(pathName(net1), pathName(highest_net)))) {
|
|
highest_net = net1;
|
|
highest_level = level;
|
|
}
|
|
}
|
|
return highest_net;
|
|
}
|
|
|
|
void
|
|
Network::connectedNets(Net *net,
|
|
NetSet *nets) const
|
|
{
|
|
if (!nets->hasKey(net)) {
|
|
nets->insert(net);
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = pin(term);
|
|
if (above_pin) {
|
|
Net *above_net = this->net(above_pin);
|
|
if (above_net)
|
|
connectedNets(above_net, nets);
|
|
}
|
|
}
|
|
delete term_iter;
|
|
|
|
// Search down from net pins.
|
|
NetPinIterator *pin_iter = pinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin1 = pin_iter->next();
|
|
Term *below_term = term(pin1);
|
|
if (below_term) {
|
|
Net *below_net = this->net(below_term);
|
|
if (below_net)
|
|
connectedNets(below_net, nets);
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::connectedNets(const Pin *pin,
|
|
NetSet *nets) const
|
|
{
|
|
Net *net = this->net(pin);
|
|
if (net)
|
|
connectedNets(net, nets);
|
|
else {
|
|
Term *term = this->term(pin);
|
|
if (term) {
|
|
Net *below_net = this->net(term);
|
|
if (below_net)
|
|
connectedNets(below_net, nets);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
Network::hierarchyLevel(const Net *net) const
|
|
{
|
|
NetTermIterator *term_iter = network_->termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *pin = network_->pin(term);
|
|
if (pin) {
|
|
Net *above_net = network_->net(pin);
|
|
if (above_net) {
|
|
delete term_iter;
|
|
return hierarchyLevel(above_net) + 1;
|
|
}
|
|
}
|
|
}
|
|
delete term_iter;
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
Network::isDriver(const Pin *pin) const
|
|
{
|
|
PortDirection *dir = direction(pin);
|
|
const Instance *inst = instance(pin);
|
|
return (isLeaf(inst) && dir->isAnyOutput())
|
|
// isTopLevelPort(pin)
|
|
|| (isTopInstance(inst) && dir->isAnyInput());
|
|
}
|
|
|
|
bool
|
|
Network::isLoad(const Pin *pin) const
|
|
{
|
|
PortDirection *dir = direction(pin);
|
|
const Instance *inst = instance(pin);
|
|
return (isLeaf(inst) && dir->isAnyInput())
|
|
// isTopLevelPort(pin)
|
|
|| (isTopInstance(inst) && dir->isAnyOutput())
|
|
// Black box unknown ports are treated as loads.
|
|
|| dir->isUnknown();
|
|
}
|
|
|
|
bool
|
|
Network::isRegClkPin(const Pin *pin) const
|
|
{
|
|
const LibertyPort *port = libertyPort(pin);
|
|
return port && port->isRegClk();
|
|
}
|
|
|
|
bool
|
|
Network::isCheckClk(const Pin *pin) const
|
|
{
|
|
const LibertyPort *port = libertyPort(pin);
|
|
return port && port->isCheckClk();
|
|
}
|
|
|
|
bool
|
|
Network::isLatchData(const Pin *pin) const
|
|
{
|
|
LibertyPort *port = libertyPort(pin);
|
|
if (port)
|
|
return port->libertyCell()->isLatchData(port);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
const char *
|
|
Network::name(const Term *term) const
|
|
{
|
|
return name(pin(term));
|
|
}
|
|
|
|
const char *
|
|
Network::pathName(const Term *term) const
|
|
{
|
|
return pathName(pin(term));
|
|
}
|
|
|
|
const char *
|
|
Network::portName(const Term *term) const
|
|
{
|
|
return portName(pin(term));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
const char *
|
|
Network::cellName(const Instance *inst) const
|
|
{
|
|
return name(cell(inst));
|
|
}
|
|
|
|
Instance *
|
|
Network::findInstance(const char *path_name) const
|
|
{
|
|
return findInstanceRelative(topInstance(), path_name);
|
|
}
|
|
|
|
Instance *
|
|
Network::findInstanceRelative(const Instance *inst,
|
|
const char *path_name) const
|
|
{
|
|
char *first, *tail;
|
|
pathNameFirst(path_name, first, tail);
|
|
if (first) {
|
|
Instance *inst1 = findChild(inst, first);
|
|
stringDelete(first);
|
|
while (inst1 && tail) {
|
|
char *next_tail;
|
|
pathNameFirst(tail, first, next_tail);
|
|
if (first) {
|
|
inst1 = findChild(inst1, first);
|
|
stringDelete(first);
|
|
}
|
|
else
|
|
inst1 = findChild(inst1, tail);
|
|
stringDelete(tail);
|
|
tail = next_tail;
|
|
}
|
|
stringDelete(tail);
|
|
return inst1;
|
|
}
|
|
else
|
|
return findChild(inst, path_name);
|
|
}
|
|
|
|
InstanceSeq
|
|
Network::findInstancesMatching(const Instance *context,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
InstanceSeq matches;
|
|
if (pattern->hasWildcards()) {
|
|
size_t context_name_length = 0;
|
|
if (context != topInstance())
|
|
// Add one for the trailing divider.
|
|
context_name_length = strlen(pathName(context)) + 1;
|
|
findInstancesMatching1(context, context_name_length, pattern, matches);
|
|
}
|
|
else {
|
|
Instance *inst = findInstanceRelative(context, pattern->pattern());
|
|
if (inst)
|
|
matches.push_back(inst);
|
|
}
|
|
return matches;
|
|
}
|
|
|
|
void
|
|
Network::findInstancesMatching1(const Instance *context,
|
|
size_t context_name_length,
|
|
const PatternMatch *pattern,
|
|
InstanceSeq &matches) const
|
|
{
|
|
InstanceChildIterator *child_iter = childIterator(context);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
const char *child_name = pathName(child);
|
|
// Remove context prefix from the name.
|
|
const char *child_context_name = &child_name[context_name_length];
|
|
if (pattern->match(child_context_name))
|
|
matches.push_back(child);
|
|
if (!isLeaf(child))
|
|
findInstancesMatching1(child, context_name_length, pattern, matches);
|
|
}
|
|
delete child_iter;
|
|
}
|
|
|
|
InstanceSeq
|
|
Network::findInstancesHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
InstanceSeq matches;
|
|
findInstancesHierMatching1(instance, pattern, matches);
|
|
return matches;
|
|
}
|
|
|
|
void
|
|
Network::findInstancesHierMatching1(const Instance *instance,
|
|
const PatternMatch *pattern,
|
|
InstanceSeq &matches) const
|
|
{
|
|
InstanceChildIterator *child_iter = childIterator(instance);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
if (pattern->match(name(child)))
|
|
matches.push_back(child);
|
|
if (!isLeaf(child))
|
|
findInstancesHierMatching1(child, pattern, matches);
|
|
}
|
|
delete child_iter;
|
|
}
|
|
|
|
void
|
|
Network::findChildrenMatching(const Instance *parent,
|
|
const PatternMatch *pattern,
|
|
InstanceSeq &matches) const
|
|
{
|
|
if (pattern->hasWildcards()) {
|
|
InstanceChildIterator *child_iter = childIterator(parent);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
if (pattern->match(name(child)))
|
|
matches.push_back(child);
|
|
}
|
|
delete child_iter;
|
|
}
|
|
else {
|
|
Instance *child = findChild(parent, pattern->pattern());
|
|
if (child)
|
|
matches.push_back(child);
|
|
}
|
|
}
|
|
|
|
Pin *
|
|
Network::findPin(const char *path_name) const
|
|
{
|
|
return findPinRelative(topInstance(), path_name);
|
|
}
|
|
|
|
Pin *
|
|
Network::findPinRelative(const Instance *inst,
|
|
const char *path_name) const
|
|
{
|
|
char *inst_path, *port_name;
|
|
pathNameLast(path_name, inst_path, port_name);
|
|
if (inst_path) {
|
|
Instance *pin_inst = findInstanceRelative(inst, inst_path);
|
|
if (pin_inst) {
|
|
Pin *pin = findPin(pin_inst, port_name);
|
|
stringDelete(inst_path);
|
|
stringDelete(port_name);
|
|
return pin;
|
|
}
|
|
stringDelete(inst_path);
|
|
stringDelete(port_name);
|
|
return nullptr;
|
|
}
|
|
else
|
|
// Top level pin.
|
|
return findPin(inst, path_name);
|
|
}
|
|
|
|
Pin *
|
|
Network::findPinLinear(const Instance *instance,
|
|
const char *port_name) const
|
|
{
|
|
InstancePinIterator *pin_iter = pinIterator(instance);
|
|
while (pin_iter->hasNext()) {
|
|
Pin *pin = pin_iter->next();
|
|
if (stringEq(port_name, portName(pin))) {
|
|
delete pin_iter;
|
|
return pin;
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
return nullptr;
|
|
}
|
|
|
|
Pin *
|
|
Network::findPin(const Instance *instance,
|
|
const Port *port) const
|
|
{
|
|
return findPin(instance, name(port));
|
|
}
|
|
|
|
Pin *
|
|
Network::findPin(const Instance *instance,
|
|
const LibertyPort *port) const
|
|
{
|
|
return findPin(instance, port->name());
|
|
}
|
|
|
|
Net *
|
|
Network::findNet(const char *path_name) const
|
|
{
|
|
return findNetRelative(topInstance(), path_name);
|
|
}
|
|
|
|
Net *
|
|
Network::findNetRelative(const Instance *inst,
|
|
const char *path_name) const
|
|
{
|
|
char *inst_path, *net_name;
|
|
pathNameLast(path_name, inst_path, net_name);
|
|
if (inst_path) {
|
|
Instance *net_inst = findInstanceRelative(inst, inst_path);
|
|
if (net_inst) {
|
|
Net *net = findNet(net_inst, net_name);
|
|
stringDelete(inst_path);
|
|
stringDelete(net_name);
|
|
return net;
|
|
}
|
|
stringDelete(inst_path);
|
|
stringDelete(net_name);
|
|
return nullptr;
|
|
}
|
|
else
|
|
// Top level net.
|
|
return findNet(inst, path_name);
|
|
}
|
|
|
|
Net *
|
|
Network::findNetLinear(const Instance *instance,
|
|
const char *net_name) const
|
|
{
|
|
InstanceNetIterator *net_iter = netIterator(instance);
|
|
while (net_iter->hasNext()) {
|
|
Net *net = net_iter->next();
|
|
if (stringEq(name(net), net_name)) {
|
|
delete net_iter;
|
|
return net;
|
|
}
|
|
}
|
|
delete net_iter;
|
|
return nullptr;
|
|
}
|
|
|
|
NetSeq
|
|
Network::findNetsMatching(const Instance *context,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
NetSeq matches;
|
|
findNetsMatching(context, pattern, matches);
|
|
return matches;
|
|
}
|
|
|
|
void
|
|
Network::findNetsMatching(const Instance *context,
|
|
const PatternMatch *pattern,
|
|
NetSeq &matches) const
|
|
{
|
|
if (pattern->hasWildcards()) {
|
|
char *inst_path, *net_name;
|
|
pathNameLast(pattern->pattern(), inst_path, net_name);
|
|
if (inst_path) {
|
|
PatternMatch inst_pattern(inst_path, pattern);
|
|
PatternMatch net_pattern(net_name, pattern);
|
|
InstanceSeq insts = findInstancesMatching(context, &inst_pattern);
|
|
InstanceSeq::Iterator inst_iter(insts);
|
|
while (inst_iter.hasNext()) {
|
|
const Instance *inst = inst_iter.next();
|
|
findNetsMatching(inst, &net_pattern, matches);
|
|
}
|
|
stringDelete(inst_path);
|
|
stringDelete(net_name);
|
|
}
|
|
else
|
|
// Top level net.
|
|
findInstNetsMatching(context, pattern, matches);
|
|
}
|
|
else {
|
|
Net *net = findNet(pattern->pattern());
|
|
if (net)
|
|
matches.push_back(net);
|
|
}
|
|
}
|
|
|
|
NetSeq
|
|
Network::findNetsHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
NetSeq matches;
|
|
findNetsHierMatching(instance, pattern, matches);
|
|
return matches;
|
|
}
|
|
|
|
void
|
|
Network::findNetsHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern,
|
|
NetSeq &matches) const
|
|
{
|
|
findInstNetsMatching(instance, pattern, matches);
|
|
InstanceChildIterator *child_iter = childIterator(instance);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
findNetsHierMatching(child, pattern, matches);
|
|
}
|
|
delete child_iter;
|
|
}
|
|
|
|
NetSeq
|
|
Network::findNetsMatchingLinear(const Instance *instance,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
NetSeq matches;
|
|
InstanceNetIterator *net_iter = netIterator(instance);
|
|
while (net_iter->hasNext()) {
|
|
Net *net = net_iter->next();
|
|
if (pattern->match(name(net)))
|
|
matches.push_back(net);
|
|
}
|
|
delete net_iter;
|
|
return matches;
|
|
}
|
|
|
|
PinSeq
|
|
Network::findPinsMatching(const Instance *instance,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
PinSeq matches;
|
|
if (pattern->hasWildcards()) {
|
|
char *inst_path, *port_name;
|
|
pathNameLast(pattern->pattern(), inst_path, port_name);
|
|
if (inst_path) {
|
|
PatternMatch inst_pattern(inst_path, pattern);
|
|
PatternMatch port_pattern(port_name, pattern);
|
|
InstanceSeq insts = findInstancesMatching(instance, &inst_pattern);
|
|
InstanceSeq::Iterator inst_iter(insts);
|
|
while (inst_iter.hasNext()) {
|
|
const Instance *inst = inst_iter.next();
|
|
findInstPinsMatching(inst, &port_pattern, matches);
|
|
}
|
|
stringDelete(inst_path);
|
|
stringDelete(port_name);
|
|
}
|
|
else
|
|
// Top level pin.
|
|
findInstPinsMatching(instance, pattern, matches);
|
|
}
|
|
else {
|
|
Pin *pin = findPin(pattern->pattern());
|
|
if (pin)
|
|
matches.push_back(pin);
|
|
}
|
|
return matches;
|
|
}
|
|
|
|
PinSeq
|
|
Network::findPinsHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern) const
|
|
{
|
|
PinSeq matches;
|
|
findPinsHierMatching(instance, pattern, matches);
|
|
return matches;
|
|
}
|
|
|
|
void
|
|
Network::findPinsHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern,
|
|
// Return value.
|
|
PinSeq &matches) const
|
|
{
|
|
InstanceChildIterator *child_iter = childIterator(instance);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
findInstPinsHierMatching(child, pattern, matches);
|
|
findPinsHierMatching(child, pattern, matches);
|
|
}
|
|
delete child_iter;
|
|
}
|
|
|
|
void
|
|
Network::findInstPinsHierMatching(const Instance *instance,
|
|
const PatternMatch *pattern,
|
|
// Return value.
|
|
PinSeq &matches) const
|
|
{
|
|
const char *inst_name = name(instance);
|
|
InstancePinIterator *pin_iter = pinIterator(instance);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
const char *port_name = name(port(pin));
|
|
string pin_name;
|
|
stringPrint(pin_name, "%s%c%s", inst_name,divider_, port_name);
|
|
if (pattern->match(pin_name.c_str()))
|
|
matches.push_back(pin);
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
|
|
void
|
|
Network::findInstPinsMatching(const Instance *instance,
|
|
const PatternMatch *pattern,
|
|
PinSeq &matches) const
|
|
{
|
|
if (pattern->hasWildcards()) {
|
|
InstancePinIterator *pin_iter = pinIterator(instance);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
if (pattern->match(name(pin)))
|
|
matches.push_back(pin);
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
else {
|
|
Pin *pin = findPin(instance, pattern->pattern());
|
|
if (pin)
|
|
matches.push_back(pin);
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::location(const Pin *,
|
|
// Return values.
|
|
double &x,
|
|
double &y,
|
|
bool &exists) const
|
|
{
|
|
x = y = 0.0;
|
|
exists = false;
|
|
}
|
|
|
|
int
|
|
Network::instanceCount(Instance *inst)
|
|
{
|
|
int count = 1;
|
|
InstanceChildIterator *child_iter = childIterator(inst);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
count += instanceCount(child);
|
|
}
|
|
delete child_iter;
|
|
return count;
|
|
}
|
|
|
|
int
|
|
Network::instanceCount()
|
|
{
|
|
return instanceCount(topInstance());
|
|
}
|
|
|
|
int
|
|
Network::pinCount(Instance *inst)
|
|
{
|
|
int count = 0;
|
|
InstancePinIterator *pin_iter = pinIterator(inst);
|
|
while (pin_iter->hasNext()) {
|
|
pin_iter->next();
|
|
count++;
|
|
}
|
|
delete pin_iter;
|
|
|
|
InstanceChildIterator *child_iter = childIterator(inst);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
count += pinCount(child);
|
|
}
|
|
delete child_iter;
|
|
return count;
|
|
}
|
|
|
|
int
|
|
Network::pinCount()
|
|
{
|
|
return pinCount(topInstance());
|
|
}
|
|
|
|
int
|
|
Network::netCount(Instance *inst)
|
|
{
|
|
int count = 0;
|
|
InstanceNetIterator *net_iter = netIterator(inst);
|
|
while (net_iter->hasNext()) {
|
|
net_iter->next();
|
|
count++;
|
|
}
|
|
delete net_iter;
|
|
|
|
InstanceChildIterator *child_iter = childIterator(inst);
|
|
while (child_iter->hasNext()) {
|
|
Instance *child = child_iter->next();
|
|
count += netCount(child);
|
|
}
|
|
delete child_iter;
|
|
return count;
|
|
}
|
|
|
|
int
|
|
Network::netCount()
|
|
{
|
|
return netCount(topInstance());
|
|
}
|
|
|
|
int
|
|
Network::leafInstanceCount()
|
|
{
|
|
int count = 0;
|
|
LeafInstanceIterator *leaf_iter = leafInstanceIterator();
|
|
while (leaf_iter->hasNext()) {
|
|
leaf_iter->next();
|
|
count++;
|
|
}
|
|
delete leaf_iter;
|
|
return count;
|
|
}
|
|
|
|
int
|
|
Network::leafPinCount()
|
|
{
|
|
int count = 0;
|
|
LeafInstanceIterator *leaf_iter = leafInstanceIterator();
|
|
while (leaf_iter->hasNext()) {
|
|
Instance *leaf = leaf_iter->next();
|
|
InstancePinIterator *pin_iter = pinIterator(leaf);
|
|
while (pin_iter->hasNext()) {
|
|
pin_iter->next();
|
|
count++;
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
delete leaf_iter;
|
|
return count;
|
|
}
|
|
|
|
void
|
|
Network::setPathDivider(char divider)
|
|
{
|
|
divider_ = divider;
|
|
}
|
|
|
|
void
|
|
Network::setPathEscape(char escape)
|
|
{
|
|
escape_ = escape;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
typedef Vector<InstanceChildIterator *> InstanceChildIteratorSeq;
|
|
|
|
class LeafInstanceIterator1 : public LeafInstanceIterator
|
|
{
|
|
public:
|
|
LeafInstanceIterator1(const Instance *inst,
|
|
const Network *network);
|
|
bool hasNext() { return next_; }
|
|
Instance *next();
|
|
|
|
private:
|
|
void nextInst();
|
|
|
|
const Network *network_;
|
|
InstanceChildIteratorSeq pending_child_iters_;
|
|
InstanceChildIterator *child_iter_;
|
|
Instance *next_;
|
|
|
|
};
|
|
|
|
LeafInstanceIterator1::LeafInstanceIterator1(const Instance *inst,
|
|
const Network *network) :
|
|
network_(network),
|
|
child_iter_(network->childIterator(inst)),
|
|
next_(nullptr)
|
|
{
|
|
pending_child_iters_.reserve(8);
|
|
nextInst();
|
|
}
|
|
|
|
Instance *
|
|
LeafInstanceIterator1::next()
|
|
{
|
|
Instance *next = next_;
|
|
nextInst();
|
|
return next;
|
|
}
|
|
|
|
void
|
|
LeafInstanceIterator1::nextInst()
|
|
{
|
|
next_ = nullptr;
|
|
while (child_iter_) {
|
|
while (child_iter_->hasNext()) {
|
|
next_ = child_iter_->next();
|
|
if (network_->isLeaf(next_))
|
|
return;
|
|
else {
|
|
pending_child_iters_.push_back(child_iter_);
|
|
child_iter_ = network_->childIterator(next_);
|
|
next_ = nullptr;
|
|
}
|
|
}
|
|
delete child_iter_;
|
|
|
|
if (pending_child_iters_.empty())
|
|
child_iter_ = nullptr;
|
|
else {
|
|
child_iter_ = pending_child_iters_.back();
|
|
pending_child_iters_.pop_back();
|
|
}
|
|
}
|
|
}
|
|
|
|
LeafInstanceIterator *
|
|
Network::leafInstanceIterator() const
|
|
{
|
|
return new LeafInstanceIterator1(topInstance(), this);
|
|
}
|
|
|
|
LeafInstanceIterator *
|
|
Network::leafInstanceIterator(const Instance *hier_inst) const
|
|
{
|
|
return new LeafInstanceIterator1(hier_inst, this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
Network::visitConnectedPins(const Pin *pin,
|
|
PinVisitor &visitor) const
|
|
{
|
|
NetSet visited_nets(network_);
|
|
Net *pin_net = net(pin);
|
|
Term *pin_term = term(pin);
|
|
if (pin_net)
|
|
visitConnectedPins(pin_net, visitor, visited_nets);
|
|
else if (pin_term == nullptr)
|
|
// Unconnected or internal pin.
|
|
visitor(pin);
|
|
|
|
// Search down from pin terminal.
|
|
if (pin_term) {
|
|
Net *term_net = net(pin_term);
|
|
if (term_net)
|
|
visitConnectedPins(term_net, visitor, visited_nets);
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::visitConnectedPins(const Net *net,
|
|
PinVisitor &visitor) const
|
|
{
|
|
NetSet visited_nets(this);
|
|
visitConnectedPins(net, visitor, visited_nets);
|
|
}
|
|
|
|
void
|
|
Network::visitConnectedPins(const Net *net,
|
|
PinVisitor &visitor,
|
|
NetSet &visited_nets) const
|
|
{
|
|
if (!visited_nets.hasKey(net)) {
|
|
visited_nets.insert(net);
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = pin(term);
|
|
if (above_pin) {
|
|
Net *above_net = this->net(above_pin);
|
|
if (above_net)
|
|
visitConnectedPins(above_net, visitor, visited_nets);
|
|
else
|
|
visitor(above_pin);
|
|
}
|
|
}
|
|
delete term_iter;
|
|
|
|
// Search down from net pins.
|
|
NetPinIterator *pin_iter = pinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
visitor(pin);
|
|
Term *below_term = term(pin);
|
|
if (below_term) {
|
|
Net *below_net = this->net(below_term);
|
|
if (below_net)
|
|
visitConnectedPins(below_net, visitor, visited_nets);
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
class ConnectedPinIterator1 : public ConnectedPinIterator
|
|
{
|
|
public:
|
|
explicit ConnectedPinIterator1(PinSet *pins);
|
|
virtual ~ConnectedPinIterator1();
|
|
virtual bool hasNext();
|
|
virtual const Pin *next();
|
|
|
|
protected:
|
|
PinSet::Iterator pin_iter_;
|
|
};
|
|
|
|
ConnectedPinIterator1::ConnectedPinIterator1(PinSet *pins) :
|
|
pin_iter_(pins)
|
|
{
|
|
}
|
|
|
|
ConnectedPinIterator1::~ConnectedPinIterator1()
|
|
{
|
|
delete pin_iter_.container();
|
|
}
|
|
|
|
bool
|
|
ConnectedPinIterator1::hasNext()
|
|
{
|
|
return pin_iter_.hasNext();
|
|
}
|
|
|
|
const Pin *
|
|
ConnectedPinIterator1::next()
|
|
{
|
|
return pin_iter_.next();
|
|
}
|
|
|
|
class FindConnectedPins : public PinVisitor
|
|
{
|
|
public:
|
|
explicit FindConnectedPins(PinSet *pins);
|
|
virtual void operator()(const Pin *pin);
|
|
|
|
protected:
|
|
PinSet *pins_;
|
|
};
|
|
|
|
FindConnectedPins::FindConnectedPins(PinSet *pins) :
|
|
PinVisitor(),
|
|
pins_(pins)
|
|
{
|
|
}
|
|
|
|
void
|
|
FindConnectedPins::operator()(const Pin *pin)
|
|
{
|
|
pins_->insert(pin);
|
|
}
|
|
|
|
NetConnectedPinIterator *
|
|
Network::connectedPinIterator(const Net *net) const
|
|
{
|
|
PinSet *pins = new PinSet(this);
|
|
FindConnectedPins visitor(pins);
|
|
visitConnectedPins(net, visitor);
|
|
return new ConnectedPinIterator1(pins);
|
|
}
|
|
|
|
PinConnectedPinIterator *
|
|
Network::connectedPinIterator(const Pin *pin) const
|
|
{
|
|
PinSet *pins = new PinSet(this);
|
|
pins->insert(const_cast<Pin*>(pin));
|
|
|
|
FindConnectedPins visitor(pins);
|
|
Net *pin_net = net(pin);
|
|
if (pin_net)
|
|
visitConnectedPins(pin_net, visitor);
|
|
|
|
// Search down from pin terminal.
|
|
Term *pin_term = term(pin);
|
|
if (pin_term) {
|
|
Net *term_net = net(pin_term);
|
|
if (term_net)
|
|
visitConnectedPins(term_net, visitor);
|
|
}
|
|
return new ConnectedPinIterator1(pins);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
bool
|
|
Network::isConnected(const Net *net,
|
|
const Pin *pin) const
|
|
{
|
|
if (this->net(pin) == net)
|
|
return true;
|
|
else {
|
|
NetSet nets(this);
|
|
return isConnected(net, pin, nets);
|
|
}
|
|
}
|
|
|
|
bool
|
|
Network::isConnected(const Net *net,
|
|
const Pin *pin,
|
|
NetSet &nets) const
|
|
{
|
|
if (!nets.hasKey(net)) {
|
|
nets.insert(net);
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = this->pin(term);
|
|
if (above_pin) {
|
|
if (above_pin == pin) {
|
|
delete term_iter;
|
|
return true;
|
|
}
|
|
else {
|
|
Net *above_net = this->net(above_pin);
|
|
if (above_net && isConnected(above_net, pin, nets)) {
|
|
delete term_iter;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete term_iter;
|
|
|
|
// Search down from net pins.
|
|
NetPinIterator *pin_iter = pinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin1 = pin_iter->next();
|
|
if (pin1 == pin) {
|
|
delete pin_iter;
|
|
return true;
|
|
}
|
|
else {
|
|
Term *below_term = term(pin1);
|
|
if (below_term) {
|
|
Net *below_net = this->net(below_term);
|
|
if (below_net && isConnected(below_net, pin, nets)) {
|
|
delete pin_iter;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Network::isConnected(const Net *net1,
|
|
const Net *net2) const
|
|
{
|
|
NetSet nets(this);
|
|
return isConnected(net1, net2, nets);
|
|
}
|
|
|
|
bool
|
|
Network::isConnected(const Net *net1,
|
|
const Net *net2,
|
|
NetSet &nets) const
|
|
{
|
|
if (net1 == net2)
|
|
return true;
|
|
else if (!nets.hasKey(net1)) {
|
|
nets.insert(net1);
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = termIterator(net1);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = pin(term);
|
|
if (above_pin) {
|
|
Net *above_net = net(above_pin);
|
|
if (above_net && isConnected(above_net, net2, nets)) {
|
|
delete term_iter;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
delete term_iter;
|
|
|
|
// Search down from net pins.
|
|
NetPinIterator *pin_iter = pinIterator(net1);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin1 = pin_iter->next();
|
|
Term *below_term = term(pin1);
|
|
if (below_term) {
|
|
Net *below_net = net(below_term);
|
|
if (below_net && isConnected(below_net, net2, nets)) {
|
|
delete pin_iter;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
class FindDrvrPins : public PinVisitor
|
|
{
|
|
public:
|
|
explicit FindDrvrPins(PinSet *pins,
|
|
const Network *network);
|
|
virtual void operator()(const Pin *pin);
|
|
|
|
protected:
|
|
PinSet *pins_;
|
|
const Network *network_;
|
|
};
|
|
|
|
FindDrvrPins::FindDrvrPins(PinSet *pins,
|
|
const Network *network) :
|
|
PinVisitor(),
|
|
pins_(pins),
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
void
|
|
FindDrvrPins::operator()(const Pin *pin)
|
|
{
|
|
if (network_->isDriver(pin))
|
|
pins_->insert(pin);
|
|
}
|
|
|
|
PinSet *
|
|
Network::drivers(const Pin *pin)
|
|
{
|
|
const Net *net = this->net(pin);
|
|
if (net)
|
|
return drivers(net);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
Network::clearNetDrvrPinMap()
|
|
{
|
|
net_drvr_pin_map_.deleteContentsClear();
|
|
}
|
|
|
|
PinSet *
|
|
Network::drivers(const Net *net)
|
|
{
|
|
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
|
|
if (drvrs == nullptr) {
|
|
drvrs = new PinSet(this);
|
|
FindDrvrPins visitor(drvrs, this);
|
|
visitConnectedPins(net, visitor);
|
|
net_drvr_pin_map_[net] = drvrs;
|
|
}
|
|
return drvrs;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
Network::pathNameFirst(const char *path_name,
|
|
char *&first,
|
|
char *&tail) const
|
|
{
|
|
char escape = pathEscape();
|
|
char divider = pathDivider();
|
|
const char *d = strchr(path_name, divider);
|
|
// Skip escaped dividers.
|
|
while (d != nullptr
|
|
&& d > path_name
|
|
&& d[-1] == escape)
|
|
d = strchr(d + 1, divider);
|
|
if (d) {
|
|
first = new char[d - path_name + 1];
|
|
strncpy(first, path_name, d - path_name);
|
|
first[d - path_name] = '\0';
|
|
|
|
tail = new char[strlen(d)];
|
|
// Chop off the leading divider.
|
|
strcpy(tail, d + 1);
|
|
}
|
|
else {
|
|
// No divider in path_name.
|
|
first = nullptr;
|
|
tail = nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
Network::pathNameLast(const char *path_name,
|
|
char *&head,
|
|
char *&last) const
|
|
{
|
|
char escape = pathEscape();
|
|
char divider = pathDivider();
|
|
const char *d = strrchr(path_name, divider);
|
|
// Search for a non-escaped divider.
|
|
if (d) {
|
|
while (d > path_name
|
|
&& (d[0] != divider
|
|
|| (d[0] == divider
|
|
&& d > &path_name[1]
|
|
&& d[-1] == escape)))
|
|
d--;
|
|
}
|
|
if (d && d != path_name) {
|
|
head = new char[d - path_name + 1];
|
|
strncpy(head, path_name, d - path_name);
|
|
head[d - path_name] = '\0';
|
|
|
|
last = new char[strlen(d)];
|
|
// Chop off the last divider.
|
|
strcpy(last, d + 1);
|
|
}
|
|
else {
|
|
// No divider in path_name.
|
|
head = nullptr;
|
|
last = nullptr;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
NetworkEdit::NetworkEdit() :
|
|
Network()
|
|
{
|
|
}
|
|
|
|
void
|
|
NetworkEdit::connectPin(Pin *pin,
|
|
Net *net)
|
|
{
|
|
connect(instance(pin), port(pin), net);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
NetworkConstantPinIterator::
|
|
NetworkConstantPinIterator(const Network *network,
|
|
NetSet &zero_nets,
|
|
NetSet &one_nets) :
|
|
ConstantPinIterator(),
|
|
network_(network),
|
|
constant_pins_{PinSet(network), PinSet(network)}
|
|
{
|
|
findConstantPins(zero_nets, constant_pins_[0]);
|
|
findConstantPins(one_nets, constant_pins_[1]);
|
|
value_ = LogicValue::zero;
|
|
pin_iter_ = new PinSet::Iterator(constant_pins_[0]);
|
|
}
|
|
|
|
NetworkConstantPinIterator::~NetworkConstantPinIterator()
|
|
{
|
|
delete pin_iter_;
|
|
}
|
|
|
|
void
|
|
NetworkConstantPinIterator::findConstantPins(NetSet &nets,
|
|
PinSet &pins)
|
|
{
|
|
NetSet::Iterator net_iter(nets);
|
|
while (net_iter.hasNext()) {
|
|
const Net *net = net_iter.next();
|
|
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
pins.insert(pin);
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
}
|
|
|
|
bool
|
|
NetworkConstantPinIterator::hasNext()
|
|
{
|
|
if (pin_iter_->hasNext())
|
|
return true;
|
|
else if (value_ == LogicValue::zero) {
|
|
delete pin_iter_;
|
|
value_ = LogicValue::one;
|
|
pin_iter_ = new PinSet::Iterator(constant_pins_[1]);
|
|
return pin_iter_->hasNext();
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void
|
|
NetworkConstantPinIterator::next(const Pin *&pin,
|
|
LogicValue &value)
|
|
{
|
|
pin = pin_iter_->next();
|
|
value = value_;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
FindNetDrvrLoads::FindNetDrvrLoads(const Pin *drvr_pin,
|
|
PinSet &visited_drvrs,
|
|
PinSeq &loads,
|
|
PinSeq &drvrs,
|
|
const Network *network) :
|
|
drvr_pin_(drvr_pin),
|
|
visited_drvrs_(visited_drvrs),
|
|
loads_(loads),
|
|
drvrs_(drvrs),
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
void
|
|
FindNetDrvrLoads::operator()(const Pin *pin)
|
|
{
|
|
if (network_->isLoad(pin))
|
|
loads_.push_back(pin);
|
|
if (network_->isDriver(pin)) {
|
|
drvrs_.push_back(pin);
|
|
if (pin != drvr_pin_)
|
|
visited_drvrs_.insert(pin);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
static void
|
|
visitPinsAboveNet1(const Pin *hpin,
|
|
Net *above_net,
|
|
NetSet &visited,
|
|
PinSet &above_drvrs,
|
|
PinSet &above_loads,
|
|
const Network *network)
|
|
{
|
|
visited.insert(above_net);
|
|
// Visit above net pins.
|
|
NetPinIterator *pin_iter = network->pinIterator(above_net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *above_pin = pin_iter->next();
|
|
if (above_pin != hpin) {
|
|
if (network->isDriver(above_pin))
|
|
above_drvrs.insert(above_pin);
|
|
if (network->isLoad(above_pin))
|
|
above_loads.insert(above_pin);
|
|
Term *above_term = network->term(above_pin);
|
|
if (above_term) {
|
|
Net *above_net1 = network->net(above_term);
|
|
if (above_net1 && !visited.hasKey(above_net1))
|
|
visitPinsAboveNet1(above_pin, above_net1, visited,
|
|
above_drvrs, above_loads, network);
|
|
}
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
|
|
// Search up from net terminals.
|
|
NetTermIterator *term_iter = network->termIterator(above_net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = network->pin(term);
|
|
if (above_pin
|
|
&& above_pin != hpin) {
|
|
Net *above_net1 = network->net(above_pin);
|
|
if (above_net1 && !visited.hasKey(above_net1))
|
|
visitPinsAboveNet1(above_pin, above_net1, visited,
|
|
above_drvrs, above_loads, network);
|
|
if (network->isDriver(above_pin))
|
|
above_drvrs.insert(above_pin);
|
|
if (network->isLoad(above_pin))
|
|
above_loads.insert(above_pin);
|
|
}
|
|
}
|
|
delete term_iter;
|
|
}
|
|
|
|
static void
|
|
visitPinsBelowNet1(const Pin *hpin,
|
|
Net *below_net,
|
|
NetSet &visited,
|
|
PinSet &below_drvrs,
|
|
PinSet &below_loads,
|
|
const Network *network)
|
|
{
|
|
visited.insert(below_net);
|
|
// Visit below net pins.
|
|
NetPinIterator *pin_iter = network->pinIterator(below_net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *below_pin = pin_iter->next();
|
|
if (below_pin != hpin) {
|
|
NetSet visited_above(network);
|
|
if (network->isDriver(below_pin))
|
|
below_drvrs.insert(below_pin);
|
|
if (network->isLoad(below_pin))
|
|
below_loads.insert(below_pin);
|
|
if (network->isHierarchical(below_pin)) {
|
|
Term *term = network->term(below_pin);
|
|
if (term) {
|
|
Net *below_net1 = network->net(term);
|
|
if (below_net1 && !visited.hasKey(below_net1))
|
|
visitPinsBelowNet1(below_pin, below_net1, visited,
|
|
below_drvrs, below_loads, network);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
}
|
|
|
|
static void
|
|
visitDrvrLoads(PinSet drvrs,
|
|
PinSet loads,
|
|
HierPinThruVisitor *visitor)
|
|
{
|
|
PinSet::Iterator drvr_iter(drvrs);
|
|
while (drvr_iter.hasNext()) {
|
|
const Pin *drvr = drvr_iter.next();
|
|
PinSet::Iterator load_iter(loads);
|
|
while (load_iter.hasNext()) {
|
|
const Pin *load = load_iter.next();
|
|
visitor->visit(drvr, load);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
visitDrvrLoadsThruHierPin(const Pin *hpin,
|
|
const Network *network,
|
|
HierPinThruVisitor *visitor)
|
|
{
|
|
Net *above_net = network->net(hpin);
|
|
if (above_net) {
|
|
// Search down from hpin terminal.
|
|
Term *term = network->term(hpin);
|
|
if (term) {
|
|
Net *below_net = network->net(term);
|
|
if (below_net) {
|
|
NetSet visited(network);
|
|
PinSet above_drvrs(network);
|
|
PinSet above_loads(network);
|
|
visitPinsAboveNet1(hpin, above_net, visited,
|
|
above_drvrs, above_loads, network);
|
|
PinSet below_drvrs(network);
|
|
PinSet below_loads(network);
|
|
visitPinsBelowNet1(hpin, below_net, visited,
|
|
below_drvrs, below_loads, network);
|
|
visitDrvrLoads(above_drvrs, below_loads, visitor);
|
|
visitDrvrLoads(below_drvrs, above_loads, visitor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
visitDrvrLoadsThruNet(const Net *net,
|
|
const Network *network,
|
|
HierPinThruVisitor *visitor)
|
|
{
|
|
NetSet visited(network);
|
|
PinSet above_drvrs(network);
|
|
PinSet above_loads(network);
|
|
PinSet below_drvrs(network);
|
|
PinSet below_loads(network);
|
|
PinSet net_drvrs(network);
|
|
PinSet net_loads(network);
|
|
NetPinIterator *pin_iter = network->pinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
if (network->isHierarchical(pin)) {
|
|
// Search down from pin terminal.
|
|
const Term *term = network->term(pin);
|
|
if (term) {
|
|
Net *below_net = network->net(term);
|
|
if (below_net) {
|
|
visitPinsBelowNet1(pin, below_net, visited,
|
|
below_drvrs, below_loads, network);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (network->isDriver(pin))
|
|
net_drvrs.insert(pin);
|
|
if (network->isLoad(pin))
|
|
net_loads.insert(pin);
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
|
|
NetTermIterator *term_iter = network->termIterator(net);
|
|
while (term_iter->hasNext()) {
|
|
Term *term = term_iter->next();
|
|
Pin *above_pin = network->pin(term);
|
|
if (above_pin) {
|
|
if (network->isDriver(above_pin))
|
|
above_drvrs.insert(above_pin);
|
|
if (network->isLoad(above_pin))
|
|
above_loads.insert(above_pin);
|
|
Net *above_net = network->net(above_pin);
|
|
if (above_net)
|
|
visitPinsAboveNet1(above_pin, above_net, visited,
|
|
above_drvrs, above_loads, network);
|
|
}
|
|
}
|
|
delete term_iter;
|
|
visitDrvrLoads(above_drvrs, below_loads, visitor);
|
|
visitDrvrLoads(above_drvrs, net_loads, visitor);
|
|
visitDrvrLoads(below_drvrs, above_loads, visitor);
|
|
visitDrvrLoads(below_drvrs, net_loads, visitor);
|
|
visitDrvrLoads(net_drvrs, above_loads, visitor);
|
|
visitDrvrLoads(net_drvrs, below_loads, visitor);
|
|
visitDrvrLoads(net_drvrs, net_loads, visitor);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
char
|
|
logicValueString(LogicValue value)
|
|
{
|
|
static char str[] = "01X^v";
|
|
return str[int(value)];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
CellIdLess::CellIdLess(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
bool
|
|
CellIdLess::operator()(const Cell *cell1,
|
|
const Cell *cell2) const
|
|
{
|
|
return network_->id(cell1) < network_->id(cell2);
|
|
}
|
|
|
|
PortIdLess::PortIdLess(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
bool
|
|
PortIdLess::operator()(const Port *port1,
|
|
const Port *port2) const
|
|
{
|
|
return network_->id(port1) < network_->id(port2);
|
|
}
|
|
|
|
InstanceIdLess::InstanceIdLess(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
bool
|
|
InstanceIdLess::operator()(const Instance *inst1,
|
|
const Instance *inst2) const
|
|
{
|
|
return network_->id(inst1) < network_->id(inst2);
|
|
}
|
|
|
|
PinIdLess::PinIdLess(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
bool
|
|
PinIdLess::operator()(const Pin *pin1,
|
|
const Pin *pin2) const
|
|
{
|
|
return network_->id(pin1) < network_->id(pin2);
|
|
}
|
|
|
|
PinIdHash::PinIdHash(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
size_t
|
|
PinIdHash::operator()(const Pin *pin) const
|
|
{
|
|
return network_->id(pin);
|
|
}
|
|
|
|
NetIdLess::NetIdLess(const Network *network) :
|
|
network_(network)
|
|
{
|
|
}
|
|
|
|
bool
|
|
NetIdLess::operator()(const Net *net1,
|
|
const Net *net2) const
|
|
{
|
|
return network_->id(net1) < network_->id(net2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
CellSet::CellSet(const Network *network) :
|
|
Set<const Cell*, CellIdLess>(CellIdLess(network))
|
|
{
|
|
}
|
|
|
|
PortSet::PortSet(const Network *network) :
|
|
Set<const Port*, PortIdLess>(PortIdLess(network))
|
|
{
|
|
}
|
|
|
|
InstanceSet::InstanceSet() :
|
|
Set<const Instance*, InstanceIdLess>(InstanceIdLess(nullptr))
|
|
{
|
|
}
|
|
|
|
InstanceSet::InstanceSet(const Network *network) :
|
|
Set<const Instance*, InstanceIdLess>(InstanceIdLess(network))
|
|
{
|
|
}
|
|
|
|
int
|
|
InstanceSet::compare(const InstanceSet *set1,
|
|
const InstanceSet *set2,
|
|
const Network *network)
|
|
{
|
|
size_t size1 = set1 ? set1->size() : 0;
|
|
size_t size2 = set2 ? set2->size() : 0;
|
|
if (size1 == size2) {
|
|
InstanceSet::ConstIterator iter1(set1);
|
|
InstanceSet::ConstIterator iter2(set2);
|
|
while (iter1.hasNext() && iter2.hasNext()) {
|
|
const Instance *inst1 = iter1.next();
|
|
const Instance *inst2 = iter2.next();
|
|
ObjectId id1 = network->id(inst1);
|
|
ObjectId id2 = network->id(inst2);
|
|
if (id1 < id2)
|
|
return -1;
|
|
else if (id1 > id2)
|
|
return 1;
|
|
}
|
|
// Sets are equal.
|
|
return 0;
|
|
}
|
|
else
|
|
return (size1 > size2) ? 1 : -1;
|
|
}
|
|
|
|
PinSet::PinSet() :
|
|
Set<const Pin*, PinIdLess>(PinIdLess(nullptr))
|
|
{
|
|
}
|
|
|
|
PinSet::PinSet(const Network *network) :
|
|
Set<const Pin*, PinIdLess>(PinIdLess(network))
|
|
{
|
|
}
|
|
|
|
int
|
|
PinSet::compare(const PinSet *set1,
|
|
const PinSet *set2,
|
|
const Network *network)
|
|
{
|
|
size_t size1 = set1 ? set1->size() : 0;
|
|
size_t size2 = set2 ? set2->size() : 0;
|
|
if (size1 == size2) {
|
|
PinSet::ConstIterator iter1(set1);
|
|
PinSet::ConstIterator iter2(set2);
|
|
while (iter1.hasNext() && iter2.hasNext()) {
|
|
const Pin *pin1 = iter1.next();
|
|
const Pin *pin2 = iter2.next();
|
|
ObjectId id1 = network->id(pin1);
|
|
ObjectId id2 = network->id(pin2);
|
|
if (id1 < id2)
|
|
return -1;
|
|
else if (id1 > id2)
|
|
return 1;
|
|
}
|
|
// Sets are equal.
|
|
return 0;
|
|
}
|
|
else
|
|
return (size1 > size2) ? 1 : -1;
|
|
}
|
|
|
|
NetSet::NetSet() :
|
|
Set<const Net*, NetIdLess>(NetIdLess(nullptr))
|
|
{
|
|
}
|
|
|
|
NetSet::NetSet(const Network *network) :
|
|
Set<const Net*, NetIdLess>(NetIdLess(network))
|
|
{
|
|
}
|
|
|
|
int
|
|
NetSet::compare(const NetSet *set1,
|
|
const NetSet *set2,
|
|
const Network *network)
|
|
{
|
|
size_t size1 = set1 ? set1->size() : 0;
|
|
size_t size2 = set2 ? set2->size() : 0;
|
|
if (size1 == size2) {
|
|
NetSet::ConstIterator iter1(set1);
|
|
NetSet::ConstIterator iter2(set2);
|
|
while (iter1.hasNext() && iter2.hasNext()) {
|
|
const Net *net1 = iter1.next();
|
|
const Net *net2 = iter2.next();
|
|
ObjectId id1 = network->id(net1);
|
|
ObjectId id2 = network->id(net2);
|
|
if (id1 < id2)
|
|
return -1;
|
|
else if (id1 > id2)
|
|
return 1;
|
|
}
|
|
// Sets are equal.
|
|
return 0;
|
|
}
|
|
else
|
|
return (size1 > size2) ? 1 : -1;
|
|
}
|
|
|
|
} // namespace
|