From 409d165961b3d5b20919efacec8c1f9d6e557ef8 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Thu, 12 Dec 2024 18:55:54 -0800 Subject: [PATCH 01/15] fix for hierarchy connect module traverse Signed-off-by: andyfox-rushc --- src/dbSta/src/dbNetwork.cc | 7 ++-- src/dbSta/src/tmp | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/dbSta/src/tmp diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index 9494de32886..41fe0a2c2c6 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -2894,7 +2894,7 @@ void dbNetwork::getParentHierarchy(dbModule* start_module, if (cur_module == top_module) { return; } - cur_module = start_module->getModInst()->getParent(); + cur_module = cur_module->getModInst()->getParent(); } } @@ -3125,7 +3125,9 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, } else { dest_pin->connect(top_net); } - + //TODO: Clean up after everything is resolved. + //Turns out that there are intermediate states + /* // During the addition of new ports and new wiring we may // leave orphaned pins, clean them up. std::set cleaned_up; @@ -3145,6 +3147,7 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, } } } + */ } } diff --git a/src/dbSta/src/tmp b/src/dbSta/src/tmp new file mode 100644 index 00000000000..32e131ea1f9 --- /dev/null +++ b/src/dbSta/src/tmp @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (c) 2021, The Regents of the University of California +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#include "AbstractPowerDensityDataSource.h" +#include "gui/heatMap.h" + +namespace sta { +class dbSta; +class Corner; + +class PowerDensityDataSource : public gui::RealValueHeatMapDataSource, + public AbstractPowerDensityDataSource +{ + public: + PowerDensityDataSource(dbSta* sta, utl::Logger* logger); + + protected: + bool populateMap() override; + void combineMapData(bool base_has_value, + double& base, + double new_data, + double data_area, + double intersection_area, + double rect_area) override; + + private: + sta::dbSta* sta_; + + bool include_internal_ = true; + bool include_leakage_ = true; + bool include_switching_ = true; + + std::string corner_; + + sta::Corner* getCorner() const; +}; + +} // namespace sta From 1cf4943b6ce0977885c5440772eead2c6f4c313a Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 16 Dec 2024 22:40:42 -0800 Subject: [PATCH 02/15] Unit test with hierarchy, part 1: no modnets, yet Signed-off-by: andyfox-rushc --- src/odb/test/cpp/TestModule.cpp | 278 ++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) diff --git a/src/odb/test/cpp/TestModule.cpp b/src/odb/test/cpp/TestModule.cpp index 8582ca460ad..c26867c7289 100644 --- a/src/odb/test/cpp/TestModule.cpp +++ b/src/odb/test/cpp/TestModule.cpp @@ -287,6 +287,7 @@ BOOST_FIXTURE_TEST_CASE(test_default, F_DEFAULT) dbInst::destroy(inst1); BOOST_TEST(parent_mod->getInsts().size() == 0); } + BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) { auto top = block->getTopModule(); @@ -297,6 +298,281 @@ BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) auto minst2 = odb::dbModInst::create(master1, master2, "minst2"); BOOST_TEST(block->findModInst("minst1/minst2") == minst2); } + + +/* + Test fixture for hierarchical connect test + ------------------------------------------ + + Two module instances, 1 with 1 inverter, second with 4 inverters. + Modules have different hierarchical depth and shared terms + to stress test the hierarchical connection code. + + So any reconnection has to go up and down the hierarchy. + + top level module <-- {inv_module, 4inv_module} + inv_module <-- 1 inverter + + + Test: + Add a buffer in module 1 and make sure connectivity ok + (both hierarchical and flat). + */ + +dbDatabase* createSimpleDBDelimiter() +{ + utl::Logger* logger = new utl::Logger(); + dbDatabase* db = dbDatabase::create(); + db->setLogger(logger); + dbTech* tech = dbTech::create(db, "tech"); + dbTechLayer::create(tech, "L1", dbTechLayerType::MASTERSLICE); + dbLib* lib = dbLib::create(db, "lib1", tech, ','); + dbChip* chip = dbChip::create(db); + //set up the delimiter + dbBlock::create(chip, "simple_block",nullptr,'/'); + createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o"); + createMaster2X1(lib, "or2", 500, 500, "a", "b", "o"); + createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); + return db; +} + + +struct F_HCONNECT +{ + F_HCONNECT() + { + db = createSimpleDBDelimiter(); + block = db->getChip()->getBlock(); + lib = db->findLib("lib1"); + + root_mod = dbModule::create(block, "root_mod") ; + + inv1_mod_master = dbModule::create(block, "inv1_master_mod"); + dbModBTerm* inv1_mod_i0_port = dbModBTerm::create(inv1_mod_master,"i0"); + dbModBTerm* inv1_mod_o0_port = dbModBTerm::create(inv1_mod_master,"o0"); + inv1_mod_inst = dbModInst::create(root_mod, inv1_mod_master, "inv1_mod_inst"); + + + inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); + dbModBTerm* inv_mod_level0_master_i0_port = dbModBTerm::create(inv4_mod_level0_master,"i0"); + dbModBTerm* inv_mod_level0_master_i1_port = dbModBTerm::create(inv4_mod_level0_master,"i1"); + dbModBTerm* inv_mod_level0_master_i2_port = dbModBTerm::create(inv4_mod_level0_master,"i2"); + dbModBTerm* inv_mod_level0_master_i3_port = dbModBTerm::create(inv4_mod_level0_master,"i3"); + dbModBTerm* inv_mod_level0_master_o0_port= dbModBTerm::create(inv4_mod_level0_master,"o0"); + + + inv4_mod_level1_master = dbModule::create(block, "inv4_master_level1"); + inv_mod_level1_master_i0_port = dbModBTerm::create(inv4_mod_level1_master,"i0"); + inv_mod_level1_master_i1_port = dbModBTerm::create(inv4_mod_level1_master,"i1"); + inv_mod_level1_master_i2_port = dbModBTerm::create(inv4_mod_level1_master,"i2"); + inv_mod_level1_master_i3_port = dbModBTerm::create(inv4_mod_level1_master,"i3"); + inv_mod_level1_master_o0_port= dbModBTerm::create(inv4_mod_level1_master,"o0"); + + + inv4_mod_level2_master = dbModule::create(block, "inv4_master_level2"); + inv_mod_level2_master_i0_port = dbModBTerm::create(inv4_mod_level2_master,"i0"); + inv_mod_level2_master_i1_port = dbModBTerm::create(inv4_mod_level2_master,"i1"); + inv_mod_level2_master_i2_port = dbModBTerm::create(inv4_mod_level2_master,"i2"); + inv_mod_level2_master_i3_port = dbModBTerm::create(inv4_mod_level2_master,"i3"); + inv_mod_level2_master_o0_port= dbModBTerm::create(inv4_mod_level2_master,"o0"); + + + + //During modinst creation we set the parent. + inv4_mod_level0_inst = dbModInst::create(root_mod, //parent + inv4_mod_level0_master, + "inv4_mod_level0_inst"); + inv4_mod_level1_inst = dbModInst::create(inv4_mod_level0_master, //parent + inv4_mod_level1_master, + "inv4_mod_level1_inst"); + inv4_mod_level2_inst = dbModInst::create(inv4_mod_level1_master, //parent + inv4_mod_level2_master, + "inv4_mod_level2_inst"); + + + //Use full scoped names for instances for this test + inv1_1 = dbInst::create(block, lib->findMaster("inv1"), "inv1_mod_inst/inst1",false,inv1_mod_master); + inv1_1_inst_ip0 = block -> findITerm("inv1_mod_inst/inst1/ip0"); + inv1_1_inst_op0 = block -> findITerm("inv1_mod_inst/inst1/op0"); + + + // + //create the low level inverter instances, for now uniquely name them in the scope of a block. + // + inv4_1 = dbInst::create(block, lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst1"); + + + //get the iterm off the instance. Just give the terminal name + //offset used to find iterm. + inv4_1_ip = inv4_1 -> findITerm( + "ip0"); + inv4_1_op = inv4_1 -> findITerm( + "op0"); + + inv4_2 = dbInst::create(block, lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst2"); + inv4_2_ip = inv4_2 -> findITerm("ip0"); + inv4_2_op = inv4_2 -> findITerm("op0"); + + inv4_3 = dbInst::create(block, lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst3"); + inv4_3_ip = inv4_3 -> findITerm("ip0"); + inv4_3_op = inv4_3 -> findITerm("op0"); + + + inv4_4 = dbInst::create(block, lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst4"); + inv4_4_ip = inv4_4 -> findITerm("ip0"); + inv4_4_op = inv4_4 -> findITerm("op0"); + + + inv4_mod_level2_master -> addInst(inv4_1); + inv4_mod_level2_master -> addInst(inv4_2); + inv4_mod_level2_master -> addInst(inv4_3); + inv4_mod_level2_master -> addInst(inv4_4); + + + //First make the flat view + dbNet* ip0_net = dbNet::create(block,"ip0_flat_net",false); + dbNet* inv_op_net = dbNet::create(block,"inv_op_flat_net",false); + dbNet* op0_net = dbNet::create(block,"op0_flat_net",false); + dbNet* op1_net = dbNet::create(block,"op1_flat_net",false); + dbNet* op2_net = dbNet::create(block,"op2_flat_net",false); + dbNet* op3_net = dbNet::create(block,"op3_flat_net",false); + + //connections to the primary (root) ports + ip0_bterm = dbBTerm::create(ip0_net,"ip0"); + op0_bterm = dbBTerm::create(op0_net,"op0"); + op1_bterm = dbBTerm::create(op1_net,"op1"); + op2_bterm = dbBTerm::create(op2_net,"op2"); + op3_bterm = dbBTerm::create(op3_net,"op3"); + + + //flat connections: + //inverter 1 in module inv1_1 + inv1_1_inst_ip0 -> connect(ip0_net) ; + inv1_1_inst_op0 -> connect(inv_op_net); + + //now the 4 inverters in inv4_1 + inv4_1_ip -> connect(inv_op_net); + inv4_2_ip -> connect(inv_op_net); + inv4_3_ip -> connect(inv_op_net); + inv4_4_ip -> connect(inv_op_net); + + //now core to external connections + inv4_1_op -> connect(op0_net); + inv4_2_op -> connect(op1_net); + inv4_3_op -> connect(op2_net); + inv4_4_op -> connect(op3_net); + + std::stringstream str_str; + DbStrDebugHierarchy(block, str_str); + + printf("The Flat design created %s\n", str_str.str().c_str()); + + } + + ~F_HCONNECT() { dbDatabase::destroy(db); } + + dbDatabase* db; + dbLib* lib; + dbBlock* block; + + dbModule* root_mod; + dbModule* inv1_mod_master; + dbModule* inv4_mod_level0_master; + dbModule* inv4_mod_level1_master; + dbModule* inv4_mod_level2_master; + + dbModBTerm* inv_mod_level0_master_i0_port; + dbModBTerm* inv_mod_level0_master_i1_port; + dbModBTerm* inv_mod_level0_master_i2_port; + dbModBTerm* inv_mod_level0_master_i3_port; + dbModBTerm* inv_mod_level0_master_o0_port; + + + dbModBTerm* inv_mod_level1_master_i0_port; + dbModBTerm* inv_mod_level1_master_i1_port; + dbModBTerm* inv_mod_level1_master_i2_port; + dbModBTerm* inv_mod_level1_master_i3_port; + dbModBTerm* inv_mod_level1_master_o0_port; + + dbModBTerm* inv_mod_level2_master_i0_port; + dbModBTerm* inv_mod_level2_master_i1_port; + dbModBTerm* inv_mod_level2_master_i2_port; + dbModBTerm* inv_mod_level2_master_i3_port; + dbModBTerm* inv_mod_level2_master_o0_port; + + + dbModInst* inv1_mod_inst; + dbModInst* inv4_mod_level0_inst; + dbModInst* inv4_mod_level1_inst; + dbModInst* inv4_mod_level2_inst; + + + dbInst* inv1_1; + dbInst* inv4_1; + dbInst* inv4_2; + dbInst* inv4_3; + dbInst* inv4_4; + + dbNet* ip0_net; + dbNet* inv_op__net; + dbNet* op0_net; + dbNet* op1_net; + dbNet* op2_net; + dbNet* op3_net; + + dbBTerm* ip0_bterm; + dbBTerm* op0_bterm; + dbBTerm* op1_bterm; + dbBTerm* op2_bterm; + dbBTerm* op3_bterm; + + dbModITerm* inv1_1_ip; + dbModITerm* inv1_1_op; + + dbITerm* inv1_1_inst_ip0; + dbITerm* inv1_1_inst_op0; + + dbITerm* inv4_1_ip; + dbITerm* inv4_2_ip; + dbITerm* inv4_3_ip; + dbITerm* inv4_4_ip; + dbITerm* inv4_1_op; + dbITerm* inv4_2_op; + dbITerm* inv4_3_op; + dbITerm* inv4_4_op; + + +}; + + +BOOST_FIXTURE_TEST_CASE(test_hier, F_HCONNECT) +{ + auto top = block->getTopModule(); + BOOST_TEST(top != nullptr); + auto master1 = odb::dbModule::create(block, "master1"); + + odb::dbModInst::create(top, master1, "minst1"); + + auto master2 = odb::dbModule::create(block, "master2"); + auto minst2 = odb::dbModInst::create(master1, master2, "minst2"); + + BOOST_TEST(block->findModInst("minst1/minst2") == minst2); + +} + + +BOOST_FIXTURE_TEST_CASE(test_hierconnect, F_HCONNECT) +{ + +} + + + + struct F_DETAILED { F_DETAILED() @@ -333,6 +609,8 @@ struct F_DETAILED dbInst* inst2; dbInst* inst3; }; + + BOOST_FIXTURE_TEST_CASE(test_destroy, F_DETAILED) { BOOST_TEST(block->getModInsts().size() == 3); From ac40e4f18f72a237fbe5256c4de742072cf962cb Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 16 Dec 2024 22:41:15 -0800 Subject: [PATCH 03/15] Unit test db creation with delimiters Signed-off-by: andyfox-rushc --- src/odb/test/cpp/helper/helper.cpp | 18 ++++++++++++++++++ src/odb/test/cpp/helper/helper.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/src/odb/test/cpp/helper/helper.cpp b/src/odb/test/cpp/helper/helper.cpp index 791c2957f0d..4253930024b 100644 --- a/src/odb/test/cpp/helper/helper.cpp +++ b/src/odb/test/cpp/helper/helper.cpp @@ -56,6 +56,23 @@ dbMaster* createMaster2X1(dbLib* lib, return master; } +dbMaster* createMaster1X1(dbLib* lib, + const char* name, + uint width, + uint height, + const char* in1, + const char* out) +{ + dbMaster* master = dbMaster::create(lib, name); + master->setWidth(width); + master->setHeight(height); + master->setType(dbMasterType::CORE); + dbMTerm::create(master, in1, dbIoType::INPUT, dbSigType::SIGNAL); + dbMTerm::create(master, out, dbIoType::OUTPUT, dbSigType::SIGNAL); + master->setFrozen(); + return master; +} + dbDatabase* createSimpleDB() { utl::Logger* logger = new utl::Logger(); @@ -68,6 +85,7 @@ dbDatabase* createSimpleDB() dbBlock::create(chip, "simple_block"); createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o"); createMaster2X1(lib, "or2", 500, 500, "a", "b", "o"); + createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); return db; } diff --git a/src/odb/test/cpp/helper/helper.h b/src/odb/test/cpp/helper/helper.h index 04f7abe78c2..d4eee3debf3 100644 --- a/src/odb/test/cpp/helper/helper.h +++ b/src/odb/test/cpp/helper/helper.h @@ -41,6 +41,12 @@ odb::dbMaster* createMaster2X1(odb::dbLib* lib, const char* in1, const char* in2, const char* out); +odb::dbMaster* createMaster1X1(odb::dbLib* lib, + const char* name, + uint width, + uint height, + const char* in1, + const char* out); odb::dbDatabase* createSimpleDB(); From 6810b3ceeabfedbd8a72094fcd40774a45ddc9e7 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Thu, 19 Dec 2024 21:25:59 -0800 Subject: [PATCH 04/15] Debugged 4 level hierarchical structure Signed-off-by: andyfox-rushc --- src/odb/test/cpp/TestModule.cpp | 679 ++++++++++++++++++++++++-------- 1 file changed, 506 insertions(+), 173 deletions(-) diff --git a/src/odb/test/cpp/TestModule.cpp b/src/odb/test/cpp/TestModule.cpp index c26867c7289..36559e5e663 100644 --- a/src/odb/test/cpp/TestModule.cpp +++ b/src/odb/test/cpp/TestModule.cpp @@ -299,24 +299,23 @@ BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) BOOST_TEST(block->findModInst("minst1/minst2") == minst2); } - -/* +/* Test fixture for hierarchical connect test ------------------------------------------ - Two module instances, 1 with 1 inverter, second with 4 inverters. - Modules have different hierarchical depth and shared terms - to stress test the hierarchical connection code. - - So any reconnection has to go up and down the hierarchy. - - top level module <-- {inv_module, 4inv_module} - inv_module <-- 1 inverter - - - Test: - Add a buffer in module 1 and make sure connectivity ok - (both hierarchical and flat). + Two modules, 1 with 1 inverter, second with 4 inverters. + + inv1 is instantiated in the top level + inv4 is instantiated three levels down: + level0 -- instantiation in root + level1 + level2 -- contains 4 inverters + + Objective of this test is to stress the hierarchical connection code. + + + + */ dbDatabase* createSimpleDBDelimiter() @@ -328,149 +327,433 @@ dbDatabase* createSimpleDBDelimiter() dbTechLayer::create(tech, "L1", dbTechLayerType::MASTERSLICE); dbLib* lib = dbLib::create(db, "lib1", tech, ','); dbChip* chip = dbChip::create(db); - //set up the delimiter - dbBlock::create(chip, "simple_block",nullptr,'/'); + // set up the delimiter + dbBlock::create(chip, "simple_block", nullptr, '/'); createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o"); createMaster2X1(lib, "or2", 500, 500, "a", "b", "o"); - createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); + createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); return db; } - struct F_HCONNECT { F_HCONNECT() { + // create a db with a delimiter & initialize the db library db = createSimpleDBDelimiter(); block = db->getChip()->getBlock(); lib = db->findLib("lib1"); - root_mod = dbModule::create(block, "root_mod") ; + root_mod = dbModule::create(block, "root_mod"); + // The bterms are created below during wiring + // Note a bterm without a parent is a root bterm. - inv1_mod_master = dbModule::create(block, "inv1_master_mod"); - dbModBTerm* inv1_mod_i0_port = dbModBTerm::create(inv1_mod_master,"i0"); - dbModBTerm* inv1_mod_o0_port = dbModBTerm::create(inv1_mod_master,"o0"); - inv1_mod_inst = dbModInst::create(root_mod, inv1_mod_master, "inv1_mod_inst"); - - - inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); - dbModBTerm* inv_mod_level0_master_i0_port = dbModBTerm::create(inv4_mod_level0_master,"i0"); - dbModBTerm* inv_mod_level0_master_i1_port = dbModBTerm::create(inv4_mod_level0_master,"i1"); - dbModBTerm* inv_mod_level0_master_i2_port = dbModBTerm::create(inv4_mod_level0_master,"i2"); - dbModBTerm* inv_mod_level0_master_i3_port = dbModBTerm::create(inv4_mod_level0_master,"i3"); - dbModBTerm* inv_mod_level0_master_o0_port= dbModBTerm::create(inv4_mod_level0_master,"o0"); - - - inv4_mod_level1_master = dbModule::create(block, "inv4_master_level1"); - inv_mod_level1_master_i0_port = dbModBTerm::create(inv4_mod_level1_master,"i0"); - inv_mod_level1_master_i1_port = dbModBTerm::create(inv4_mod_level1_master,"i1"); - inv_mod_level1_master_i2_port = dbModBTerm::create(inv4_mod_level1_master,"i2"); - inv_mod_level1_master_i3_port = dbModBTerm::create(inv4_mod_level1_master,"i3"); - inv_mod_level1_master_o0_port= dbModBTerm::create(inv4_mod_level1_master,"o0"); - - - inv4_mod_level2_master = dbModule::create(block, "inv4_master_level2"); - inv_mod_level2_master_i0_port = dbModBTerm::create(inv4_mod_level2_master,"i0"); - inv_mod_level2_master_i1_port = dbModBTerm::create(inv4_mod_level2_master,"i1"); - inv_mod_level2_master_i2_port = dbModBTerm::create(inv4_mod_level2_master,"i2"); - inv_mod_level2_master_i3_port = dbModBTerm::create(inv4_mod_level2_master,"i3"); - inv_mod_level2_master_o0_port= dbModBTerm::create(inv4_mod_level2_master,"o0"); - + // Make the inv1 module (contains 1 inverter). + inv1_mod_master = dbModule::create(block, "inv1_master_mod"); + inv1_mod_i0_port = dbModBTerm::create(inv1_mod_master, "i0"); + inv1_mod_o0_port = dbModBTerm::create(inv1_mod_master, "o0"); + inv1_mod_inst + = dbModInst::create(root_mod, inv1_mod_master, "inv1_mod_inst"); - //During modinst creation we set the parent. - inv4_mod_level0_inst = dbModInst::create(root_mod, //parent - inv4_mod_level0_master, - "inv4_mod_level0_inst"); - inv4_mod_level1_inst = dbModInst::create(inv4_mod_level0_master, //parent - inv4_mod_level1_master, - "inv4_mod_level1_inst"); - inv4_mod_level2_inst = dbModInst::create(inv4_mod_level1_master, //parent - inv4_mod_level2_master, - "inv4_mod_level2_inst"); + inv1_mod_inst_i0_miterm = dbModITerm::create(inv1_mod_inst, "i0"); + inv1_mod_inst_o0_miterm = dbModITerm::create(inv1_mod_inst, "o0"); + // correlate the iterms and bterms + inv1_mod_inst_i0_miterm->setChildModBTerm(inv1_mod_i0_port); + inv1_mod_i0_port->setParentModITerm(inv1_mod_inst_i0_miterm); + inv1_mod_inst_o0_miterm->setChildModBTerm(inv1_mod_o0_port); + inv1_mod_o0_port->setParentModITerm(inv1_mod_inst_o0_miterm); - //Use full scoped names for instances for this test - inv1_1 = dbInst::create(block, lib->findMaster("inv1"), "inv1_mod_inst/inst1",false,inv1_mod_master); - inv1_1_inst_ip0 = block -> findITerm("inv1_mod_inst/inst1/ip0"); - inv1_1_inst_op0 = block -> findITerm("inv1_mod_inst/inst1/op0"); + inv1_1 = dbInst::create(block, + lib->findMaster("inv1"), + "inv1_mod_inst/inst1", + false, + inv1_mod_master); + inv1_1_inst_ip0 = block->findITerm("inv1_mod_inst/inst1/ip0"); + inv1_1_inst_op0 = block->findITerm("inv1_mod_inst/inst1/op0"); + inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); + inv4_mod_level0_master_i0_port + = dbModBTerm::create(inv4_mod_level0_master, "i0"); + inv4_mod_level0_master_o0_port + = dbModBTerm::create(inv4_mod_level0_master, "o0"); + inv4_mod_level0_master_o1_port + = dbModBTerm::create(inv4_mod_level0_master, "o1"); + inv4_mod_level0_master_o2_port + = dbModBTerm::create(inv4_mod_level0_master, "o2"); + inv4_mod_level0_master_o3_port + = dbModBTerm::create(inv4_mod_level0_master, "o3"); + + inv4_mod_level1_master = dbModule::create(block, "inv4_master_level1"); + inv4_mod_level1_master_i0_port + = dbModBTerm::create(inv4_mod_level1_master, "i0"); + inv4_mod_level1_master_o0_port + = dbModBTerm::create(inv4_mod_level1_master, "o0"); + inv4_mod_level1_master_o1_port + = dbModBTerm::create(inv4_mod_level1_master, "o1"); + inv4_mod_level1_master_o2_port + = dbModBTerm::create(inv4_mod_level1_master, "o2"); + inv4_mod_level1_master_o3_port + = dbModBTerm::create(inv4_mod_level1_master, "o3"); + + inv4_mod_level2_master = dbModule::create(block, "inv4_master_level2"); + inv4_mod_level2_master_i0_port + = dbModBTerm::create(inv4_mod_level2_master, "i0"); + inv4_mod_level2_master_o0_port + = dbModBTerm::create(inv4_mod_level2_master, "o0"); + inv4_mod_level2_master_o1_port + = dbModBTerm::create(inv4_mod_level2_master, "o1"); + inv4_mod_level2_master_o2_port + = dbModBTerm::create(inv4_mod_level2_master, "o2"); + inv4_mod_level2_master_o3_port + = dbModBTerm::create(inv4_mod_level2_master, "o3"); + + // During modinst creation we set the parent. + inv4_mod_level0_inst = dbModInst::create(root_mod, // parent + inv4_mod_level0_master, + "inv4_mod_level0_inst"); + inv4_mod_level0_inst_i0_miterm + = dbModITerm::create(inv4_mod_level0_inst, "i0"); + inv4_mod_level0_inst_i0_miterm->setChildModBTerm( + inv4_mod_level0_master_i0_port); + inv4_mod_level0_master_i0_port->setParentModITerm( + inv4_mod_level0_inst_i0_miterm); + + inv4_mod_level0_inst_o0_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o0"); + inv4_mod_level0_inst_o0_miterm->setChildModBTerm( + inv4_mod_level0_master_o0_port); + inv4_mod_level0_master_o0_port->setParentModITerm( + inv4_mod_level0_inst_o0_miterm); + + inv4_mod_level0_inst_o1_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o1"); + inv4_mod_level0_inst_o1_miterm->setChildModBTerm( + inv4_mod_level0_master_o1_port); + inv4_mod_level0_master_o1_port->setParentModITerm( + inv4_mod_level0_inst_o1_miterm); + + inv4_mod_level0_inst_o2_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o2"); + inv4_mod_level0_inst_o2_miterm->setChildModBTerm( + inv4_mod_level0_master_o2_port); + inv4_mod_level0_master_o2_port->setParentModITerm( + inv4_mod_level0_inst_o2_miterm); + + inv4_mod_level0_inst_o3_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o3"); + inv4_mod_level0_inst_o3_miterm->setChildModBTerm( + inv4_mod_level0_master_o3_port); + inv4_mod_level0_master_o3_port->setParentModITerm( + inv4_mod_level0_inst_o3_miterm); + + inv4_mod_level1_inst = dbModInst::create(inv4_mod_level0_master, // parent + inv4_mod_level1_master, + "inv4_mod_level1_inst"); + + inv4_mod_level1_inst_i0_miterm + = dbModITerm::create(inv4_mod_level1_inst, "i0"); + inv4_mod_level1_inst_i0_miterm->setChildModBTerm( + inv4_mod_level1_master_i0_port); + inv4_mod_level1_master_i0_port->setParentModITerm( + inv4_mod_level1_inst_i0_miterm); + + inv4_mod_level1_inst_o0_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o0"); + inv4_mod_level1_inst_o0_miterm->setChildModBTerm( + inv4_mod_level1_master_o0_port); + inv4_mod_level1_master_o0_port->setParentModITerm( + inv4_mod_level1_inst_o0_miterm); + + inv4_mod_level1_inst_o1_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o1"); + inv4_mod_level1_inst_o1_miterm->setChildModBTerm( + inv4_mod_level1_master_o1_port); + inv4_mod_level1_master_o1_port->setParentModITerm( + inv4_mod_level1_inst_o1_miterm); + + inv4_mod_level1_inst_o2_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o2"); + inv4_mod_level1_inst_o2_miterm->setChildModBTerm( + inv4_mod_level1_master_o2_port); + inv4_mod_level1_master_o2_port->setParentModITerm( + inv4_mod_level1_inst_o2_miterm); + + inv4_mod_level1_inst_o3_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o3"); + inv4_mod_level1_inst_o3_miterm->setChildModBTerm( + inv4_mod_level1_master_o3_port); + inv4_mod_level1_master_o3_port->setParentModITerm( + inv4_mod_level1_inst_o3_miterm); + + inv4_mod_level2_inst = dbModInst::create(inv4_mod_level1_master, // parent + inv4_mod_level2_master, + "inv4_mod_level2_inst"); + + inv4_mod_level2_inst_i0_miterm + = dbModITerm::create(inv4_mod_level2_inst, "i0"); + inv4_mod_level2_inst_i0_miterm->setChildModBTerm( + inv4_mod_level2_master_i0_port); + inv4_mod_level2_master_i0_port->setParentModITerm( + inv4_mod_level2_inst_i0_miterm); + + inv4_mod_level2_inst_o0_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o0"); + inv4_mod_level2_inst_o0_miterm->setChildModBTerm( + inv4_mod_level2_master_o0_port); + inv4_mod_level2_master_o0_port->setParentModITerm( + inv4_mod_level2_inst_o0_miterm); + + inv4_mod_level2_inst_o1_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o1"); + inv4_mod_level2_inst_o1_miterm->setChildModBTerm( + inv4_mod_level2_master_o1_port); + inv4_mod_level2_master_o1_port->setParentModITerm( + inv4_mod_level2_inst_o1_miterm); + + inv4_mod_level2_inst_o2_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o2"); + inv4_mod_level2_inst_o2_miterm->setChildModBTerm( + inv4_mod_level2_master_o2_port); + inv4_mod_level2_master_o2_port->setParentModITerm( + inv4_mod_level2_inst_o2_miterm); + + inv4_mod_level2_inst_o3_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o3"); + inv4_mod_level2_inst_o3_miterm->setChildModBTerm( + inv4_mod_level2_master_o3_port); + inv4_mod_level2_master_o3_port->setParentModITerm( + inv4_mod_level2_inst_o3_miterm); // - //create the low level inverter instances, for now uniquely name them in the scope of a block. + // create the low level inverter instances, for now uniquely name them in + // the scope of a block. + + inv4_1 = dbInst::create( + block, + lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst1"); + + // get the iterm off the instance. Just give the terminal name + // offset used to find iterm. + inv4_1_ip = inv4_1->findITerm("ip0"); + inv4_1_op = inv4_1->findITerm("op0"); + + inv4_2 = dbInst::create( + block, + lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst2"); + inv4_2_ip = inv4_2->findITerm("ip0"); + inv4_2_op = inv4_2->findITerm("op0"); + + inv4_3 = dbInst::create( + block, + lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst3"); + inv4_3_ip = inv4_3->findITerm("ip0"); + inv4_3_op = inv4_3->findITerm("op0"); + + inv4_4 = dbInst::create( + block, + lib->findMaster("inv1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst4"); + inv4_4_ip = inv4_4->findITerm("ip0"); + inv4_4_op = inv4_4->findITerm("op0"); + // - inv4_1 = dbInst::create(block, lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst1"); - - - //get the iterm off the instance. Just give the terminal name - //offset used to find iterm. - inv4_1_ip = inv4_1 -> findITerm( - "ip0"); - inv4_1_op = inv4_1 -> findITerm( - "op0"); - - inv4_2 = dbInst::create(block, lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst2"); - inv4_2_ip = inv4_2 -> findITerm("ip0"); - inv4_2_op = inv4_2 -> findITerm("op0"); - - inv4_3 = dbInst::create(block, lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst3"); - inv4_3_ip = inv4_3 -> findITerm("ip0"); - inv4_3_op = inv4_3 -> findITerm("op0"); - - - inv4_4 = dbInst::create(block, lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst4"); - inv4_4_ip = inv4_4 -> findITerm("ip0"); - inv4_4_op = inv4_4 -> findITerm("op0"); - - - inv4_mod_level2_master -> addInst(inv4_1); - inv4_mod_level2_master -> addInst(inv4_2); - inv4_mod_level2_master -> addInst(inv4_3); - inv4_mod_level2_master -> addInst(inv4_4); - - - //First make the flat view - dbNet* ip0_net = dbNet::create(block,"ip0_flat_net",false); - dbNet* inv_op_net = dbNet::create(block,"inv_op_flat_net",false); - dbNet* op0_net = dbNet::create(block,"op0_flat_net",false); - dbNet* op1_net = dbNet::create(block,"op1_flat_net",false); - dbNet* op2_net = dbNet::create(block,"op2_flat_net",false); - dbNet* op3_net = dbNet::create(block,"op3_flat_net",false); - - //connections to the primary (root) ports - ip0_bterm = dbBTerm::create(ip0_net,"ip0"); - op0_bterm = dbBTerm::create(op0_net,"op0"); - op1_bterm = dbBTerm::create(op1_net,"op1"); - op2_bterm = dbBTerm::create(op2_net,"op2"); - op3_bterm = dbBTerm::create(op3_net,"op3"); - - - //flat connections: - //inverter 1 in module inv1_1 - inv1_1_inst_ip0 -> connect(ip0_net) ; - inv1_1_inst_op0 -> connect(inv_op_net); - - //now the 4 inverters in inv4_1 - inv4_1_ip -> connect(inv_op_net); - inv4_2_ip -> connect(inv_op_net); - inv4_3_ip -> connect(inv_op_net); - inv4_4_ip -> connect(inv_op_net); - - //now core to external connections - inv4_1_op -> connect(op0_net); - inv4_2_op -> connect(op1_net); - inv4_3_op -> connect(op2_net); - inv4_4_op -> connect(op3_net); + // inv4_mod_level2_master is lowest level in hierarchy + // + inv4_mod_level2_master->addInst(inv4_1); + inv4_mod_level2_master->addInst(inv4_2); + inv4_mod_level2_master->addInst(inv4_3); + inv4_mod_level2_master->addInst(inv4_4); + + inv4_mod_level2_inst_i0_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_i0_mnet"); + inv4_mod_level2_inst_o0_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o0_mnet"); + inv4_mod_level2_inst_o1_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o1_mnet"); + inv4_mod_level2_inst_o2_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o2_mnet"); + inv4_mod_level2_inst_o3_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o3_mnet"); + inv4_1_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_2_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_3_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_4_ip->connect(inv4_mod_level2_inst_i0_mnet); + + inv4_1_op->connect(inv4_mod_level2_inst_o0_mnet); + inv4_2_op->connect(inv4_mod_level2_inst_o1_mnet); + inv4_3_op->connect(inv4_mod_level2_inst_o2_mnet); + inv4_4_op->connect(inv4_mod_level2_inst_o3_mnet); + + inv4_mod_level2_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); + inv4_mod_level2_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); + inv4_mod_level2_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); + inv4_mod_level2_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); + inv4_mod_level2_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); + + // First make the flat view connectivity + dbNet* ip0_net = dbNet::create(block, "ip0_flat_net", false); + dbNet* inv_op_net = dbNet::create(block, "inv_op_flat_net", false); + op0_net = dbNet::create(block, "op0_flat_net", false); + op1_net = dbNet::create(block, "op1_flat_net", false); + op2_net = dbNet::create(block, "op2_flat_net", false); + op3_net = dbNet::create(block, "op3_flat_net", false); + + // + // connections to the primary (root) ports + // Note: a bterm without a parent is a root port. + // + ip0_bterm = dbBTerm::create(ip0_net, "ip0"); + op0_bterm = dbBTerm::create(op0_net, "op0"); + op1_bterm = dbBTerm::create(op1_net, "op1"); + op2_bterm = dbBTerm::create(op2_net, "op2"); + op3_bterm = dbBTerm::create(op3_net, "op3"); + + op0_bterm->connect(inv4_mod_level2_inst_o0_mnet); + op1_bterm->connect(inv4_mod_level2_inst_o1_mnet); + op2_bterm->connect(inv4_mod_level2_inst_o2_mnet); + op3_bterm->connect(inv4_mod_level2_inst_o3_mnet); + + // flat connections: + // inverter 1 in module inv1_1 + inv1_1_inst_ip0->connect(ip0_net); + inv1_1_inst_op0->connect(inv_op_net); + + // now the 4 inverters in inv4_1 + inv4_1_ip->connect(inv_op_net); + inv4_2_ip->connect(inv_op_net); + inv4_3_ip->connect(inv_op_net); + inv4_4_ip->connect(inv_op_net); + + // now core to external connections + inv4_1_op->connect(op0_net); + inv4_2_op->connect(op1_net); + inv4_3_op->connect(op2_net); + inv4_4_op->connect(op3_net); std::stringstream str_str; DbStrDebugHierarchy(block, str_str); - printf("The Flat design created %s\n", str_str.str().c_str()); - + + // Now build the hierarchical "overlay" + // What we are doing here is adding the modnets which hook up + + // wire in hierarchy for inv1 + + // Contents of inv1 (modnets from ports to internals). + inv1_mod_i0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_i0_mnet"); + inv1_mod_o0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_o0_mnet"); + // connection from port to net in module + inv1_mod_i0_port->connect(inv1_mod_i0_modnet); + // connection to inverter ip + inv1_1_inst_ip0->connect(inv1_mod_i0_modnet); + // from inverter op to port + inv1_1_inst_op0->connect(inv1_mod_o0_modnet); + inv1_mod_o0_port->connect(inv1_mod_o0_modnet); + + // Instantiation of inv1 connections to top level (root bterms to modnets, + // modnets to moditerms on inv1). + root_inv1_i0_mnet = dbModNet::create(root_mod, "inv1_inst_i0_mnet"); + root_inv1_o0_mnet = dbModNet::create(root_mod, "inv1_inst_o0_mnet"); + inv1_mod_inst_i0_miterm->connect(root_inv1_i0_mnet); + inv1_mod_inst_o0_miterm->connect(root_inv1_o0_mnet); + + // top level connections for inv1. + // root input to instance, via a modnet. + ip0_bterm->connect(root_inv1_i0_mnet); + // note the output from out inverter module is inv1_inst_o0_mnet + // which now needs to be hooked up the inv4 hierarchy. + + // The inv4 hierarchy connections + // inv1 -> inv4 connection + inv4_mod_level0_inst_i0_miterm->connect(root_inv1_o0_mnet); + + // level 0 is top of hierarchy, in root + // the level 0 instance -> root connections + root_inv4_o0_mnet = dbModNet::create(root_mod, "inv4_inst_o0_mnet"); + inv4_mod_level0_inst_o0_miterm->connect(root_inv4_o0_mnet); + op0_bterm->connect(root_inv4_o0_mnet); + + root_inv4_o1_mnet = dbModNet::create(root_mod, "inv4_inst_o1_mnet"); + inv4_mod_level0_inst_o1_miterm->connect(root_inv4_o1_mnet); + op1_bterm->connect(root_inv4_o1_mnet); + + root_inv4_o2_mnet = dbModNet::create(root_mod, "inv4_inst_o2_mnet"); + inv4_mod_level0_inst_o2_miterm->connect(root_inv4_o2_mnet); + op2_bterm->connect(root_inv4_o2_mnet); + + root_inv4_o3_mnet = dbModNet::create(root_mod, "inv4_inst_o3_mnet"); + inv4_mod_level0_inst_o3_miterm->connect(root_inv4_o3_mnet); + op3_bterm->connect(root_inv4_o3_mnet); + + // level 1 is next level down + // The level 1 instance connections within the scope of the + // inv4_mod_level0_master + inv4_mod_level1_inst_i0_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_i0_mnet"); + + inv4_mod_level1_inst_i0_miterm->connect(inv4_mod_level1_inst_i0_mnet); + inv4_mod_level0_master_i0_port->connect(inv4_mod_level1_inst_i0_mnet); + + inv4_mod_level1_inst_o0_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); + inv4_mod_level1_inst_o0_miterm->connect(inv4_mod_level1_inst_o0_mnet); + inv4_mod_level0_master_o0_port->connect(inv4_mod_level1_inst_o0_mnet); + + inv4_mod_level1_inst_o1_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); + inv4_mod_level1_inst_o1_miterm->connect(inv4_mod_level1_inst_o1_mnet); + inv4_mod_level0_master_o1_port->connect(inv4_mod_level1_inst_o1_mnet); + + inv4_mod_level1_inst_o2_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o2_mnet"); + inv4_mod_level1_inst_o2_miterm->connect(inv4_mod_level1_inst_o2_mnet); + inv4_mod_level0_master_o2_port->connect(inv4_mod_level1_inst_o2_mnet); + + inv4_mod_level1_inst_o3_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o3_mnet"); + inv4_mod_level1_inst_o3_miterm->connect(inv4_mod_level1_inst_o3_mnet); + inv4_mod_level0_master_o3_port->connect(inv4_mod_level1_inst_o3_mnet); + + // The level 2 instance connections within the scope of the + // inv4_mod_level1_master level 2 is the cell which contains the 4 inverters + inv4_mod_level2_inst_i0_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_i0_mnet"); + + inv4_mod_level2_inst_i0_miterm->connect(inv4_mod_level2_inst_i0_mnet); + inv4_mod_level1_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); + + inv4_mod_level2_inst_o0_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o0_mnet"); + + inv4_mod_level2_inst_o0_miterm->connect(inv4_mod_level2_inst_o0_mnet); + inv4_mod_level1_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); + + inv4_mod_level2_inst_o1_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o1_mnet"); + + inv4_mod_level2_inst_o1_miterm->connect(inv4_mod_level2_inst_o1_mnet); + inv4_mod_level1_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); + + inv4_mod_level2_inst_o2_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o2_mnet"); + + inv4_mod_level2_inst_o2_miterm->connect(inv4_mod_level2_inst_o2_mnet); + inv4_mod_level1_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); + + inv4_mod_level2_inst_o3_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o3_mnet"); + + inv4_mod_level2_inst_o3_miterm->connect(inv4_mod_level2_inst_o3_mnet); + inv4_mod_level1_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); + + std::stringstream full_design; + DbStrDebugHierarchy(block, full_design); + printf("The design created %s\n", full_design.str().c_str()); } ~F_HCONNECT() { dbDatabase::destroy(db); } @@ -479,38 +762,72 @@ struct F_HCONNECT dbLib* lib; dbBlock* block; - dbModule* root_mod; + dbModule* root_mod; + dbMTerm* root_mod_i0_mterm; + dbMTerm* root_mod_i1_mterm; + dbMTerm* root_mod_i2_mterm; + dbMTerm* root_mod_i3_mterm; + dbMTerm* root_mod_o0_mterm; + + dbBTerm* root_mod_i0_bterm; + dbBTerm* root_mod_i1_bterm; + dbBTerm* root_mod_i2_bterm; + dbBTerm* root_mod_i3_bterm; + dbBTerm* root_mod_o0_bterm; + dbModule* inv1_mod_master; + dbModInst* inv1_mod_inst; + dbModITerm* inv1_mod_inst_i0_miterm; + dbModITerm* inv1_mod_inst_o0_miterm; + dbModBTerm* inv1_mod_i0_port; + dbModBTerm* inv1_mod_o0_port; + dbModNet* inv1_mod_i0_modnet; + dbModNet* inv1_mod_o0_modnet; + dbModule* inv4_mod_level0_master; dbModule* inv4_mod_level1_master; dbModule* inv4_mod_level2_master; - - dbModBTerm* inv_mod_level0_master_i0_port; - dbModBTerm* inv_mod_level0_master_i1_port; - dbModBTerm* inv_mod_level0_master_i2_port; - dbModBTerm* inv_mod_level0_master_i3_port; - dbModBTerm* inv_mod_level0_master_o0_port; - - - dbModBTerm* inv_mod_level1_master_i0_port; - dbModBTerm* inv_mod_level1_master_i1_port; - dbModBTerm* inv_mod_level1_master_i2_port; - dbModBTerm* inv_mod_level1_master_i3_port; - dbModBTerm* inv_mod_level1_master_o0_port; - - dbModBTerm* inv_mod_level2_master_i0_port; - dbModBTerm* inv_mod_level2_master_i1_port; - dbModBTerm* inv_mod_level2_master_i2_port; - dbModBTerm* inv_mod_level2_master_i3_port; - dbModBTerm* inv_mod_level2_master_o0_port; - - - dbModInst* inv1_mod_inst; + + dbModBTerm* inv4_mod_level0_master_i0_port; + dbModBTerm* inv4_mod_level0_master_o0_port; + dbModBTerm* inv4_mod_level0_master_o1_port; + dbModBTerm* inv4_mod_level0_master_o2_port; + dbModBTerm* inv4_mod_level0_master_o3_port; + + dbModBTerm* inv4_mod_level1_master_i0_port; + dbModBTerm* inv4_mod_level1_master_o0_port; + dbModBTerm* inv4_mod_level1_master_o1_port; + dbModBTerm* inv4_mod_level1_master_o2_port; + dbModBTerm* inv4_mod_level1_master_o3_port; + + dbModBTerm* inv4_mod_level2_master_i0_port; + dbModBTerm* inv4_mod_level2_master_o0_port; + dbModBTerm* inv4_mod_level2_master_o1_port; + dbModBTerm* inv4_mod_level2_master_o2_port; + dbModBTerm* inv4_mod_level2_master_o3_port; + dbModInst* inv4_mod_level0_inst; dbModInst* inv4_mod_level1_inst; dbModInst* inv4_mod_level2_inst; - - + + dbModITerm* inv4_mod_level0_inst_i0_miterm; + dbModITerm* inv4_mod_level0_inst_o0_miterm; + dbModITerm* inv4_mod_level0_inst_o1_miterm; + dbModITerm* inv4_mod_level0_inst_o2_miterm; + dbModITerm* inv4_mod_level0_inst_o3_miterm; + + dbModITerm* inv4_mod_level1_inst_i0_miterm; + dbModITerm* inv4_mod_level1_inst_o0_miterm; + dbModITerm* inv4_mod_level1_inst_o1_miterm; + dbModITerm* inv4_mod_level1_inst_o2_miterm; + dbModITerm* inv4_mod_level1_inst_o3_miterm; + + dbModITerm* inv4_mod_level2_inst_i0_miterm; + dbModITerm* inv4_mod_level2_inst_o0_miterm; + dbModITerm* inv4_mod_level2_inst_o1_miterm; + dbModITerm* inv4_mod_level2_inst_o2_miterm; + dbModITerm* inv4_mod_level2_inst_o3_miterm; + dbInst* inv1_1; dbInst* inv4_1; dbInst* inv4_2; @@ -528,51 +845,68 @@ struct F_HCONNECT dbBTerm* op0_bterm; dbBTerm* op1_bterm; dbBTerm* op2_bterm; - dbBTerm* op3_bterm; + dbBTerm* op3_bterm; dbModITerm* inv1_1_ip; dbModITerm* inv1_1_op; + dbModNet* root_inv1_i0_mnet; + dbModNet* root_inv1_o0_mnet; + + dbModNet* root_inv4_o0_mnet; + dbModNet* root_inv4_o1_mnet; + dbModNet* root_inv4_o2_mnet; + dbModNet* root_inv4_o3_mnet; + + // first input inv4_mod_level_i0 comes from root_inv1_o0_modnet + dbModNet* inv4_mod_level0_inst_o0_mnet; + dbModNet* inv4_mod_level0_inst_o1_mnet; + dbModNet* inv4_mod_level0_inst_o2_mnet; + dbModNet* inv4_mod_level0_inst_o3_mnet; + + dbModNet* inv4_mod_level1_inst_i0_mnet; + dbModNet* inv4_mod_level1_inst_o0_mnet; + dbModNet* inv4_mod_level1_inst_o1_mnet; + dbModNet* inv4_mod_level1_inst_o2_mnet; + dbModNet* inv4_mod_level1_inst_o3_mnet; + + dbModNet* inv4_mod_level2_inst_i0_mnet; + dbModNet* inv4_mod_level2_inst_o0_mnet; + dbModNet* inv4_mod_level2_inst_o1_mnet; + dbModNet* inv4_mod_level2_inst_o2_mnet; + dbModNet* inv4_mod_level2_inst_o3_mnet; + dbITerm* inv1_1_inst_ip0; dbITerm* inv1_1_inst_op0; dbITerm* inv4_1_ip; dbITerm* inv4_2_ip; dbITerm* inv4_3_ip; - dbITerm* inv4_4_ip; + dbITerm* inv4_4_ip; dbITerm* inv4_1_op; dbITerm* inv4_2_op; dbITerm* inv4_3_op; - dbITerm* inv4_4_op; - - + dbITerm* inv4_4_op; }; - BOOST_FIXTURE_TEST_CASE(test_hier, F_HCONNECT) { auto top = block->getTopModule(); BOOST_TEST(top != nullptr); auto master1 = odb::dbModule::create(block, "master1"); - + odb::dbModInst::create(top, master1, "minst1"); - + auto master2 = odb::dbModule::create(block, "master2"); auto minst2 = odb::dbModInst::create(master1, master2, "minst2"); - - BOOST_TEST(block->findModInst("minst1/minst2") == minst2); + BOOST_TEST(block->findModInst("minst1/minst2") == minst2); } - BOOST_FIXTURE_TEST_CASE(test_hierconnect, F_HCONNECT) { - } - - - struct F_DETAILED { F_DETAILED() @@ -610,7 +944,6 @@ struct F_DETAILED dbInst* inst3; }; - BOOST_FIXTURE_TEST_CASE(test_destroy, F_DETAILED) { BOOST_TEST(block->getModInsts().size() == 3); From be7178a0a8370bcf7c67556c9342d60af055df46 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Fri, 20 Dec 2024 12:54:32 -0800 Subject: [PATCH 05/15] with call to hierconnect commented out Signed-off-by: andyfox-rushc --- src/odb/test/cpp/TestModule.cpp | 158 +++++++++++++++++++++++++++----- 1 file changed, 135 insertions(+), 23 deletions(-) diff --git a/src/odb/test/cpp/TestModule.cpp b/src/odb/test/cpp/TestModule.cpp index 36559e5e663..10e139c7994 100644 --- a/src/odb/test/cpp/TestModule.cpp +++ b/src/odb/test/cpp/TestModule.cpp @@ -3,9 +3,11 @@ #include #include + #include "helper.h" #include "odb/db.h" + namespace odb { namespace { @@ -299,24 +301,6 @@ BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) BOOST_TEST(block->findModInst("minst1/minst2") == minst2); } -/* - Test fixture for hierarchical connect test - ------------------------------------------ - - Two modules, 1 with 1 inverter, second with 4 inverters. - - inv1 is instantiated in the top level - inv4 is instantiated three levels down: - level0 -- instantiation in root - level1 - level2 -- contains 4 inverters - - Objective of this test is to stress the hierarchical connection code. - - - - - */ dbDatabase* createSimpleDBDelimiter() { @@ -335,6 +319,27 @@ dbDatabase* createSimpleDBDelimiter() return db; } +/* + Test fixture for hierarchical connect test + ------------------------------------------ + + Two modules, 1 with 1 inverter, second with 4 inverters. + + inv1 is instantiated in the top level + inv4 is instantiated three levels down: + level0 -- instantiation in root + level1 + level2 -- contains 4 inverters + + Objective of this test is to stress the hierarchical connection code. + + root {inputs: i0; outputs: o0, o1, o2,o3} + --> inv1 (module containing 1 inverter) this drives inv1_level0_inst + --> inv4_level0_inst {wrapper input: i0, outputs o0,o1,o2,o3} + --> inv4_level1_inst {wrapper input: i0, outputs o0,o1,o2,o3} + --> inv4_level2_inst {contains 4 inverters. Has input i0, outputs o0,01,o2,o3} + */ + struct F_HCONNECT { F_HCONNECT() @@ -344,6 +349,7 @@ struct F_HCONNECT block = db->getChip()->getBlock(); lib = db->findLib("lib1"); + root_mod = dbModule::create(block, "root_mod"); // The bterms are created below during wiring // Note a bterm without a parent is a root bterm. @@ -372,7 +378,9 @@ struct F_HCONNECT inv1_mod_master); inv1_1_inst_ip0 = block->findITerm("inv1_mod_inst/inst1/ip0"); inv1_1_inst_op0 = block->findITerm("inv1_mod_inst/inst1/op0"); + + inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); inv4_mod_level0_master_i0_port = dbModBTerm::create(inv4_mod_level0_master, "i0"); @@ -635,9 +643,9 @@ struct F_HCONNECT inv4_3_op->connect(op2_net); inv4_4_op->connect(op3_net); - std::stringstream str_str; - DbStrDebugHierarchy(block, str_str); - printf("The Flat design created %s\n", str_str.str().c_str()); + // std::stringstream str_str; + // DbStrDebugHierarchy(block, str_str); + // printf("The Flat design created %s\n", str_str.str().c_str()); // Now build the hierarchical "overlay" // What we are doing here is adding the modnets which hook up @@ -753,7 +761,7 @@ struct F_HCONNECT std::stringstream full_design; DbStrDebugHierarchy(block, full_design); - printf("The design created %s\n", full_design.str().c_str()); + printf("The design created (flat and hierarchical) %s\n", full_design.str().c_str()); } ~F_HCONNECT() { dbDatabase::destroy(db); } @@ -761,7 +769,7 @@ struct F_HCONNECT dbDatabase* db; dbLib* lib; dbBlock* block; - + dbModule* root_mod; dbMTerm* root_mod_i0_mterm; dbMTerm* root_mod_i1_mterm; @@ -905,6 +913,109 @@ BOOST_FIXTURE_TEST_CASE(test_hier, F_HCONNECT) BOOST_FIXTURE_TEST_CASE(test_hierconnect, F_HCONNECT) { + // + // + //Hierarchical connection test case: + //---------------------------------- + // + //add a new inverter to inv1 and connect to the fanout of the + //existing one. + //remove the driver of the 4th inverter in inv4_4 leaf + //and connect to it via hierarchy + // + // + // Before + //--inv1_1 -----------inv4_1_ip0 + // |----------inv4_2_ip0 + // |----------inv4_3_ip0 + // |----------inv4_4_ip0 + // + // + //After: + // + //--inv1_1-----------inv4_1_ip0 + // |----------inv4_2_ip0 + // |----------inv4_3_ip0 + // + //--inv1_2---------inv4_4_ip0 + // + // + // + //Objects referenced in "before" + // + //inv1_1 -- dbInst in inv1_1 + //inv1_1_inst_op0 -- op iterm on inv1 + //inv1_mod_master -- dbModule parent for inv1_1 + //inv4_mod_level2_master -- dbModule parent for leaf level inverters in inv4 + //inv4_4_ip0 -- ip iterm on 4th inverter + // + // + + std::stringstream str_str_start; + DbStrDebugHierarchy(block, str_str_start); + printf("The original design: %s\n", str_str_start.str().c_str()); + + // + //first create the new inverter in inv1_mod_master + //and get its pins ready for connection. + //Note we are declaring these new objects outside + //of the test struct so it is obvious what is in the test harness + //and what is in the test + // + dbInst* inv1_2 = dbInst::create(block, + lib->findMaster("inv2"), + "inv1_mod_inst/inst2", + false, + inv1_mod_master); + dbITerm* inv1_2_inst_ip0 = block->findITerm("inv1_mod_inst/inst2/ip0"); + dbITerm* inv1_2_inst_op0 = block->findITerm("inv1_mod_inst/inst2/op0"); + + //Plumb in the new input of the inverter + //This is the ip0_net, which is hooked to the top level bterm. + //And to the top level modnet (which connects the modbterm on + //inv1_mod_master) to the inverter. Note the dual connection: + //one flat, one hierarchical. + + inv1_2_inst_ip0 -> connect(ip0_net); //flat world + inv1_2_inst_ip0 -> connect(inv1_mod_i0_modnet); //hierarchical world + + //now disconnect the 4th inverter in inv4_4 (this is in level 2, the 3rd + //level, of the hierarchy). + //This kills both the dbNet (flat) connection + //and the dbModNet (hierarchical) connection. + + inv4_4_ip -> disconnect(); + + + // + //Make the flat connection. + //We keep two worlds: the modnet world + //and the dbNet world. The modnet world + //exists at the edges eg where a module ports + //(dbModITerms) connect to core gates (eg dbITerms). + // + //The flat world is always there. + // + // + std::string flat_net_name = inv1_2 -> getName() + inv4_4_ip -> getName('/'); + std::string hier_net_name = "test_hier_"+flat_net_name; + dbNet* flat_net = dbNet::create(block,flat_net_name.c_str(),false); + inv1_2_inst_op0 -> connect(flat_net); + inv4_4_ip -> connect(flat_net); + + // + //The hierarchical test: connect the output of the inverter in inv1_2_inst_op0 to + //the input of the inverter inv4_4_ip0; + // + + /* + ::hierarchicalConnect(inv1_2_inst_op0, + inv4_4_ip, + hier_net_name.c_str()); + */ + std::stringstream str_str_final; + DbStrDebugHierarchy(block, str_str_final); + printf("The final design: %s\n", str_str_final.str().c_str()); } struct F_DETAILED @@ -914,6 +1025,7 @@ struct F_DETAILED db = createSimpleDB(); block = db->getChip()->getBlock(); lib = db->findLib("lib1"); + master_mod1 = dbModule::create(block, "master_mod1"); master_mod2 = dbModule::create(block, "master_mod2"); master_mod3 = dbModule::create(block, "master_mod3"); From 3e9fa0816263d0e1356f251f4a09840f98f8cd4c Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Fri, 20 Dec 2024 22:18:25 -0800 Subject: [PATCH 06/15] New C++ regression test for dbSta, dbNetwork.cc bug fix in hierarchy mode Signed-off-by: andyfox-rushc --- src/dbSta/src/dbNetwork.cc | 43 +- src/dbSta/test/CMakeLists.txt | 2 + src/dbSta/test/cpp/CMakeLists.txt | 25 + src/dbSta/test/cpp/TestHconn.cpp | 975 ++++++++++++++++++++++++++++ src/dbSta/test/regression_tests.tcl | 4 + src/odb/test/cpp/TestModule.cpp | 723 --------------------- 6 files changed, 1042 insertions(+), 730 deletions(-) create mode 100644 src/dbSta/test/cpp/CMakeLists.txt create mode 100644 src/dbSta/test/cpp/TestHconn.cpp diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index 15d3157ded5..819abc562ab 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -2917,7 +2917,9 @@ void dbNetwork::getParentHierarchy(dbModule* start_module, if (cur_module == top_module) { return; } - cur_module = cur_module->getModInst()->getParent(); + cur_module = cur_module->getModInst() + ? cur_module->getModInst()->getParent() + : nullptr; } } @@ -3035,14 +3037,44 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, // in hierarchy, which is ok, and the source/dest modnet will be null dbModNet* source_db_mod_net = source_pin->getModNet(); dbModNet* dest_db_mod_net = dest_pin->getModNet(); - // case 1: source/dest in same module + + // + // make sure there is a direct flat net connection + // Recall the hierarchical connections are overlayed + // onto the flat db network, so we have both worlds + // co-existing, something we respect even when making + // new hierarchical connections. + + dbNet* source_db_net = source_pin->getNet(); + dbNet* dest_db_net = dest_pin->getNet(); + + if (!source_db_net) { + std::string connection_name_str(connection_name); + std::string flat_name = connection_name_str + "_flat"; + source_db_net = dbNet::create(block(), flat_name.c_str(), false); + source_pin->connect(source_db_net); + } + + if (dest_db_net && (dest_db_net != source_db_net)) { + // if we have dest_mod_net, keep it + dbModNet* dest_mod_net = dest_pin->getModNet(); + dest_pin->disconnect(); + dest_pin->connect(source_db_net); + if (dest_mod_net) { + dest_pin->connect(dest_mod_net); + } + } + if (source_db_module == dest_db_module) { if (!source_db_mod_net) { source_db_mod_net = dbModNet::create(source_db_module, connection_name); source_pin->connect(source_db_mod_net); } dest_pin->connect(source_db_mod_net); - } else { + } + + else { + // // Attempt to factor connection (minimize punch through) // dbModBTerm* dest_modbterm = nullptr; @@ -3148,9 +3180,7 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, } else { dest_pin->connect(top_net); } - //TODO: Clean up after everything is resolved. - //Turns out that there are intermediate states - /* + // During the addition of new ports and new wiring we may // leave orphaned pins, clean them up. std::set cleaned_up; @@ -3170,7 +3200,6 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, } } } - */ } } diff --git a/src/dbSta/test/CMakeLists.txt b/src/dbSta/test/CMakeLists.txt index 803b103e2fe..74b1f3693a6 100644 --- a/src/dbSta/test/CMakeLists.txt +++ b/src/dbSta/test/CMakeLists.txt @@ -49,3 +49,5 @@ set(TEST_NAMES foreach(TEST_NAME IN LISTS TEST_NAMES) or_integration_test("dbSta" ${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/regression) endforeach() + +add_subdirectory(cpp) diff --git a/src/dbSta/test/cpp/CMakeLists.txt b/src/dbSta/test/cpp/CMakeLists.txt new file mode 100644 index 00000000000..11a2250d29c --- /dev/null +++ b/src/dbSta/test/cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +include(openroad) + +add_executable(TestHconn TestHconn.cpp) +target_link_libraries(TestHconn + OpenSTA + GTest::gtest + GTest::gtest_main + GTest::gmock + dbSta_lib + utl_lib + ${TCL_LIBRARY} +) + +target_include_directories(TestHconn + PRIVATE + ${PROJECT_SOURCE_DIR}/src/dbSta/src +) + +gtest_discover_tests(TestHconn + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +add_dependencies(build_and_test TestHconn +) + diff --git a/src/dbSta/test/cpp/TestHconn.cpp b/src/dbSta/test/cpp/TestHconn.cpp new file mode 100644 index 00000000000..2dbecd47c2c --- /dev/null +++ b/src/dbSta/test/cpp/TestHconn.cpp @@ -0,0 +1,975 @@ +// Copyright 2023 Google LLC +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "db_sta/MakeDbSta.hh" +#include "db_sta/dbNetwork.hh" +#include "db_sta/dbSta.hh" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "odb/lefin.h" +#include "sta/Corner.hh" +#include "sta/FuncExpr.hh" +#include "sta/Graph.hh" +#include "sta/Liberty.hh" +#include "sta/PathAnalysisPt.hh" +#include "sta/Search.hh" +#include "sta/Sta.hh" +#include "sta/Units.hh" +#include "utl/Logger.h" +#include "utl/deleter.h" + +namespace odb { + +std::once_flag init_sta_flag; + +/* + Extract the hierarchical information in human readable format. + Shows the dbNet and dbModNet view of the database. +*/ + +void DbStrDebugHierarchy(dbBlock* block, std::stringstream& str_db) +{ + char tmp_str[10000]; + sprintf(tmp_str, + "Debug: Data base tables for block at %s:\n", + block->getName().c_str()); + str_db << tmp_str; + + sprintf(tmp_str, "Db nets (The Flat db view)\n"); + str_db << tmp_str; + + for (auto dbnet : block->getNets()) { + sprintf(tmp_str, + "dbnet %s (id %u)\n", + dbnet->getName().c_str(), + dbnet->getId()); + str_db << tmp_str; + + for (auto db_iterm : dbnet->getITerms()) { + sprintf(tmp_str, + "\t-> Db Iterm %u (%s)\n", + db_iterm->getId(), + db_iterm->getName().c_str()); + str_db << tmp_str; + } + for (auto db_bterm : dbnet->getBTerms()) { + sprintf(tmp_str, "\t-> Db Bterm %u\n", db_bterm->getId()); + str_db << tmp_str; + } + } + + sprintf(tmp_str, "Block ports\n"); + // got through the ports and their owner + sprintf(tmp_str, "\t\tBTerm Ports +++\n"); + str_db << tmp_str; + dbSet block_bterms = block->getBTerms(); + for (auto bt : block_bterms) { + sprintf(tmp_str, + "\t\tBterm (%u) %s Net %s (%u) Mod Net %s (%u) \n", + bt->getId(), + bt->getName().c_str(), + bt->getNet() ? bt->getNet()->getName().c_str() : "", + bt->getNet() ? bt->getNet()->getId() : 0, + bt->getModNet() ? bt->getModNet()->getName() : "", + bt->getModNet() ? bt->getModNet()->getId() : 0); + str_db << tmp_str; + } + sprintf(tmp_str, "\t\tBTerm Ports ---\n"); + str_db << tmp_str; + + sprintf(tmp_str, "The hierarchical db view:\n"); + str_db << tmp_str; + dbSet block_modules = block->getModules(); + sprintf(tmp_str, "Content size %u modules\n", block_modules.size()); + str_db << tmp_str; + for (auto mi : block_modules) { + dbModule* cur_obj = mi; + if (cur_obj == block->getTopModule()) { + sprintf(tmp_str, "Top Module\n"); + str_db << tmp_str; + } + sprintf(tmp_str, + "\tModule %s %s\n", + (cur_obj == block->getTopModule()) ? "(Top Module)" : "", + ((dbModule*) cur_obj)->getName()); + str_db << tmp_str; + // in case of top level, care as the bterms double up as pins + if (cur_obj == block->getTopModule()) { + for (auto bterm : block->getBTerms()) { + sprintf(tmp_str, + "Top B-term %s dbNet %s (%d) modNet %s (%d)\n", + bterm->getName().c_str(), + bterm->getNet() ? bterm->getNet()->getName().c_str() : "", + bterm->getNet() ? bterm->getNet()->getId() : -1, + bterm->getModNet() ? bterm->getModNet()->getName() : "", + bterm->getModNet() ? bterm->getModNet()->getId() : -1); + str_db << tmp_str; + } + } + // got through the module ports and their owner + sprintf(tmp_str, "\t\tModBTerm Ports +++\n"); + str_db << tmp_str; + + dbSet module_ports = cur_obj->getModBTerms(); + for (dbSet::iterator mod_bterm_iter = module_ports.begin(); + mod_bterm_iter != module_ports.end(); + mod_bterm_iter++) { + dbModBTerm* module_port = *mod_bterm_iter; + sprintf( + tmp_str, + "\t\tPort %s Net %s (%d)\n", + module_port->getName(), + (module_port->getModNet()) ? (module_port->getModNet()->getName()) + : "No-modnet", + (module_port->getModNet()) ? module_port->getModNet()->getId() : -1); + str_db << tmp_str; + sprintf(tmp_str, + "\t\tPort parent %s\n\n", + module_port->getParent()->getName()); + str_db << tmp_str; + } + sprintf(tmp_str, "\t\tModBTermPorts ---\n"); + str_db << tmp_str; + + sprintf(tmp_str, "\t\tModule instances +++\n"); + str_db << tmp_str; + dbSet module_instances = mi->getModInsts(); + for (dbSet::iterator mod_inst_iter = module_instances.begin(); + mod_inst_iter != module_instances.end(); + mod_inst_iter++) { + dbModInst* module_inst = *mod_inst_iter; + sprintf(tmp_str, "\t\tMod inst %s ", module_inst->getName()); + str_db << tmp_str; + dbModule* master = module_inst->getMaster(); + sprintf( + tmp_str, "\t\tMaster %s\n\n", module_inst->getMaster()->getName()); + str_db << tmp_str; + dbBlock* owner = master->getOwner(); + if (owner != block) { + sprintf(tmp_str, "\t\t\tMaster owner in wrong block\n"); + str_db << tmp_str; + } + sprintf(tmp_str, "\t\tConnections\n"); + str_db << tmp_str; + for (dbModITerm* miterm_pin : module_inst->getModITerms()) { + sprintf(tmp_str, + "\t\t\tModIterm : %s (%u) Mod Net %s (%u) \n", + miterm_pin->getName(), + miterm_pin->getId(), + miterm_pin->getModNet() ? (miterm_pin->getModNet()->getName()) + : "No-net", + miterm_pin->getModNet() ? miterm_pin->getModNet()->getId() : 0); + str_db << tmp_str; + } + } + sprintf(tmp_str, "\t\tModule instances ---\n"); + str_db << tmp_str; + sprintf(tmp_str, "\t\tDb instances +++\n"); + str_db << tmp_str; + for (dbInst* db_inst : cur_obj->getInsts()) { + sprintf(tmp_str, "\t\tdb inst %s\n", db_inst->getName().c_str()); + str_db << tmp_str; + sprintf(tmp_str, "\t\tdb iterms:\n"); + str_db << tmp_str; + dbSet iterms = db_inst->getITerms(); + dbSet::iterator iterm_itr; + for (iterm_itr = iterms.begin(); iterm_itr != iterms.end(); ++iterm_itr) { + dbITerm* iterm = *iterm_itr; + dbMTerm* mterm = iterm->getMTerm(); + sprintf( + tmp_str, + "\t\t\t\t iterm: %s (%u) Net: %s Mod net : %s (%d)\n", + mterm->getName().c_str(), + iterm->getId(), + iterm->getNet() ? iterm->getNet()->getName().c_str() : "unk-dbnet", + iterm->getModNet() ? iterm->getModNet()->getName() : "unk-modnet", + iterm->getModNet() ? iterm->getModNet()->getId() : -1); + str_db << tmp_str; + } + } + sprintf(tmp_str, "\t\tDb instances ---\n"); + str_db << tmp_str; + sprintf(tmp_str, "\tModule nets (modnets) +++ \n"); + str_db << tmp_str; + sprintf(tmp_str, + "\t# mod nets %u in %s \n", + cur_obj->getModNets().size(), + cur_obj->getName()); + + str_db << tmp_str; + dbSet mod_nets = cur_obj->getModNets(); + for (dbSet::iterator mod_net_iter = mod_nets.begin(); + mod_net_iter != mod_nets.end(); + mod_net_iter++) { + dbModNet* mod_net = *mod_net_iter; + sprintf( + tmp_str, "\t\tNet: %s (%u)\n", mod_net->getName(), mod_net->getId()); + str_db << tmp_str; + sprintf(tmp_str, + "\t\tConnections -> modIterms/modbterms/bterms/iterms:\n"); + str_db << tmp_str; + sprintf( + tmp_str, "\t\t -> %u moditerms\n", mod_net->getModITerms().size()); + str_db << tmp_str; + for (dbModITerm* modi_term : mod_net->getModITerms()) { + sprintf(tmp_str, "\t\t\t%s\n", modi_term->getName()); + str_db << tmp_str; + } + sprintf( + tmp_str, "\t\t -> %u modbterms\n", mod_net->getModBTerms().size()); + str_db << tmp_str; + for (dbModBTerm* modb_term : mod_net->getModBTerms()) { + sprintf(tmp_str, "\t\t\t%s\n", modb_term->getName()); + str_db << tmp_str; + } + sprintf(tmp_str, "\t\t -> %u iterms\n", mod_net->getITerms().size()); + str_db << tmp_str; + for (dbITerm* db_iterm : mod_net->getITerms()) { + sprintf(tmp_str, "\t\t\t%s\n", db_iterm->getName().c_str()); + str_db << tmp_str; + } + sprintf(tmp_str, "\t\t -> %u bterms\n", mod_net->getBTerms().size()); + str_db << tmp_str; + for (dbBTerm* db_bterm : mod_net->getBTerms()) { + sprintf(tmp_str, "\t\t\t%s\n", db_bterm->getName().c_str()); + str_db << tmp_str; + } + } + } +} + +/* + Test fixture for hierarchical connect test + ------------------------------------------ + + Two modules, 1 with 1 inverter, second with 4 inverters. + + inv1 is instantiated in the top level + inv4 is instantiated three levels down: + level0 -- instantiation in root + level1 + level2 -- contains 4 inverters + + Objective of this test is to stress the hierarchical connection code. + + root {inputs: i0; outputs: o0, o1, o2,o3} + --> inv1 (module containing 1 inverter) this drives inv1_level0_inst + --> inv4_level0_inst {wrapper input: i0, outputs o0,o1,o2,o3} + --> inv4_level1_inst {wrapper input: i0, outputs o0,o1,o2,o3} + --> inv4_level2_inst {contains 4 inverters. Has input i0, outputs + o0,01,o2,o3} +*/ + +class TestHconn : public ::testing::Test +{ + protected: + void SetUp() override + { + // this will be so much easier with read_def + db_ = utl::UniquePtrWithDeleter(odb::dbDatabase::create(), + &odb::dbDatabase::destroy); + std::call_once(init_sta_flag, []() { sta::initSta(); }); + sta_ = std::unique_ptr(ord::makeDbSta()); + sta_->initVars(Tcl_CreateInterp(), db_.get(), &logger_); + auto path = std::filesystem::canonical("./Nangate45/Nangate45_typ.lib"); + library_ = sta_->readLiberty(path.string().c_str(), + sta_->findCorner("default"), + sta::MinMaxAll::all(), + /*infer_latches=*/false); + odb::lefin lefParser( + db_.get(), &logger_, /*ignore_non_routing_layers*/ false); + const char* libName = "Nangate45.lef"; + lib = lefParser.createTechAndLib( + "tech", libName, "./Nangate45/Nangate45.lef"); + + sta_->postReadLef(/*tech=*/nullptr, lib); + + sta::Units* units = library_->units(); + power_unit_ = units->powerUnit(); + db_network_ = sta_->getDbNetwork(); + db_->setLogger(&logger_); + + // create a chain consisting of 4 buffers + odb::dbChip* chip = odb::dbChip::create(db_.get()); + block = odb::dbBlock::create(chip, "top"); + db_network_->setBlock(block); + block->setDieArea(odb::Rect(0, 0, 1000, 1000)); + // register proper callbacks for timer like read_def + sta_->postReadDef(block); + + root_mod = dbModule::create(block, "root_mod"); + // The bterms are created below during wiring + // Note a bterm without a parent is a root bterm. + + // Make the inv1 module (contains 1 inverter). + inv1_mod_master = dbModule::create(block, "inv1_master_mod"); + inv1_mod_i0_port = dbModBTerm::create(inv1_mod_master, "i0"); + inv1_mod_o0_port = dbModBTerm::create(inv1_mod_master, "o0"); + + inv1_mod_inst + = dbModInst::create(root_mod, inv1_mod_master, "inv1_mod_inst"); + + inv1_mod_inst_i0_miterm = dbModITerm::create(inv1_mod_inst, "i0"); + inv1_mod_inst_o0_miterm = dbModITerm::create(inv1_mod_inst, "o0"); + // correlate the iterms and bterms + inv1_mod_inst_i0_miterm->setChildModBTerm(inv1_mod_i0_port); + inv1_mod_i0_port->setParentModITerm(inv1_mod_inst_i0_miterm); + + inv1_mod_inst_o0_miterm->setChildModBTerm(inv1_mod_o0_port); + inv1_mod_o0_port->setParentModITerm(inv1_mod_inst_o0_miterm); + + inv1_1 = dbInst::create(block, + lib->findMaster("INV_X1"), + "inv1_mod_inst/inst1", + false, + inv1_mod_master); + + inv1_1_inst_ip0 = inv1_1->findITerm("A"); + inv1_1_inst_op0 = inv1_1->findITerm("ZN"); + + inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); + inv4_mod_level0_master_i0_port + = dbModBTerm::create(inv4_mod_level0_master, "i0"); + inv4_mod_level0_master_o0_port + = dbModBTerm::create(inv4_mod_level0_master, "o0"); + inv4_mod_level0_master_o1_port + = dbModBTerm::create(inv4_mod_level0_master, "o1"); + inv4_mod_level0_master_o2_port + = dbModBTerm::create(inv4_mod_level0_master, "o2"); + inv4_mod_level0_master_o3_port + = dbModBTerm::create(inv4_mod_level0_master, "o3"); + + inv4_mod_level1_master = dbModule::create(block, "inv4_master_level1"); + inv4_mod_level1_master_i0_port + = dbModBTerm::create(inv4_mod_level1_master, "i0"); + inv4_mod_level1_master_o0_port + = dbModBTerm::create(inv4_mod_level1_master, "o0"); + inv4_mod_level1_master_o1_port + = dbModBTerm::create(inv4_mod_level1_master, "o1"); + inv4_mod_level1_master_o2_port + = dbModBTerm::create(inv4_mod_level1_master, "o2"); + inv4_mod_level1_master_o3_port + = dbModBTerm::create(inv4_mod_level1_master, "o3"); + + inv4_mod_level2_master = dbModule::create(block, "inv4_master_level2"); + inv4_mod_level2_master_i0_port + = dbModBTerm::create(inv4_mod_level2_master, "i0"); + inv4_mod_level2_master_o0_port + = dbModBTerm::create(inv4_mod_level2_master, "o0"); + inv4_mod_level2_master_o1_port + = dbModBTerm::create(inv4_mod_level2_master, "o1"); + inv4_mod_level2_master_o2_port + = dbModBTerm::create(inv4_mod_level2_master, "o2"); + inv4_mod_level2_master_o3_port + = dbModBTerm::create(inv4_mod_level2_master, "o3"); + + // During modinst creation we set the parent. + inv4_mod_level0_inst = dbModInst::create(root_mod, // parent + inv4_mod_level0_master, + "inv4_mod_level0_inst"); + inv4_mod_level0_inst_i0_miterm + = dbModITerm::create(inv4_mod_level0_inst, "i0"); + inv4_mod_level0_inst_i0_miterm->setChildModBTerm( + inv4_mod_level0_master_i0_port); + inv4_mod_level0_master_i0_port->setParentModITerm( + inv4_mod_level0_inst_i0_miterm); + + inv4_mod_level0_inst_o0_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o0"); + inv4_mod_level0_inst_o0_miterm->setChildModBTerm( + inv4_mod_level0_master_o0_port); + inv4_mod_level0_master_o0_port->setParentModITerm( + inv4_mod_level0_inst_o0_miterm); + + inv4_mod_level0_inst_o1_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o1"); + inv4_mod_level0_inst_o1_miterm->setChildModBTerm( + inv4_mod_level0_master_o1_port); + inv4_mod_level0_master_o1_port->setParentModITerm( + inv4_mod_level0_inst_o1_miterm); + + inv4_mod_level0_inst_o2_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o2"); + inv4_mod_level0_inst_o2_miterm->setChildModBTerm( + inv4_mod_level0_master_o2_port); + inv4_mod_level0_master_o2_port->setParentModITerm( + inv4_mod_level0_inst_o2_miterm); + + inv4_mod_level0_inst_o3_miterm + = dbModITerm::create(inv4_mod_level0_inst, "o3"); + inv4_mod_level0_inst_o3_miterm->setChildModBTerm( + inv4_mod_level0_master_o3_port); + inv4_mod_level0_master_o3_port->setParentModITerm( + inv4_mod_level0_inst_o3_miterm); + + inv4_mod_level1_inst = dbModInst::create(inv4_mod_level0_master, // parent + inv4_mod_level1_master, + "inv4_mod_level1_inst"); + + inv4_mod_level1_inst_i0_miterm + = dbModITerm::create(inv4_mod_level1_inst, "i0"); + inv4_mod_level1_inst_i0_miterm->setChildModBTerm( + inv4_mod_level1_master_i0_port); + inv4_mod_level1_master_i0_port->setParentModITerm( + inv4_mod_level1_inst_i0_miterm); + + inv4_mod_level1_inst_o0_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o0"); + inv4_mod_level1_inst_o0_miterm->setChildModBTerm( + inv4_mod_level1_master_o0_port); + inv4_mod_level1_master_o0_port->setParentModITerm( + inv4_mod_level1_inst_o0_miterm); + + inv4_mod_level1_inst_o1_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o1"); + inv4_mod_level1_inst_o1_miterm->setChildModBTerm( + inv4_mod_level1_master_o1_port); + inv4_mod_level1_master_o1_port->setParentModITerm( + inv4_mod_level1_inst_o1_miterm); + + inv4_mod_level1_inst_o2_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o2"); + inv4_mod_level1_inst_o2_miterm->setChildModBTerm( + inv4_mod_level1_master_o2_port); + inv4_mod_level1_master_o2_port->setParentModITerm( + inv4_mod_level1_inst_o2_miterm); + + inv4_mod_level1_inst_o3_miterm + = dbModITerm::create(inv4_mod_level1_inst, "o3"); + inv4_mod_level1_inst_o3_miterm->setChildModBTerm( + inv4_mod_level1_master_o3_port); + inv4_mod_level1_master_o3_port->setParentModITerm( + inv4_mod_level1_inst_o3_miterm); + + inv4_mod_level2_inst = dbModInst::create(inv4_mod_level1_master, // parent + inv4_mod_level2_master, + "inv4_mod_level2_inst"); + + inv4_mod_level2_inst_i0_miterm + = dbModITerm::create(inv4_mod_level2_inst, "i0"); + inv4_mod_level2_inst_i0_miterm->setChildModBTerm( + inv4_mod_level2_master_i0_port); + inv4_mod_level2_master_i0_port->setParentModITerm( + inv4_mod_level2_inst_i0_miterm); + + inv4_mod_level2_inst_o0_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o0"); + inv4_mod_level2_inst_o0_miterm->setChildModBTerm( + inv4_mod_level2_master_o0_port); + inv4_mod_level2_master_o0_port->setParentModITerm( + inv4_mod_level2_inst_o0_miterm); + + inv4_mod_level2_inst_o1_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o1"); + inv4_mod_level2_inst_o1_miterm->setChildModBTerm( + inv4_mod_level2_master_o1_port); + inv4_mod_level2_master_o1_port->setParentModITerm( + inv4_mod_level2_inst_o1_miterm); + + inv4_mod_level2_inst_o2_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o2"); + inv4_mod_level2_inst_o2_miterm->setChildModBTerm( + inv4_mod_level2_master_o2_port); + inv4_mod_level2_master_o2_port->setParentModITerm( + inv4_mod_level2_inst_o2_miterm); + + inv4_mod_level2_inst_o3_miterm + = dbModITerm::create(inv4_mod_level2_inst, "o3"); + inv4_mod_level2_inst_o3_miterm->setChildModBTerm( + inv4_mod_level2_master_o3_port); + inv4_mod_level2_master_o3_port->setParentModITerm( + inv4_mod_level2_inst_o3_miterm); + + // + // create the low level inverter instances, for now uniquely name them in + // the scope of a block. + + inv4_1 = dbInst::create( + block, + lib->findMaster("INV_X1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst1"); + + // get the iterm off the instance. Just give the terminal name + // offset used to find iterm. + inv4_1_ip = inv4_1->findITerm("A"); + inv4_1_op = inv4_1->findITerm("ZN"); + + inv4_2 = dbInst::create( + block, + lib->findMaster("INV_X1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst2"); + inv4_2_ip = inv4_2->findITerm("A"); + inv4_2_op = inv4_2->findITerm("ZN"); + + inv4_3 = dbInst::create( + block, + lib->findMaster("INV_X1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst3"); + inv4_3_ip = inv4_3->findITerm("A"); + inv4_3_op = inv4_3->findITerm("ZN"); + + inv4_4 = dbInst::create( + block, + lib->findMaster("INV_X1"), + "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst4"); + inv4_4_ip = inv4_4->findITerm("A"); + inv4_4_op = inv4_4->findITerm("ZN"); + + // + // inv4_mod_level2_master is lowest level in hierarchy + // + inv4_mod_level2_master->addInst(inv4_1); + inv4_mod_level2_master->addInst(inv4_2); + inv4_mod_level2_master->addInst(inv4_3); + inv4_mod_level2_master->addInst(inv4_4); + + inv4_mod_level2_inst_i0_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_i0_mnet"); + inv4_mod_level2_inst_o0_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o0_mnet"); + inv4_mod_level2_inst_o1_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o1_mnet"); + inv4_mod_level2_inst_o2_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o2_mnet"); + inv4_mod_level2_inst_o3_mnet = dbModNet::create( + inv4_mod_level2_master, "inv4_mod_level2_inst_o3_mnet"); + inv4_1_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_2_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_3_ip->connect(inv4_mod_level2_inst_i0_mnet); + inv4_4_ip->connect(inv4_mod_level2_inst_i0_mnet); + + inv4_1_op->connect(inv4_mod_level2_inst_o0_mnet); + inv4_2_op->connect(inv4_mod_level2_inst_o1_mnet); + inv4_3_op->connect(inv4_mod_level2_inst_o2_mnet); + inv4_4_op->connect(inv4_mod_level2_inst_o3_mnet); + + inv4_mod_level2_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); + inv4_mod_level2_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); + inv4_mod_level2_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); + inv4_mod_level2_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); + inv4_mod_level2_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); + + // First make the flat view connectivity + ip0_net = dbNet::create(block, "ip0_flat_net", false); + inv_op_net = dbNet::create(block, "inv_op_flat_net", false); + op0_net = dbNet::create(block, "op0_flat_net", false); + op1_net = dbNet::create(block, "op1_flat_net", false); + op2_net = dbNet::create(block, "op2_flat_net", false); + op3_net = dbNet::create(block, "op3_flat_net", false); + + // + // connections to the primary (root) ports + // Note: a bterm without a parent is a root port. + // + ip0_bterm = dbBTerm::create(ip0_net, "ip0"); + op0_bterm = dbBTerm::create(op0_net, "op0"); + op1_bterm = dbBTerm::create(op1_net, "op1"); + op2_bterm = dbBTerm::create(op2_net, "op2"); + op3_bterm = dbBTerm::create(op3_net, "op3"); + + op0_bterm->connect(inv4_mod_level2_inst_o0_mnet); + op1_bterm->connect(inv4_mod_level2_inst_o1_mnet); + op2_bterm->connect(inv4_mod_level2_inst_o2_mnet); + op3_bterm->connect(inv4_mod_level2_inst_o3_mnet); + + // flat connections: + // inverter 1 in module inv1_1 + inv1_1_inst_ip0->connect(ip0_net); + inv1_1_inst_op0->connect(inv_op_net); + + // now the 4 inverters in inv4_1 + inv4_1_ip->connect(inv_op_net); + inv4_2_ip->connect(inv_op_net); + inv4_3_ip->connect(inv_op_net); + inv4_4_ip->connect(inv_op_net); + + // now core to external connections + inv4_1_op->connect(op0_net); + inv4_2_op->connect(op1_net); + inv4_3_op->connect(op2_net); + inv4_4_op->connect(op3_net); + + // std::stringstream str_str; + // DbStrDebugHierarchy(block, str_str); + // printf("The Flat design created %s\n", str_str.str().c_str()); + + // Now build the hierarchical "overlay" + // What we are doing here is adding the modnets which hook up + + // wire in hierarchy for inv1 + + // Contents of inv1 (modnets from ports to internals). + inv1_mod_i0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_i0_mnet"); + inv1_mod_o0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_o0_mnet"); + // connection from port to net in module + inv1_mod_i0_port->connect(inv1_mod_i0_modnet); + // connection to inverter ip + inv1_1_inst_ip0->connect(inv1_mod_i0_modnet); + // from inverter op to port + inv1_1_inst_op0->connect(inv1_mod_o0_modnet); + inv1_mod_o0_port->connect(inv1_mod_o0_modnet); + + // Instantiation of inv1 connections to top level (root bterms to modnets, + // modnets to moditerms on inv1). + root_inv1_i0_mnet = dbModNet::create(root_mod, "inv1_inst_i0_mnet"); + root_inv1_o0_mnet = dbModNet::create(root_mod, "inv1_inst_o0_mnet"); + inv1_mod_inst_i0_miterm->connect(root_inv1_i0_mnet); + inv1_mod_inst_o0_miterm->connect(root_inv1_o0_mnet); + + // top level connections for inv1. + // root input to instance, via a modnet. + ip0_bterm->connect(root_inv1_i0_mnet); + // note the output from out inverter module is inv1_inst_o0_mnet + // which now needs to be hooked up the inv4 hierarchy. + + // The inv4 hierarchy connections + // inv1 -> inv4 connection + inv4_mod_level0_inst_i0_miterm->connect(root_inv1_o0_mnet); + + // level 0 is top of hierarchy, in root + // the level 0 instance -> root connections + root_inv4_o0_mnet = dbModNet::create(root_mod, "inv4_inst_o0_mnet"); + inv4_mod_level0_inst_o0_miterm->connect(root_inv4_o0_mnet); + op0_bterm->connect(root_inv4_o0_mnet); + + root_inv4_o1_mnet = dbModNet::create(root_mod, "inv4_inst_o1_mnet"); + inv4_mod_level0_inst_o1_miterm->connect(root_inv4_o1_mnet); + op1_bterm->connect(root_inv4_o1_mnet); + + root_inv4_o2_mnet = dbModNet::create(root_mod, "inv4_inst_o2_mnet"); + inv4_mod_level0_inst_o2_miterm->connect(root_inv4_o2_mnet); + op2_bterm->connect(root_inv4_o2_mnet); + + root_inv4_o3_mnet = dbModNet::create(root_mod, "inv4_inst_o3_mnet"); + inv4_mod_level0_inst_o3_miterm->connect(root_inv4_o3_mnet); + op3_bterm->connect(root_inv4_o3_mnet); + + // level 1 is next level down + // The level 1 instance connections within the scope of the + // inv4_mod_level0_master + inv4_mod_level1_inst_i0_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_i0_mnet"); + + inv4_mod_level1_inst_i0_miterm->connect(inv4_mod_level1_inst_i0_mnet); + inv4_mod_level0_master_i0_port->connect(inv4_mod_level1_inst_i0_mnet); + + inv4_mod_level1_inst_o0_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); + inv4_mod_level1_inst_o0_miterm->connect(inv4_mod_level1_inst_o0_mnet); + inv4_mod_level0_master_o0_port->connect(inv4_mod_level1_inst_o0_mnet); + + inv4_mod_level1_inst_o1_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); + inv4_mod_level1_inst_o1_miterm->connect(inv4_mod_level1_inst_o1_mnet); + inv4_mod_level0_master_o1_port->connect(inv4_mod_level1_inst_o1_mnet); + + inv4_mod_level1_inst_o2_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o2_mnet"); + inv4_mod_level1_inst_o2_miterm->connect(inv4_mod_level1_inst_o2_mnet); + inv4_mod_level0_master_o2_port->connect(inv4_mod_level1_inst_o2_mnet); + + inv4_mod_level1_inst_o3_mnet = dbModNet::create( + inv4_mod_level0_master, "inv4_mod_level1_inst_o3_mnet"); + inv4_mod_level1_inst_o3_miterm->connect(inv4_mod_level1_inst_o3_mnet); + inv4_mod_level0_master_o3_port->connect(inv4_mod_level1_inst_o3_mnet); + + // The level 2 instance connections within the scope of the + // inv4_mod_level1_master level 2 is the cell which contains the 4 inverters + inv4_mod_level2_inst_i0_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_i0_mnet"); + + inv4_mod_level2_inst_i0_miterm->connect(inv4_mod_level2_inst_i0_mnet); + inv4_mod_level1_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); + + inv4_mod_level2_inst_o0_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o0_mnet"); + + inv4_mod_level2_inst_o0_miterm->connect(inv4_mod_level2_inst_o0_mnet); + inv4_mod_level1_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); + + inv4_mod_level2_inst_o1_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o1_mnet"); + + inv4_mod_level2_inst_o1_miterm->connect(inv4_mod_level2_inst_o1_mnet); + inv4_mod_level1_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); + + inv4_mod_level2_inst_o2_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o2_mnet"); + + inv4_mod_level2_inst_o2_miterm->connect(inv4_mod_level2_inst_o2_mnet); + inv4_mod_level1_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); + + inv4_mod_level2_inst_o3_mnet = dbModNet::create( + inv4_mod_level1_master, "inv4_mod_level2_inst_o3_mnet"); + + inv4_mod_level2_inst_o3_miterm->connect(inv4_mod_level2_inst_o3_mnet); + inv4_mod_level1_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); + + // std::stringstream full_design; + // DbStrDebugHierarchy(block, full_design); + // printf("The design created (flat and hierarchical) %s\n", + // full_design.str().c_str()); + } + + utl::UniquePtrWithDeleter db_; + sta::Unit* power_unit_; + std::unique_ptr sta_; + sta::LibertyLibrary* library_; + + utl::Logger logger_; + sta::dbNetwork* db_network_; + + dbBlock* block; + odb::dbLib* lib; + + dbModule* root_mod; + dbMTerm* root_mod_i0_mterm; + dbMTerm* root_mod_i1_mterm; + dbMTerm* root_mod_i2_mterm; + dbMTerm* root_mod_i3_mterm; + dbMTerm* root_mod_o0_mterm; + + dbBTerm* root_mod_i0_bterm; + dbBTerm* root_mod_i1_bterm; + dbBTerm* root_mod_i2_bterm; + dbBTerm* root_mod_i3_bterm; + dbBTerm* root_mod_o0_bterm; + + dbModule* inv1_mod_master; + dbModInst* inv1_mod_inst; + dbModITerm* inv1_mod_inst_i0_miterm; + dbModITerm* inv1_mod_inst_o0_miterm; + dbModBTerm* inv1_mod_i0_port; + dbModBTerm* inv1_mod_o0_port; + dbModNet* inv1_mod_i0_modnet; + dbModNet* inv1_mod_o0_modnet; + + dbModule* inv4_mod_level0_master; + dbModule* inv4_mod_level1_master; + dbModule* inv4_mod_level2_master; + + dbModBTerm* inv4_mod_level0_master_i0_port; + dbModBTerm* inv4_mod_level0_master_o0_port; + dbModBTerm* inv4_mod_level0_master_o1_port; + dbModBTerm* inv4_mod_level0_master_o2_port; + dbModBTerm* inv4_mod_level0_master_o3_port; + + dbModBTerm* inv4_mod_level1_master_i0_port; + dbModBTerm* inv4_mod_level1_master_o0_port; + dbModBTerm* inv4_mod_level1_master_o1_port; + dbModBTerm* inv4_mod_level1_master_o2_port; + dbModBTerm* inv4_mod_level1_master_o3_port; + + dbModBTerm* inv4_mod_level2_master_i0_port; + dbModBTerm* inv4_mod_level2_master_o0_port; + dbModBTerm* inv4_mod_level2_master_o1_port; + dbModBTerm* inv4_mod_level2_master_o2_port; + dbModBTerm* inv4_mod_level2_master_o3_port; + + dbModInst* inv4_mod_level0_inst; + dbModInst* inv4_mod_level1_inst; + dbModInst* inv4_mod_level2_inst; + + dbModITerm* inv4_mod_level0_inst_i0_miterm; + dbModITerm* inv4_mod_level0_inst_o0_miterm; + dbModITerm* inv4_mod_level0_inst_o1_miterm; + dbModITerm* inv4_mod_level0_inst_o2_miterm; + dbModITerm* inv4_mod_level0_inst_o3_miterm; + + dbModITerm* inv4_mod_level1_inst_i0_miterm; + dbModITerm* inv4_mod_level1_inst_o0_miterm; + dbModITerm* inv4_mod_level1_inst_o1_miterm; + dbModITerm* inv4_mod_level1_inst_o2_miterm; + dbModITerm* inv4_mod_level1_inst_o3_miterm; + + dbModITerm* inv4_mod_level2_inst_i0_miterm; + dbModITerm* inv4_mod_level2_inst_o0_miterm; + dbModITerm* inv4_mod_level2_inst_o1_miterm; + dbModITerm* inv4_mod_level2_inst_o2_miterm; + dbModITerm* inv4_mod_level2_inst_o3_miterm; + + dbInst* inv1_1; + dbInst* inv4_1; + dbInst* inv4_2; + dbInst* inv4_3; + dbInst* inv4_4; + + dbNet* ip0_net; + dbNet* inv_op_net; + dbNet* op0_net; + dbNet* op1_net; + dbNet* op2_net; + dbNet* op3_net; + + dbBTerm* ip0_bterm; + dbBTerm* op0_bterm; + dbBTerm* op1_bterm; + dbBTerm* op2_bterm; + dbBTerm* op3_bterm; + + dbModITerm* inv1_1_ip; + dbModITerm* inv1_1_op; + + dbModNet* root_inv1_i0_mnet; + dbModNet* root_inv1_o0_mnet; + + dbModNet* root_inv4_o0_mnet; + dbModNet* root_inv4_o1_mnet; + dbModNet* root_inv4_o2_mnet; + dbModNet* root_inv4_o3_mnet; + + // first input inv4_mod_level_i0 comes from root_inv1_o0_modnet + dbModNet* inv4_mod_level0_inst_o0_mnet; + dbModNet* inv4_mod_level0_inst_o1_mnet; + dbModNet* inv4_mod_level0_inst_o2_mnet; + dbModNet* inv4_mod_level0_inst_o3_mnet; + + dbModNet* inv4_mod_level1_inst_i0_mnet; + dbModNet* inv4_mod_level1_inst_o0_mnet; + dbModNet* inv4_mod_level1_inst_o1_mnet; + dbModNet* inv4_mod_level1_inst_o2_mnet; + dbModNet* inv4_mod_level1_inst_o3_mnet; + + dbModNet* inv4_mod_level2_inst_i0_mnet; + dbModNet* inv4_mod_level2_inst_o0_mnet; + dbModNet* inv4_mod_level2_inst_o1_mnet; + dbModNet* inv4_mod_level2_inst_o2_mnet; + dbModNet* inv4_mod_level2_inst_o3_mnet; + + dbITerm* inv1_1_inst_ip0; + dbITerm* inv1_1_inst_op0; + + dbITerm* inv4_1_ip; + dbITerm* inv4_2_ip; + dbITerm* inv4_3_ip; + dbITerm* inv4_4_ip; + dbITerm* inv4_1_op; + dbITerm* inv4_2_op; + dbITerm* inv4_3_op; + dbITerm* inv4_4_op; +}; + +TEST_F(TestHconn, ConnectionMade) +{ + // std::stringstream str_str_initial; + // DbStrDebugHierarchy(block, str_str_initial); + // printf("The initial design: %s\n", str_str_initial.str().c_str()); + + // + // + // Hierarchical connection test case: + //---------------------------------- + // + // add a new inverter to inv1 and connect to the fanout of the + // existing one. + // remove the driver of the 4th inverter in inv4_4 leaf + // and connect to it via hierarchy + // + // + // Before + //--inv1_1 -----------inv4_1_ip0 + // |----------inv4_2_ip0 + // |----------inv4_3_ip0 + // |----------inv4_4_ip0 + // + // + // After: + // + //--inv1_1-----------inv4_1_ip0 + // |----------inv4_2_ip0 + // |----------inv4_3_ip0 + // + //--inv1_2---------inv4_4_ip0 + // + // + // + // Objects referenced in "before" + // + // inv1_1 -- dbInst in inv1_1 + // inv1_1_inst_op0 -- op iterm on inv1 + // inv1_mod_master -- dbModule parent for inv1_1 + // inv4_mod_level2_master -- dbModule parent for leaf level inverters in inv4 + // inv4_4_ip0 -- ip iterm on 4th inverter + // + // + + size_t initial_count = block->getModNets().size(); + + // + // first create the new inverter in inv1_mod_master + // and get its pins ready for connection. + // Note we are declaring these new objects outside + // of the test struct so it is obvious what is in the test harness + // and what is in the test + // + dbInst* inv1_2 = dbInst::create(block, + lib->findMaster("INV_X1"), + "inv1_mod_inst/inst2", + false, + inv1_mod_master); + dbITerm* inv1_2_inst_ip0 = inv1_2->findITerm("A"); + dbITerm* inv1_2_inst_op0 = inv1_2->findITerm("ZN"); + + // Plumb in the new input of the inverter + // This is the ip0_net, which is hooked to the top level bterm. + // And to the top level modnet (which connects the modbterm on + // inv1_mod_master) to the inverter. Note the dual connection: + // one flat, one hierarchical. + + inv1_2_inst_ip0->connect(ip0_net); // flat world + inv1_2_inst_ip0->connect(inv1_mod_i0_modnet); // hierarchical world + + // now disconnect the 4th inverter in inv4_4 (this is in level 2, the 3rd + // level, of the hierarchy). + // This kills both the dbNet (flat) connection + // and the dbModNet (hierarchical) connection. + + inv4_4_ip->disconnect(); + + // + // Make the flat connection. + // We keep two worlds: the modnet world + // and the dbNet world. The modnet world + // exists at the edges eg where a module ports + //(dbModITerms) connect to core gates (eg dbITerms). + // + // The flat world is always there. + // + // + std::string flat_net_name = inv1_2->getName() + inv4_4_ip->getName('/'); + std::string hier_net_name = "test_hier_" + flat_net_name; + dbNet* flat_net = dbNet::create(block, flat_net_name.c_str(), false); + inv1_2_inst_op0->connect(flat_net); + inv4_4_ip->connect(flat_net); + + // + // The hierarchical test: connect the output of the inverter in + // inv1_2_inst_op0 to the input of the inverter inv4_4_ip0; + // + + db_network_->hierarchicalConnect( + inv1_2_inst_op0, inv4_4_ip, hier_net_name.c_str()); + + // std::stringstream str_str_final; + // DbStrDebugHierarchy(block, str_str_final); + // printf("The final design: %s\n", str_str_final.str().c_str()); + + size_t final_count = block->getModNets().size(); + EXPECT_LE(initial_count, final_count); +} + +} // namespace odb diff --git a/src/dbSta/test/regression_tests.tcl b/src/dbSta/test/regression_tests.tcl index 339ded4542c..73cd2248b3d 100644 --- a/src/dbSta/test/regression_tests.tcl +++ b/src/dbSta/test/regression_tests.tcl @@ -49,3 +49,7 @@ record_tests { write_sdc1 } + +record_pass_fail_tests { + cpp_tests +} diff --git a/src/odb/test/cpp/TestModule.cpp b/src/odb/test/cpp/TestModule.cpp index 10e139c7994..8582ca460ad 100644 --- a/src/odb/test/cpp/TestModule.cpp +++ b/src/odb/test/cpp/TestModule.cpp @@ -3,11 +3,9 @@ #include #include - #include "helper.h" #include "odb/db.h" - namespace odb { namespace { @@ -289,7 +287,6 @@ BOOST_FIXTURE_TEST_CASE(test_default, F_DEFAULT) dbInst::destroy(inst1); BOOST_TEST(parent_mod->getInsts().size() == 0); } - BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) { auto top = block->getTopModule(); @@ -300,724 +297,6 @@ BOOST_FIXTURE_TEST_CASE(test_find_modinst, F_DEFAULT) auto minst2 = odb::dbModInst::create(master1, master2, "minst2"); BOOST_TEST(block->findModInst("minst1/minst2") == minst2); } - - -dbDatabase* createSimpleDBDelimiter() -{ - utl::Logger* logger = new utl::Logger(); - dbDatabase* db = dbDatabase::create(); - db->setLogger(logger); - dbTech* tech = dbTech::create(db, "tech"); - dbTechLayer::create(tech, "L1", dbTechLayerType::MASTERSLICE); - dbLib* lib = dbLib::create(db, "lib1", tech, ','); - dbChip* chip = dbChip::create(db); - // set up the delimiter - dbBlock::create(chip, "simple_block", nullptr, '/'); - createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o"); - createMaster2X1(lib, "or2", 500, 500, "a", "b", "o"); - createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); - return db; -} - -/* - Test fixture for hierarchical connect test - ------------------------------------------ - - Two modules, 1 with 1 inverter, second with 4 inverters. - - inv1 is instantiated in the top level - inv4 is instantiated three levels down: - level0 -- instantiation in root - level1 - level2 -- contains 4 inverters - - Objective of this test is to stress the hierarchical connection code. - - root {inputs: i0; outputs: o0, o1, o2,o3} - --> inv1 (module containing 1 inverter) this drives inv1_level0_inst - --> inv4_level0_inst {wrapper input: i0, outputs o0,o1,o2,o3} - --> inv4_level1_inst {wrapper input: i0, outputs o0,o1,o2,o3} - --> inv4_level2_inst {contains 4 inverters. Has input i0, outputs o0,01,o2,o3} - */ - -struct F_HCONNECT -{ - F_HCONNECT() - { - // create a db with a delimiter & initialize the db library - db = createSimpleDBDelimiter(); - block = db->getChip()->getBlock(); - lib = db->findLib("lib1"); - - - root_mod = dbModule::create(block, "root_mod"); - // The bterms are created below during wiring - // Note a bterm without a parent is a root bterm. - - // Make the inv1 module (contains 1 inverter). - inv1_mod_master = dbModule::create(block, "inv1_master_mod"); - inv1_mod_i0_port = dbModBTerm::create(inv1_mod_master, "i0"); - inv1_mod_o0_port = dbModBTerm::create(inv1_mod_master, "o0"); - - inv1_mod_inst - = dbModInst::create(root_mod, inv1_mod_master, "inv1_mod_inst"); - - inv1_mod_inst_i0_miterm = dbModITerm::create(inv1_mod_inst, "i0"); - inv1_mod_inst_o0_miterm = dbModITerm::create(inv1_mod_inst, "o0"); - // correlate the iterms and bterms - inv1_mod_inst_i0_miterm->setChildModBTerm(inv1_mod_i0_port); - inv1_mod_i0_port->setParentModITerm(inv1_mod_inst_i0_miterm); - - inv1_mod_inst_o0_miterm->setChildModBTerm(inv1_mod_o0_port); - inv1_mod_o0_port->setParentModITerm(inv1_mod_inst_o0_miterm); - - inv1_1 = dbInst::create(block, - lib->findMaster("inv1"), - "inv1_mod_inst/inst1", - false, - inv1_mod_master); - inv1_1_inst_ip0 = block->findITerm("inv1_mod_inst/inst1/ip0"); - inv1_1_inst_op0 = block->findITerm("inv1_mod_inst/inst1/op0"); - - - - inv4_mod_level0_master = dbModule::create(block, "inv4_master_level0"); - inv4_mod_level0_master_i0_port - = dbModBTerm::create(inv4_mod_level0_master, "i0"); - inv4_mod_level0_master_o0_port - = dbModBTerm::create(inv4_mod_level0_master, "o0"); - inv4_mod_level0_master_o1_port - = dbModBTerm::create(inv4_mod_level0_master, "o1"); - inv4_mod_level0_master_o2_port - = dbModBTerm::create(inv4_mod_level0_master, "o2"); - inv4_mod_level0_master_o3_port - = dbModBTerm::create(inv4_mod_level0_master, "o3"); - - inv4_mod_level1_master = dbModule::create(block, "inv4_master_level1"); - inv4_mod_level1_master_i0_port - = dbModBTerm::create(inv4_mod_level1_master, "i0"); - inv4_mod_level1_master_o0_port - = dbModBTerm::create(inv4_mod_level1_master, "o0"); - inv4_mod_level1_master_o1_port - = dbModBTerm::create(inv4_mod_level1_master, "o1"); - inv4_mod_level1_master_o2_port - = dbModBTerm::create(inv4_mod_level1_master, "o2"); - inv4_mod_level1_master_o3_port - = dbModBTerm::create(inv4_mod_level1_master, "o3"); - - inv4_mod_level2_master = dbModule::create(block, "inv4_master_level2"); - inv4_mod_level2_master_i0_port - = dbModBTerm::create(inv4_mod_level2_master, "i0"); - inv4_mod_level2_master_o0_port - = dbModBTerm::create(inv4_mod_level2_master, "o0"); - inv4_mod_level2_master_o1_port - = dbModBTerm::create(inv4_mod_level2_master, "o1"); - inv4_mod_level2_master_o2_port - = dbModBTerm::create(inv4_mod_level2_master, "o2"); - inv4_mod_level2_master_o3_port - = dbModBTerm::create(inv4_mod_level2_master, "o3"); - - // During modinst creation we set the parent. - inv4_mod_level0_inst = dbModInst::create(root_mod, // parent - inv4_mod_level0_master, - "inv4_mod_level0_inst"); - inv4_mod_level0_inst_i0_miterm - = dbModITerm::create(inv4_mod_level0_inst, "i0"); - inv4_mod_level0_inst_i0_miterm->setChildModBTerm( - inv4_mod_level0_master_i0_port); - inv4_mod_level0_master_i0_port->setParentModITerm( - inv4_mod_level0_inst_i0_miterm); - - inv4_mod_level0_inst_o0_miterm - = dbModITerm::create(inv4_mod_level0_inst, "o0"); - inv4_mod_level0_inst_o0_miterm->setChildModBTerm( - inv4_mod_level0_master_o0_port); - inv4_mod_level0_master_o0_port->setParentModITerm( - inv4_mod_level0_inst_o0_miterm); - - inv4_mod_level0_inst_o1_miterm - = dbModITerm::create(inv4_mod_level0_inst, "o1"); - inv4_mod_level0_inst_o1_miterm->setChildModBTerm( - inv4_mod_level0_master_o1_port); - inv4_mod_level0_master_o1_port->setParentModITerm( - inv4_mod_level0_inst_o1_miterm); - - inv4_mod_level0_inst_o2_miterm - = dbModITerm::create(inv4_mod_level0_inst, "o2"); - inv4_mod_level0_inst_o2_miterm->setChildModBTerm( - inv4_mod_level0_master_o2_port); - inv4_mod_level0_master_o2_port->setParentModITerm( - inv4_mod_level0_inst_o2_miterm); - - inv4_mod_level0_inst_o3_miterm - = dbModITerm::create(inv4_mod_level0_inst, "o3"); - inv4_mod_level0_inst_o3_miterm->setChildModBTerm( - inv4_mod_level0_master_o3_port); - inv4_mod_level0_master_o3_port->setParentModITerm( - inv4_mod_level0_inst_o3_miterm); - - inv4_mod_level1_inst = dbModInst::create(inv4_mod_level0_master, // parent - inv4_mod_level1_master, - "inv4_mod_level1_inst"); - - inv4_mod_level1_inst_i0_miterm - = dbModITerm::create(inv4_mod_level1_inst, "i0"); - inv4_mod_level1_inst_i0_miterm->setChildModBTerm( - inv4_mod_level1_master_i0_port); - inv4_mod_level1_master_i0_port->setParentModITerm( - inv4_mod_level1_inst_i0_miterm); - - inv4_mod_level1_inst_o0_miterm - = dbModITerm::create(inv4_mod_level1_inst, "o0"); - inv4_mod_level1_inst_o0_miterm->setChildModBTerm( - inv4_mod_level1_master_o0_port); - inv4_mod_level1_master_o0_port->setParentModITerm( - inv4_mod_level1_inst_o0_miterm); - - inv4_mod_level1_inst_o1_miterm - = dbModITerm::create(inv4_mod_level1_inst, "o1"); - inv4_mod_level1_inst_o1_miterm->setChildModBTerm( - inv4_mod_level1_master_o1_port); - inv4_mod_level1_master_o1_port->setParentModITerm( - inv4_mod_level1_inst_o1_miterm); - - inv4_mod_level1_inst_o2_miterm - = dbModITerm::create(inv4_mod_level1_inst, "o2"); - inv4_mod_level1_inst_o2_miterm->setChildModBTerm( - inv4_mod_level1_master_o2_port); - inv4_mod_level1_master_o2_port->setParentModITerm( - inv4_mod_level1_inst_o2_miterm); - - inv4_mod_level1_inst_o3_miterm - = dbModITerm::create(inv4_mod_level1_inst, "o3"); - inv4_mod_level1_inst_o3_miterm->setChildModBTerm( - inv4_mod_level1_master_o3_port); - inv4_mod_level1_master_o3_port->setParentModITerm( - inv4_mod_level1_inst_o3_miterm); - - inv4_mod_level2_inst = dbModInst::create(inv4_mod_level1_master, // parent - inv4_mod_level2_master, - "inv4_mod_level2_inst"); - - inv4_mod_level2_inst_i0_miterm - = dbModITerm::create(inv4_mod_level2_inst, "i0"); - inv4_mod_level2_inst_i0_miterm->setChildModBTerm( - inv4_mod_level2_master_i0_port); - inv4_mod_level2_master_i0_port->setParentModITerm( - inv4_mod_level2_inst_i0_miterm); - - inv4_mod_level2_inst_o0_miterm - = dbModITerm::create(inv4_mod_level2_inst, "o0"); - inv4_mod_level2_inst_o0_miterm->setChildModBTerm( - inv4_mod_level2_master_o0_port); - inv4_mod_level2_master_o0_port->setParentModITerm( - inv4_mod_level2_inst_o0_miterm); - - inv4_mod_level2_inst_o1_miterm - = dbModITerm::create(inv4_mod_level2_inst, "o1"); - inv4_mod_level2_inst_o1_miterm->setChildModBTerm( - inv4_mod_level2_master_o1_port); - inv4_mod_level2_master_o1_port->setParentModITerm( - inv4_mod_level2_inst_o1_miterm); - - inv4_mod_level2_inst_o2_miterm - = dbModITerm::create(inv4_mod_level2_inst, "o2"); - inv4_mod_level2_inst_o2_miterm->setChildModBTerm( - inv4_mod_level2_master_o2_port); - inv4_mod_level2_master_o2_port->setParentModITerm( - inv4_mod_level2_inst_o2_miterm); - - inv4_mod_level2_inst_o3_miterm - = dbModITerm::create(inv4_mod_level2_inst, "o3"); - inv4_mod_level2_inst_o3_miterm->setChildModBTerm( - inv4_mod_level2_master_o3_port); - inv4_mod_level2_master_o3_port->setParentModITerm( - inv4_mod_level2_inst_o3_miterm); - - // - // create the low level inverter instances, for now uniquely name them in - // the scope of a block. - - inv4_1 = dbInst::create( - block, - lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst1"); - - // get the iterm off the instance. Just give the terminal name - // offset used to find iterm. - inv4_1_ip = inv4_1->findITerm("ip0"); - inv4_1_op = inv4_1->findITerm("op0"); - - inv4_2 = dbInst::create( - block, - lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst2"); - inv4_2_ip = inv4_2->findITerm("ip0"); - inv4_2_op = inv4_2->findITerm("op0"); - - inv4_3 = dbInst::create( - block, - lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst3"); - inv4_3_ip = inv4_3->findITerm("ip0"); - inv4_3_op = inv4_3->findITerm("op0"); - - inv4_4 = dbInst::create( - block, - lib->findMaster("inv1"), - "inv4_mod_level0_inst/inv4_mod_level1_inst/inv4_mod_level2_inst/inst4"); - inv4_4_ip = inv4_4->findITerm("ip0"); - inv4_4_op = inv4_4->findITerm("op0"); - - // - // inv4_mod_level2_master is lowest level in hierarchy - // - inv4_mod_level2_master->addInst(inv4_1); - inv4_mod_level2_master->addInst(inv4_2); - inv4_mod_level2_master->addInst(inv4_3); - inv4_mod_level2_master->addInst(inv4_4); - - inv4_mod_level2_inst_i0_mnet = dbModNet::create( - inv4_mod_level2_master, "inv4_mod_level2_inst_i0_mnet"); - inv4_mod_level2_inst_o0_mnet = dbModNet::create( - inv4_mod_level2_master, "inv4_mod_level2_inst_o0_mnet"); - inv4_mod_level2_inst_o1_mnet = dbModNet::create( - inv4_mod_level2_master, "inv4_mod_level2_inst_o1_mnet"); - inv4_mod_level2_inst_o2_mnet = dbModNet::create( - inv4_mod_level2_master, "inv4_mod_level2_inst_o2_mnet"); - inv4_mod_level2_inst_o3_mnet = dbModNet::create( - inv4_mod_level2_master, "inv4_mod_level2_inst_o3_mnet"); - inv4_1_ip->connect(inv4_mod_level2_inst_i0_mnet); - inv4_2_ip->connect(inv4_mod_level2_inst_i0_mnet); - inv4_3_ip->connect(inv4_mod_level2_inst_i0_mnet); - inv4_4_ip->connect(inv4_mod_level2_inst_i0_mnet); - - inv4_1_op->connect(inv4_mod_level2_inst_o0_mnet); - inv4_2_op->connect(inv4_mod_level2_inst_o1_mnet); - inv4_3_op->connect(inv4_mod_level2_inst_o2_mnet); - inv4_4_op->connect(inv4_mod_level2_inst_o3_mnet); - - inv4_mod_level2_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); - inv4_mod_level2_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); - inv4_mod_level2_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); - inv4_mod_level2_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); - inv4_mod_level2_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); - - // First make the flat view connectivity - dbNet* ip0_net = dbNet::create(block, "ip0_flat_net", false); - dbNet* inv_op_net = dbNet::create(block, "inv_op_flat_net", false); - op0_net = dbNet::create(block, "op0_flat_net", false); - op1_net = dbNet::create(block, "op1_flat_net", false); - op2_net = dbNet::create(block, "op2_flat_net", false); - op3_net = dbNet::create(block, "op3_flat_net", false); - - // - // connections to the primary (root) ports - // Note: a bterm without a parent is a root port. - // - ip0_bterm = dbBTerm::create(ip0_net, "ip0"); - op0_bterm = dbBTerm::create(op0_net, "op0"); - op1_bterm = dbBTerm::create(op1_net, "op1"); - op2_bterm = dbBTerm::create(op2_net, "op2"); - op3_bterm = dbBTerm::create(op3_net, "op3"); - - op0_bterm->connect(inv4_mod_level2_inst_o0_mnet); - op1_bterm->connect(inv4_mod_level2_inst_o1_mnet); - op2_bterm->connect(inv4_mod_level2_inst_o2_mnet); - op3_bterm->connect(inv4_mod_level2_inst_o3_mnet); - - // flat connections: - // inverter 1 in module inv1_1 - inv1_1_inst_ip0->connect(ip0_net); - inv1_1_inst_op0->connect(inv_op_net); - - // now the 4 inverters in inv4_1 - inv4_1_ip->connect(inv_op_net); - inv4_2_ip->connect(inv_op_net); - inv4_3_ip->connect(inv_op_net); - inv4_4_ip->connect(inv_op_net); - - // now core to external connections - inv4_1_op->connect(op0_net); - inv4_2_op->connect(op1_net); - inv4_3_op->connect(op2_net); - inv4_4_op->connect(op3_net); - - // std::stringstream str_str; - // DbStrDebugHierarchy(block, str_str); - // printf("The Flat design created %s\n", str_str.str().c_str()); - - // Now build the hierarchical "overlay" - // What we are doing here is adding the modnets which hook up - - // wire in hierarchy for inv1 - - // Contents of inv1 (modnets from ports to internals). - inv1_mod_i0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_i0_mnet"); - inv1_mod_o0_modnet = dbModNet::create(inv1_mod_master, "inv1_mod_o0_mnet"); - // connection from port to net in module - inv1_mod_i0_port->connect(inv1_mod_i0_modnet); - // connection to inverter ip - inv1_1_inst_ip0->connect(inv1_mod_i0_modnet); - // from inverter op to port - inv1_1_inst_op0->connect(inv1_mod_o0_modnet); - inv1_mod_o0_port->connect(inv1_mod_o0_modnet); - - // Instantiation of inv1 connections to top level (root bterms to modnets, - // modnets to moditerms on inv1). - root_inv1_i0_mnet = dbModNet::create(root_mod, "inv1_inst_i0_mnet"); - root_inv1_o0_mnet = dbModNet::create(root_mod, "inv1_inst_o0_mnet"); - inv1_mod_inst_i0_miterm->connect(root_inv1_i0_mnet); - inv1_mod_inst_o0_miterm->connect(root_inv1_o0_mnet); - - // top level connections for inv1. - // root input to instance, via a modnet. - ip0_bterm->connect(root_inv1_i0_mnet); - // note the output from out inverter module is inv1_inst_o0_mnet - // which now needs to be hooked up the inv4 hierarchy. - - // The inv4 hierarchy connections - // inv1 -> inv4 connection - inv4_mod_level0_inst_i0_miterm->connect(root_inv1_o0_mnet); - - // level 0 is top of hierarchy, in root - // the level 0 instance -> root connections - root_inv4_o0_mnet = dbModNet::create(root_mod, "inv4_inst_o0_mnet"); - inv4_mod_level0_inst_o0_miterm->connect(root_inv4_o0_mnet); - op0_bterm->connect(root_inv4_o0_mnet); - - root_inv4_o1_mnet = dbModNet::create(root_mod, "inv4_inst_o1_mnet"); - inv4_mod_level0_inst_o1_miterm->connect(root_inv4_o1_mnet); - op1_bterm->connect(root_inv4_o1_mnet); - - root_inv4_o2_mnet = dbModNet::create(root_mod, "inv4_inst_o2_mnet"); - inv4_mod_level0_inst_o2_miterm->connect(root_inv4_o2_mnet); - op2_bterm->connect(root_inv4_o2_mnet); - - root_inv4_o3_mnet = dbModNet::create(root_mod, "inv4_inst_o3_mnet"); - inv4_mod_level0_inst_o3_miterm->connect(root_inv4_o3_mnet); - op3_bterm->connect(root_inv4_o3_mnet); - - // level 1 is next level down - // The level 1 instance connections within the scope of the - // inv4_mod_level0_master - inv4_mod_level1_inst_i0_mnet = dbModNet::create( - inv4_mod_level0_master, "inv4_mod_level1_inst_i0_mnet"); - - inv4_mod_level1_inst_i0_miterm->connect(inv4_mod_level1_inst_i0_mnet); - inv4_mod_level0_master_i0_port->connect(inv4_mod_level1_inst_i0_mnet); - - inv4_mod_level1_inst_o0_mnet = dbModNet::create( - inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); - inv4_mod_level1_inst_o0_miterm->connect(inv4_mod_level1_inst_o0_mnet); - inv4_mod_level0_master_o0_port->connect(inv4_mod_level1_inst_o0_mnet); - - inv4_mod_level1_inst_o1_mnet = dbModNet::create( - inv4_mod_level0_master, "inv4_mod_level1_inst_o1_mnet"); - inv4_mod_level1_inst_o1_miterm->connect(inv4_mod_level1_inst_o1_mnet); - inv4_mod_level0_master_o1_port->connect(inv4_mod_level1_inst_o1_mnet); - - inv4_mod_level1_inst_o2_mnet = dbModNet::create( - inv4_mod_level0_master, "inv4_mod_level1_inst_o2_mnet"); - inv4_mod_level1_inst_o2_miterm->connect(inv4_mod_level1_inst_o2_mnet); - inv4_mod_level0_master_o2_port->connect(inv4_mod_level1_inst_o2_mnet); - - inv4_mod_level1_inst_o3_mnet = dbModNet::create( - inv4_mod_level0_master, "inv4_mod_level1_inst_o3_mnet"); - inv4_mod_level1_inst_o3_miterm->connect(inv4_mod_level1_inst_o3_mnet); - inv4_mod_level0_master_o3_port->connect(inv4_mod_level1_inst_o3_mnet); - - // The level 2 instance connections within the scope of the - // inv4_mod_level1_master level 2 is the cell which contains the 4 inverters - inv4_mod_level2_inst_i0_mnet = dbModNet::create( - inv4_mod_level1_master, "inv4_mod_level2_inst_i0_mnet"); - - inv4_mod_level2_inst_i0_miterm->connect(inv4_mod_level2_inst_i0_mnet); - inv4_mod_level1_master_i0_port->connect(inv4_mod_level2_inst_i0_mnet); - - inv4_mod_level2_inst_o0_mnet = dbModNet::create( - inv4_mod_level1_master, "inv4_mod_level2_inst_o0_mnet"); - - inv4_mod_level2_inst_o0_miterm->connect(inv4_mod_level2_inst_o0_mnet); - inv4_mod_level1_master_o0_port->connect(inv4_mod_level2_inst_o0_mnet); - - inv4_mod_level2_inst_o1_mnet = dbModNet::create( - inv4_mod_level1_master, "inv4_mod_level2_inst_o1_mnet"); - - inv4_mod_level2_inst_o1_miterm->connect(inv4_mod_level2_inst_o1_mnet); - inv4_mod_level1_master_o1_port->connect(inv4_mod_level2_inst_o1_mnet); - - inv4_mod_level2_inst_o2_mnet = dbModNet::create( - inv4_mod_level1_master, "inv4_mod_level2_inst_o2_mnet"); - - inv4_mod_level2_inst_o2_miterm->connect(inv4_mod_level2_inst_o2_mnet); - inv4_mod_level1_master_o2_port->connect(inv4_mod_level2_inst_o2_mnet); - - inv4_mod_level2_inst_o3_mnet = dbModNet::create( - inv4_mod_level1_master, "inv4_mod_level2_inst_o3_mnet"); - - inv4_mod_level2_inst_o3_miterm->connect(inv4_mod_level2_inst_o3_mnet); - inv4_mod_level1_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); - - std::stringstream full_design; - DbStrDebugHierarchy(block, full_design); - printf("The design created (flat and hierarchical) %s\n", full_design.str().c_str()); - } - - ~F_HCONNECT() { dbDatabase::destroy(db); } - - dbDatabase* db; - dbLib* lib; - dbBlock* block; - - dbModule* root_mod; - dbMTerm* root_mod_i0_mterm; - dbMTerm* root_mod_i1_mterm; - dbMTerm* root_mod_i2_mterm; - dbMTerm* root_mod_i3_mterm; - dbMTerm* root_mod_o0_mterm; - - dbBTerm* root_mod_i0_bterm; - dbBTerm* root_mod_i1_bterm; - dbBTerm* root_mod_i2_bterm; - dbBTerm* root_mod_i3_bterm; - dbBTerm* root_mod_o0_bterm; - - dbModule* inv1_mod_master; - dbModInst* inv1_mod_inst; - dbModITerm* inv1_mod_inst_i0_miterm; - dbModITerm* inv1_mod_inst_o0_miterm; - dbModBTerm* inv1_mod_i0_port; - dbModBTerm* inv1_mod_o0_port; - dbModNet* inv1_mod_i0_modnet; - dbModNet* inv1_mod_o0_modnet; - - dbModule* inv4_mod_level0_master; - dbModule* inv4_mod_level1_master; - dbModule* inv4_mod_level2_master; - - dbModBTerm* inv4_mod_level0_master_i0_port; - dbModBTerm* inv4_mod_level0_master_o0_port; - dbModBTerm* inv4_mod_level0_master_o1_port; - dbModBTerm* inv4_mod_level0_master_o2_port; - dbModBTerm* inv4_mod_level0_master_o3_port; - - dbModBTerm* inv4_mod_level1_master_i0_port; - dbModBTerm* inv4_mod_level1_master_o0_port; - dbModBTerm* inv4_mod_level1_master_o1_port; - dbModBTerm* inv4_mod_level1_master_o2_port; - dbModBTerm* inv4_mod_level1_master_o3_port; - - dbModBTerm* inv4_mod_level2_master_i0_port; - dbModBTerm* inv4_mod_level2_master_o0_port; - dbModBTerm* inv4_mod_level2_master_o1_port; - dbModBTerm* inv4_mod_level2_master_o2_port; - dbModBTerm* inv4_mod_level2_master_o3_port; - - dbModInst* inv4_mod_level0_inst; - dbModInst* inv4_mod_level1_inst; - dbModInst* inv4_mod_level2_inst; - - dbModITerm* inv4_mod_level0_inst_i0_miterm; - dbModITerm* inv4_mod_level0_inst_o0_miterm; - dbModITerm* inv4_mod_level0_inst_o1_miterm; - dbModITerm* inv4_mod_level0_inst_o2_miterm; - dbModITerm* inv4_mod_level0_inst_o3_miterm; - - dbModITerm* inv4_mod_level1_inst_i0_miterm; - dbModITerm* inv4_mod_level1_inst_o0_miterm; - dbModITerm* inv4_mod_level1_inst_o1_miterm; - dbModITerm* inv4_mod_level1_inst_o2_miterm; - dbModITerm* inv4_mod_level1_inst_o3_miterm; - - dbModITerm* inv4_mod_level2_inst_i0_miterm; - dbModITerm* inv4_mod_level2_inst_o0_miterm; - dbModITerm* inv4_mod_level2_inst_o1_miterm; - dbModITerm* inv4_mod_level2_inst_o2_miterm; - dbModITerm* inv4_mod_level2_inst_o3_miterm; - - dbInst* inv1_1; - dbInst* inv4_1; - dbInst* inv4_2; - dbInst* inv4_3; - dbInst* inv4_4; - - dbNet* ip0_net; - dbNet* inv_op__net; - dbNet* op0_net; - dbNet* op1_net; - dbNet* op2_net; - dbNet* op3_net; - - dbBTerm* ip0_bterm; - dbBTerm* op0_bterm; - dbBTerm* op1_bterm; - dbBTerm* op2_bterm; - dbBTerm* op3_bterm; - - dbModITerm* inv1_1_ip; - dbModITerm* inv1_1_op; - - dbModNet* root_inv1_i0_mnet; - dbModNet* root_inv1_o0_mnet; - - dbModNet* root_inv4_o0_mnet; - dbModNet* root_inv4_o1_mnet; - dbModNet* root_inv4_o2_mnet; - dbModNet* root_inv4_o3_mnet; - - // first input inv4_mod_level_i0 comes from root_inv1_o0_modnet - dbModNet* inv4_mod_level0_inst_o0_mnet; - dbModNet* inv4_mod_level0_inst_o1_mnet; - dbModNet* inv4_mod_level0_inst_o2_mnet; - dbModNet* inv4_mod_level0_inst_o3_mnet; - - dbModNet* inv4_mod_level1_inst_i0_mnet; - dbModNet* inv4_mod_level1_inst_o0_mnet; - dbModNet* inv4_mod_level1_inst_o1_mnet; - dbModNet* inv4_mod_level1_inst_o2_mnet; - dbModNet* inv4_mod_level1_inst_o3_mnet; - - dbModNet* inv4_mod_level2_inst_i0_mnet; - dbModNet* inv4_mod_level2_inst_o0_mnet; - dbModNet* inv4_mod_level2_inst_o1_mnet; - dbModNet* inv4_mod_level2_inst_o2_mnet; - dbModNet* inv4_mod_level2_inst_o3_mnet; - - dbITerm* inv1_1_inst_ip0; - dbITerm* inv1_1_inst_op0; - - dbITerm* inv4_1_ip; - dbITerm* inv4_2_ip; - dbITerm* inv4_3_ip; - dbITerm* inv4_4_ip; - dbITerm* inv4_1_op; - dbITerm* inv4_2_op; - dbITerm* inv4_3_op; - dbITerm* inv4_4_op; -}; - -BOOST_FIXTURE_TEST_CASE(test_hier, F_HCONNECT) -{ - auto top = block->getTopModule(); - BOOST_TEST(top != nullptr); - auto master1 = odb::dbModule::create(block, "master1"); - - odb::dbModInst::create(top, master1, "minst1"); - - auto master2 = odb::dbModule::create(block, "master2"); - auto minst2 = odb::dbModInst::create(master1, master2, "minst2"); - - BOOST_TEST(block->findModInst("minst1/minst2") == minst2); -} - -BOOST_FIXTURE_TEST_CASE(test_hierconnect, F_HCONNECT) -{ - // - // - //Hierarchical connection test case: - //---------------------------------- - // - //add a new inverter to inv1 and connect to the fanout of the - //existing one. - //remove the driver of the 4th inverter in inv4_4 leaf - //and connect to it via hierarchy - // - // - // Before - //--inv1_1 -----------inv4_1_ip0 - // |----------inv4_2_ip0 - // |----------inv4_3_ip0 - // |----------inv4_4_ip0 - // - // - //After: - // - //--inv1_1-----------inv4_1_ip0 - // |----------inv4_2_ip0 - // |----------inv4_3_ip0 - // - //--inv1_2---------inv4_4_ip0 - // - // - // - //Objects referenced in "before" - // - //inv1_1 -- dbInst in inv1_1 - //inv1_1_inst_op0 -- op iterm on inv1 - //inv1_mod_master -- dbModule parent for inv1_1 - //inv4_mod_level2_master -- dbModule parent for leaf level inverters in inv4 - //inv4_4_ip0 -- ip iterm on 4th inverter - // - // - - std::stringstream str_str_start; - DbStrDebugHierarchy(block, str_str_start); - printf("The original design: %s\n", str_str_start.str().c_str()); - - // - //first create the new inverter in inv1_mod_master - //and get its pins ready for connection. - //Note we are declaring these new objects outside - //of the test struct so it is obvious what is in the test harness - //and what is in the test - // - dbInst* inv1_2 = dbInst::create(block, - lib->findMaster("inv2"), - "inv1_mod_inst/inst2", - false, - inv1_mod_master); - dbITerm* inv1_2_inst_ip0 = block->findITerm("inv1_mod_inst/inst2/ip0"); - dbITerm* inv1_2_inst_op0 = block->findITerm("inv1_mod_inst/inst2/op0"); - - //Plumb in the new input of the inverter - //This is the ip0_net, which is hooked to the top level bterm. - //And to the top level modnet (which connects the modbterm on - //inv1_mod_master) to the inverter. Note the dual connection: - //one flat, one hierarchical. - - inv1_2_inst_ip0 -> connect(ip0_net); //flat world - inv1_2_inst_ip0 -> connect(inv1_mod_i0_modnet); //hierarchical world - - //now disconnect the 4th inverter in inv4_4 (this is in level 2, the 3rd - //level, of the hierarchy). - //This kills both the dbNet (flat) connection - //and the dbModNet (hierarchical) connection. - - inv4_4_ip -> disconnect(); - - - // - //Make the flat connection. - //We keep two worlds: the modnet world - //and the dbNet world. The modnet world - //exists at the edges eg where a module ports - //(dbModITerms) connect to core gates (eg dbITerms). - // - //The flat world is always there. - // - // - std::string flat_net_name = inv1_2 -> getName() + inv4_4_ip -> getName('/'); - std::string hier_net_name = "test_hier_"+flat_net_name; - dbNet* flat_net = dbNet::create(block,flat_net_name.c_str(),false); - inv1_2_inst_op0 -> connect(flat_net); - inv4_4_ip -> connect(flat_net); - - // - //The hierarchical test: connect the output of the inverter in inv1_2_inst_op0 to - //the input of the inverter inv4_4_ip0; - // - - /* - ::hierarchicalConnect(inv1_2_inst_op0, - inv4_4_ip, - hier_net_name.c_str()); - */ - std::stringstream str_str_final; - DbStrDebugHierarchy(block, str_str_final); - printf("The final design: %s\n", str_str_final.str().c_str()); -} - struct F_DETAILED { F_DETAILED() @@ -1025,7 +304,6 @@ struct F_DETAILED db = createSimpleDB(); block = db->getChip()->getBlock(); lib = db->findLib("lib1"); - master_mod1 = dbModule::create(block, "master_mod1"); master_mod2 = dbModule::create(block, "master_mod2"); master_mod3 = dbModule::create(block, "master_mod3"); @@ -1055,7 +333,6 @@ struct F_DETAILED dbInst* inst2; dbInst* inst3; }; - BOOST_FIXTURE_TEST_CASE(test_destroy, F_DETAILED) { BOOST_TEST(block->getModInsts().size() == 3); From b14bb2214cbe9dca5ec98e50990456ee3ce2c0e0 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Sun, 22 Dec 2024 18:56:59 -0800 Subject: [PATCH 07/15] reformat Signed-off-by: andyfox-rushc --- src/odb/test/cpp/helper/helper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odb/test/cpp/helper/helper.cpp b/src/odb/test/cpp/helper/helper.cpp index 4253930024b..92b2855a72c 100644 --- a/src/odb/test/cpp/helper/helper.cpp +++ b/src/odb/test/cpp/helper/helper.cpp @@ -72,7 +72,7 @@ dbMaster* createMaster1X1(dbLib* lib, master->setFrozen(); return master; } - + dbDatabase* createSimpleDB() { utl::Logger* logger = new utl::Logger(); @@ -85,7 +85,7 @@ dbDatabase* createSimpleDB() dbBlock::create(chip, "simple_block"); createMaster2X1(lib, "and2", 1000, 1000, "a", "b", "o"); createMaster2X1(lib, "or2", 500, 500, "a", "b", "o"); - createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); + createMaster1X1(lib, "inv1", 500, 500, "ip0", "op0"); return db; } From 44262cd2b4682d2aaf02d4536b6bf7637f8b07bc Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Sun, 22 Dec 2024 19:02:24 -0800 Subject: [PATCH 08/15] removed extraneous file Signed-off-by: andyfox-rushc --- src/dbSta/src/tmp | 69 ----------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 src/dbSta/src/tmp diff --git a/src/dbSta/src/tmp b/src/dbSta/src/tmp deleted file mode 100644 index 32e131ea1f9..00000000000 --- a/src/dbSta/src/tmp +++ /dev/null @@ -1,69 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// BSD 3-Clause License -// -// Copyright (c) 2021, The Regents of the University of California -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * Neither the name of the copyright holder nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "AbstractPowerDensityDataSource.h" -#include "gui/heatMap.h" - -namespace sta { -class dbSta; -class Corner; - -class PowerDensityDataSource : public gui::RealValueHeatMapDataSource, - public AbstractPowerDensityDataSource -{ - public: - PowerDensityDataSource(dbSta* sta, utl::Logger* logger); - - protected: - bool populateMap() override; - void combineMapData(bool base_has_value, - double& base, - double new_data, - double data_area, - double intersection_area, - double rect_area) override; - - private: - sta::dbSta* sta_; - - bool include_internal_ = true; - bool include_leakage_ = true; - bool include_switching_ = true; - - std::string corner_; - - sta::Corner* getCorner() const; -}; - -} // namespace sta From 365b5f65a0b1574e6922d54fc1a7097328db896a Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 23 Dec 2024 14:28:36 -0800 Subject: [PATCH 09/15] reverted helper.h to master version, dbSta has cpp test in now Signed-off-by: andyfox-rushc --- src/odb/test/cpp/helper/helper.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/odb/test/cpp/helper/helper.h b/src/odb/test/cpp/helper/helper.h index d4eee3debf3..04f7abe78c2 100644 --- a/src/odb/test/cpp/helper/helper.h +++ b/src/odb/test/cpp/helper/helper.h @@ -41,12 +41,6 @@ odb::dbMaster* createMaster2X1(odb::dbLib* lib, const char* in1, const char* in2, const char* out); -odb::dbMaster* createMaster1X1(odb::dbLib* lib, - const char* name, - uint width, - uint height, - const char* in1, - const char* out); odb::dbDatabase* createSimpleDB(); From 9a2246f839a52aaf229d830776731169fc366885 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 23 Dec 2024 14:52:28 -0800 Subject: [PATCH 10/15] Added more meaningful test metrics to hier case Signed-off-by: andyfox-rushc --- src/dbSta/test/cpp/TestHconn.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/dbSta/test/cpp/TestHconn.cpp b/src/dbSta/test/cpp/TestHconn.cpp index 2dbecd47c2c..27c2f3c36a0 100644 --- a/src/dbSta/test/cpp/TestHconn.cpp +++ b/src/dbSta/test/cpp/TestHconn.cpp @@ -719,10 +719,11 @@ class TestHconn : public ::testing::Test inv4_mod_level2_inst_o3_miterm->connect(inv4_mod_level2_inst_o3_mnet); inv4_mod_level1_master_o3_port->connect(inv4_mod_level2_inst_o3_mnet); + // Uncomment this to see the full design // std::stringstream full_design; // DbStrDebugHierarchy(block, full_design); // printf("The design created (flat and hierarchical) %s\n", - // full_design.str().c_str()); + // full_design.str().c_str()); } utl::UniquePtrWithDeleter db_; @@ -868,6 +869,8 @@ TEST_F(TestHconn, ConnectionMade) // std::stringstream str_str_initial; // DbStrDebugHierarchy(block, str_str_initial); // printf("The initial design: %s\n", str_str_initial.str().c_str()); + size_t initial_db_net_count = block->getNets().size(); + size_t initial_mod_net_count = block->getModNets().size(); // // @@ -907,8 +910,6 @@ TEST_F(TestHconn, ConnectionMade) // // - size_t initial_count = block->getModNets().size(); - // // first create the new inverter in inv1_mod_master // and get its pins ready for connection. @@ -964,12 +965,18 @@ TEST_F(TestHconn, ConnectionMade) db_network_->hierarchicalConnect( inv1_2_inst_op0, inv4_4_ip, hier_net_name.c_str()); + // Uncomment this to see the final design // std::stringstream str_str_final; // DbStrDebugHierarchy(block, str_str_final); // printf("The final design: %s\n", str_str_final.str().c_str()); - size_t final_count = block->getModNets().size(); - EXPECT_LE(initial_count, final_count); + size_t final_db_net_count = block->getNets().size(); + size_t final_mod_net_count = block->getModNets().size(); + + EXPECT_EQ(initial_db_net_count, 6); + EXPECT_EQ(initial_mod_net_count, 23); + EXPECT_EQ(final_mod_net_count, 27); + EXPECT_EQ(final_db_net_count, 7); } } // namespace odb From 25f7e0ac9ed231b97bc4cfc47df79b70851fb61d Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 23 Dec 2024 15:22:21 -0800 Subject: [PATCH 11/15] reformatted TestHconn.cpp, applied clang-tidy suggestions Signed-off-by: andyfox-rushc --- src/dbSta/test/cpp/TestHconn.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/dbSta/test/cpp/TestHconn.cpp b/src/dbSta/test/cpp/TestHconn.cpp index 27c2f3c36a0..0d60e4a2c58 100644 --- a/src/dbSta/test/cpp/TestHconn.cpp +++ b/src/dbSta/test/cpp/TestHconn.cpp @@ -125,10 +125,7 @@ void DbStrDebugHierarchy(dbBlock* block, std::stringstream& str_db) str_db << tmp_str; dbSet module_ports = cur_obj->getModBTerms(); - for (dbSet::iterator mod_bterm_iter = module_ports.begin(); - mod_bterm_iter != module_ports.end(); - mod_bterm_iter++) { - dbModBTerm* module_port = *mod_bterm_iter; + for (auto module_port : module_ports) { sprintf( tmp_str, "\t\tPort %s Net %s (%d)\n", @@ -148,10 +145,7 @@ void DbStrDebugHierarchy(dbBlock* block, std::stringstream& str_db) sprintf(tmp_str, "\t\tModule instances +++\n"); str_db << tmp_str; dbSet module_instances = mi->getModInsts(); - for (dbSet::iterator mod_inst_iter = module_instances.begin(); - mod_inst_iter != module_instances.end(); - mod_inst_iter++) { - dbModInst* module_inst = *mod_inst_iter; + for (auto module_inst : module_instances) { sprintf(tmp_str, "\t\tMod inst %s ", module_inst->getName()); str_db << tmp_str; dbModule* master = module_inst->getMaster(); @@ -186,9 +180,7 @@ void DbStrDebugHierarchy(dbBlock* block, std::stringstream& str_db) sprintf(tmp_str, "\t\tdb iterms:\n"); str_db << tmp_str; dbSet iterms = db_inst->getITerms(); - dbSet::iterator iterm_itr; - for (iterm_itr = iterms.begin(); iterm_itr != iterms.end(); ++iterm_itr) { - dbITerm* iterm = *iterm_itr; + for (auto iterm : iterms) { dbMTerm* mterm = iterm->getMTerm(); sprintf( tmp_str, @@ -212,10 +204,7 @@ void DbStrDebugHierarchy(dbBlock* block, std::stringstream& str_db) str_db << tmp_str; dbSet mod_nets = cur_obj->getModNets(); - for (dbSet::iterator mod_net_iter = mod_nets.begin(); - mod_net_iter != mod_nets.end(); - mod_net_iter++) { - dbModNet* mod_net = *mod_net_iter; + for (auto mod_net : mod_nets) { sprintf( tmp_str, "\t\tNet: %s (%u)\n", mod_net->getName(), mod_net->getId()); str_db << tmp_str; From 4011950a88a5ba1f3ed6328f93f670cebe1a27ed Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Tue, 24 Dec 2024 17:36:24 -0800 Subject: [PATCH 12/15] Added example of how to force invoking of callbacks on dbITerm/dbBTerm on modnet Signed-off-by: andyfox-rushc --- src/dbSta/test/cpp/TestHconn.cpp | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/dbSta/test/cpp/TestHconn.cpp b/src/dbSta/test/cpp/TestHconn.cpp index 0d60e4a2c58..5cfbbb77452 100644 --- a/src/dbSta/test/cpp/TestHconn.cpp +++ b/src/dbSta/test/cpp/TestHconn.cpp @@ -290,6 +290,8 @@ class TestHconn : public ::testing::Test sta::Units* units = library_->units(); power_unit_ = units->powerUnit(); db_network_ = sta_->getDbNetwork(); + // turn on hierarchy + db_network_->setHierarchy(); db_->setLogger(&logger_); // create a chain consisting of 4 buffers @@ -959,6 +961,40 @@ TEST_F(TestHconn, ConnectionMade) // DbStrDebugHierarchy(block, str_str_final); // printf("The final design: %s\n", str_str_final.str().c_str()); + // Example of how to turn on the call backs for all the bterms/iterms + // used by the sta + dbSet mod_nets = block->getModNets(); + for (auto mnet : mod_nets) { + sta::NetSet visited_nets; + // given one mod net go get all its low level objects to + // issue call back on + sta::Net* cur_net = db_network_->dbToSta(mnet); + sta::NetConnectedPinIterator* npi + = db_network_->connectedPinIterator(cur_net); + while (npi->hasNext()) { + const sta::Pin* cur_pin = npi->next(); + odb::dbModBTerm* modbterm; + odb::dbModITerm* moditerm; + odb::dbITerm* iterm; + odb::dbBTerm* bterm; + db_network_->staToDb(cur_pin, iterm, bterm, moditerm, modbterm); + if (iterm) { + db_network_->connectPinAfter(const_cast(cur_pin)); + sta_->connectPinAfter(const_cast(cur_pin)); + } + if (bterm) { + db_network_->connectPinAfter(const_cast(cur_pin)); + sta_->connectPinAfter(const_cast(cur_pin)); + } + if (modbterm) { + ; + } + if (moditerm) { + ; + } + } + } + size_t final_db_net_count = block->getNets().size(); size_t final_mod_net_count = block->getModNets().size(); From 9340087659ed2e08e04ced89c84b749dc56b3349 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 30 Dec 2024 12:23:34 -0800 Subject: [PATCH 13/15] Cleaned up comments to help with review Signed-off-by: andyfox-rushc --- src/dbSta/src/dbNetwork.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index 819abc562ab..cfe1e390347 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -3055,6 +3055,16 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, source_pin->connect(source_db_net); } + // Wire up the destination pin, if not already hooked to the correct + // flat net. Note the destination pin could indeed be wired to something + // else. + // This case can occur during assembly as an intermediate state + // (seems to occur in cts). We change the dest_pin's flat net + // connection to the correct source (recall buffers are being removed + // and we could be in some intermediate state in some other code). + // We also preserve any destination pin modnet connection (dest_pin + // could be on edge of another module). + if (dest_db_net && (dest_db_net != source_db_net)) { // if we have dest_mod_net, keep it dbModNet* dest_mod_net = dest_pin->getModNet(); @@ -3065,6 +3075,7 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, } } + // case 1: source/dest in same module if (source_db_module == dest_db_module) { if (!source_db_mod_net) { source_db_mod_net = dbModNet::create(source_db_module, connection_name); From e80dc702fc7c3742fb4634d7cee690eb31500b9b Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 30 Dec 2024 15:16:40 -0800 Subject: [PATCH 14/15] Removed cts specific code in hierconnect Signed-off-by: andyfox-rushc --- src/dbSta/src/dbNetwork.cc | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index cfe1e390347..3b73d552ac5 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -3053,28 +3053,10 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, std::string flat_name = connection_name_str + "_flat"; source_db_net = dbNet::create(block(), flat_name.c_str(), false); source_pin->connect(source_db_net); - } - - // Wire up the destination pin, if not already hooked to the correct - // flat net. Note the destination pin could indeed be wired to something - // else. - // This case can occur during assembly as an intermediate state - // (seems to occur in cts). We change the dest_pin's flat net - // connection to the correct source (recall buffers are being removed - // and we could be in some intermediate state in some other code). - // We also preserve any destination pin modnet connection (dest_pin - // could be on edge of another module). - - if (dest_db_net && (dest_db_net != source_db_net)) { - // if we have dest_mod_net, keep it - dbModNet* dest_mod_net = dest_pin->getModNet(); - dest_pin->disconnect(); dest_pin->connect(source_db_net); - if (dest_mod_net) { - dest_pin->connect(dest_mod_net); - } } + // Make the hierarchical connection. // case 1: source/dest in same module if (source_db_module == dest_db_module) { if (!source_db_mod_net) { From 3670481796918934275db92dd7475608a8f43e23 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Mon, 30 Dec 2024 15:26:38 -0800 Subject: [PATCH 15/15] clang-tidy feedback Signed-off-by: andyfox-rushc --- src/dbSta/src/dbNetwork.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index 3b73d552ac5..a5a10df1470 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -3046,7 +3046,6 @@ void dbNetwork::hierarchicalConnect(dbITerm* source_pin, // new hierarchical connections. dbNet* source_db_net = source_pin->getNet(); - dbNet* dest_db_net = dest_pin->getNet(); if (!source_db_net) { std::string connection_name_str(connection_name);