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.
This commit is contained in:
Jean-Paul Chaput 2020-10-23 22:28:04 +02:00
parent 0217ca1f26
commit e6e667c6c7
3 changed files with 67 additions and 11 deletions

View File

@ -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<Instance*>(occurrence.getEntity());

View File

@ -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<Instance*>(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<int_t>( xsize, ysize );
instances[instanceId].list_index = instanceId;
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize);
positions[instanceId] = point<int_t>( 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)) {

View File

@ -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<const Segment*>(component);
if ( segment != NULL ) {