From e6e667c6c7fd322241c558a2ec083ef28a6c955a Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 23 Oct 2020 22:28:04 +0200 Subject: [PATCH] Etesian manage top level obstacles when placing a sub-block. Note: To implement this in a more flexible way we should introduce a concept of Instance/Cell "placeholder" to reserve space transhierarchically. * Change: In EtesianEngine::toColoquinte(), when placing only one block in a cell, the cell itself can contains other fixed instances that are over the placement area. Create dummy fixed instances to reserve the taken space. In EtesianEngine::AddFeeds(), do not put feed cells over the cell area occuped by the sibling instances cells. * Cleanup: In KatanaEngine::setupPowerRails(): small cleanup. --- etesian/src/AddFeeds.cpp | 16 +++++++++++ etesian/src/EtesianEngine.cpp | 50 +++++++++++++++++++++++++++++++---- katana/src/PowerRails.cpp | 12 ++++----- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/etesian/src/AddFeeds.cpp b/etesian/src/AddFeeds.cpp index ca712a75..54aa2144 100644 --- a/etesian/src/AddFeeds.cpp +++ b/etesian/src/AddFeeds.cpp @@ -370,6 +370,22 @@ namespace Etesian { sliceHoles.setSpinSlice0( _yspinSlice0 ); + if (getBlockInstance()) { + Transformation toBlockTransf = getBlockInstance()->getTransformation(); + toBlockTransf.invert(); + for ( Instance* instance : getCell()->getInstances() ) { + if (instance == getBlockInstance()) continue; + if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) { + Box overlapAb = instance->getAbutmentBox(); + toBlockTransf.applyOn( overlapAb ); + overlapAb = topCellAb.getIntersection( overlapAb ); + if (not overlapAb.isEmpty()) { + sliceHoles.merge( overlapAb ); + } + } + } + } + for ( Occurrence occurrence : getBlockCell()->getTerminalNetlistInstanceOccurrences() ) { Instance* instance = static_cast(occurrence.getEntity()); diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 7f639083..952d01d3 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -577,13 +577,24 @@ namespace Etesian { Dots dots ( cmess2, " ", 80, 1000 ); if (not cmess2.enabled()) dots.disable(); - Box topAb = getBlockCell()->getAbutmentBox(); - Transformation topTransformation; - if (getBlockInstance()) topTransformation = getBlockInstance()->getTransformation(); - topTransformation.applyOn( topAb ); - size_t instancesNb = 0; size_t fixedNb = 0; + Box topAb = getBlockCell()->getAbutmentBox(); + Transformation topTransformation; + if (getBlockInstance()) { + topTransformation = getBlockInstance()->getTransformation(); + topTransformation.applyOn( topAb ); + for ( Instance* instance : getCell()->getInstances() ) { + if (instance == getBlockInstance()) continue; + if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) { + if (topAb.intersect(instance->getAbutmentBox())) { + ++instancesNb; + ++fixedNb; + } + } + } + } + for ( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences(getBlockInstance()) ) { ++instancesNb; Instance* instance = static_cast(occurrence.getEntity()); @@ -611,8 +622,37 @@ namespace Etesian { //getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten ); getCell()->flattenNets( getBlockInstance(), Cell::Flags::NoClockFlatten ); + bool tooManyInstances = false; index_t instanceId = 0; + if (getBlockInstance()) { + for ( Instance* instance : getCell()->getInstances() ) { + if (instance == getBlockInstance()) continue; + if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) { + Box overlapAb = topAb.getIntersection( instance->getAbutmentBox() ); + if (not overlapAb.isEmpty()) { + // Upper rounded + int_t xsize = (overlapAb.getWidth () + vpitch - 1) / vpitch; + int_t ysize = (overlapAb.getHeight() + hpitch - 1) / hpitch; + // Lower rounded + int_t xpos = overlapAb.getXMin() / vpitch; + int_t ypos = overlapAb.getYMin() / hpitch; + + instances[instanceId].size = point( xsize, ysize ); + instances[instanceId].list_index = instanceId; + instances[instanceId].area = static_cast(xsize) * static_cast(ysize); + positions[instanceId] = point( xpos, ypos ); + instances[instanceId].attributes = 0; + + _cellsToIds.insert( make_pair(getString(instance->getName()),instanceId) ); + _idsToInsts.push_back( instance ); + ++instanceId; + dots.dot(); + } + } + } + } + for ( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences(getBlockInstance()) ) { if (tooManyInstances or (instanceId == instancesNb)) { diff --git a/katana/src/PowerRails.cpp b/katana/src/PowerRails.cpp index 77748521..a5132673 100644 --- a/katana/src/PowerRails.cpp +++ b/katana/src/PowerRails.cpp @@ -251,17 +251,15 @@ namespace { cdebug_log(159,0) << " getRootNet:" << path << ":" << net << endl; if (net == _blockage) return _blockage; - if (net->getType() == Net::Type::POWER ) return _vdd; if (net->getType() == Net::Type::GROUND) return _vss; - if (net->getType() != Net::Type::CLOCK ) { - return NULL; - } + if (net->getType() != Net::Type::CLOCK ) return NULL; // Track up, *only* for clocks. const Net* upNet = net; if (not path.isEmpty()) { + cdebug_log(159,0) << " Path is *not* empty:" << path << endl; DeepNet* deepClockNet = getTopCell()->getDeepNet( path, net ); if (deepClockNet) { cdebug_log(159,0) << " Deep Clock Net:" << deepClockNet @@ -292,15 +290,17 @@ namespace { } } - cdebug_log(159,0) << " Check againts top clocks ck:" + cdebug_log(159,0) << " Check against top clocks ck:" << ((_ck) ? _ck->getName() : "NULL") << endl; if (_ck) { if (upNet->getName() == _ck->getName()) { + cdebug_log(159,0) << " Clock name matches upNet." << endl; if (isCoreClockNetRouted(upNet)) return _ck; } } + cdebug_log(159,0) << " upNet fixed:" << NetRoutingExtension::isFixed(upNet) << endl; return NetRoutingExtension::isFixed(upNet) ? _blockage : NULL; } @@ -1050,7 +1050,7 @@ namespace { } cdebug_log(159,0) << " rootNet " << rootNet << " (" << rootNet->isClock() << ") " - << go->getCell() << " (" << go->getCell()->isTerminal() << ")" << endl; + << go->getCell() << " (" << go->getCell()->isTerminal() << ")" << endl; const Segment* segment = dynamic_cast(component); if ( segment != NULL ) {