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:
parent
0217ca1f26
commit
e6e667c6c7
|
@ -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());
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
Loading…
Reference in New Issue