More tuning for ARMv2a (95% success, 38/40). Bugs in core2chip.

* Change: In Anabatic::GCell::updateDensity(), all non-passthrough wires
    now have a cost of 0.5 instead of 0.33 for locals.
* Change: In Manipulator::canMoveUp(), increase the "reserve" amount to
    1.0 for "far from terminal" wires (rpDistance > 2).
* Change: In NegociateWindow::NegociateOverlapCost(), always sets "AtRipupLimit"
    when the overlapping segment is nearing it's maximum ripup limit.
    (different detection for non-preferred and regular)
* Change: In SegmentFsm::_slackenStrap(), call avoidBlockage() if it is
    overlapping a blockage *or* a segment at it's ripup limit. I hope I
    didn't create an infinite loop here.
* Bug: In cumulus/plugins/PadsCorona.py, CoreWire._computeCoreLayers(),
    the big contact between symbolic and real was badly computed for
    east/west (was using width instead of height, bummer!).
      In Corona._createCoreWire(), completly screwed computation of the
    side gap, was using a badly initialized value of the "bb" variable.
* Bug: In cumulus/plugins/Chip.py, the computation of the minimal size
    for the corona was wrong, do *not* add the size of the pads and
    multiply by two as it is done by "inflate". This was forcing the user
    to create way to large chips for a given core size.
This commit is contained in:
Jean-Paul Chaput 2019-09-25 18:35:03 +02:00
parent d7931391c0
commit 2bd18313d1
7 changed files with 104 additions and 65 deletions

View File

@ -1499,7 +1499,8 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0; size_t count = 0;
for ( ; isegment != processeds.end(); ++isegment ) { for ( ; isegment != processeds.end(); ++isegment ) {
_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33; //_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33;
_feedthroughs[depth] += 0.50;
localCounts [depth] += 1.0; localCounts [depth] += 1.0;
if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0; if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0;

View File

@ -126,8 +126,8 @@ class PlaceRoute ( object ):
if not self.conf.useClockTree: self.railsNb -= 1 if not self.conf.useClockTree: self.railsNb -= 1
innerBb = Box( self.conf.coreSize ) innerBb = Box( self.conf.coreSize )
innerBb.inflate( (railsNb * vRailWidth + (railsNb+1) * vRailSpace + self.conf.getSliceHeight()) * 2 innerBb.inflate( railsNb * vRailWidth + (railsNb+1) * vRailSpace
, (railsNb * hRailWidth + (railsNb+1) * hRailSpace + self.conf.getSliceHeight()) * 2 ) , railsNb * hRailWidth + (railsNb+1) * hRailSpace )
coronaAb = self.conf.corona.getAbutmentBox() coronaAb = self.conf.corona.getAbutmentBox()
if innerBb.getWidth() > coronaAb.getWidth(): if innerBb.getWidth() > coronaAb.getWidth():

View File

@ -38,6 +38,7 @@ from Hurricane import RoutingPad
from Hurricane import Instance from Hurricane import Instance
import CRL import CRL
from CRL import RoutingLayerGauge from CRL import RoutingLayerGauge
import helpers
from helpers import trace from helpers import trace
from helpers.io import ErrorMessage from helpers.io import ErrorMessage
from helpers.io import WarningMessage from helpers.io import WarningMessage
@ -661,6 +662,9 @@ class CoreWire ( object ):
rg = self.conf.gaugeConf.routingGauge rg = self.conf.gaugeConf.routingGauge
mask = self.padSegment.getLayer().getMask() mask = self.padSegment.getLayer().getMask()
trace( 550, ',+', '\tCoreWire._computeCoreLayers()\n' )
trace( 550, '\tbbSegment: %s\n' % (self.bbSegment) )
self.symSegmentLayer = None self.symSegmentLayer = None
for layerGauge in rg.getLayerGauges(): for layerGauge in rg.getLayerGauges():
if layerGauge.getDepth() > self.conf.gaugeConf.topLayerDepth: break if layerGauge.getDepth() > self.conf.gaugeConf.topLayerDepth: break
@ -683,28 +687,35 @@ class CoreWire ( object ):
self.symSegmentLayer = rg.getLayerGauge( depth+1 ).getLayer() self.symSegmentLayer = rg.getLayerGauge( depth+1 ).getLayer()
self.symContactLayer = rg.getContactLayer( depth ) self.symContactLayer = rg.getContactLayer( depth )
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() ) if self.side & (chip.West|chip.East):
self.symContactSize = ( self.bbSegment.getHeight(), self.bbSegment.getHeight() )
else:
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() )
contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer() contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer()
, Layer.EnclosureH|Layer.EnclosureV ) \ , Layer.EnclosureH|Layer.EnclosureV ) \
+ self.symContactLayer.getMinimalSize() + self.symContactLayer.getMinimalSize()
arrayWidth = (self.bbSegment.getWidth() - contactMinSize) / CoreWire.viaPitch arrayWidth = self.symContactSize[0]
trace( 550, '\tcontactMinSize: %sl, width: %sl, arrayWidth: %d\n' arrayCount = (arrayWidth - contactMinSize) / CoreWire.viaPitch
% (DbU.toLambda(contactMinSize),DbU.toLambda(self.bbSegment.getWidth()),arrayWidth) ) trace( 550, '\tCoreWire.viaPitch: %sl\n' % (DbU.toLambda(CoreWire.viaPitch)) )
if arrayWidth < 0: arrayWidth = 0 trace( 550, '\tcontactMinSize: %sl, arrayWidth: %sl, arrayCount: %d\n'
if arrayWidth < 3: % (DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) )
if arrayCount < 0: arrayCount = 0
if arrayCount < 3:
if self.side & (chip.North|chip.South): if self.side & (chip.North|chip.South):
self.arraySize = ( arrayWidth+1, 2 ) self.arraySize = ( arrayCount+1, 2 )
else: else:
self.arraySize = ( 2, arrayWidth+1 ) self.arraySize = ( 2, arrayCount+1 )
trace( 550, '\tarraySize = (%d,%d)\n' % (self.arraySize[0], self.arraySize[1]) ) trace( 550, '\tarraySize = (%d,%d)\n' % (self.arraySize[0], self.arraySize[1]) )
trace( 550, ',-' )
return return
raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \ raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \
% self.chipNet.getName() ) % self.chipNet.getName() )
trace( 550, ',-' )
return return
@ -1086,10 +1097,11 @@ class Corona ( object ):
for component in padNet.getExternalComponents(): for component in padNet.getExternalComponents():
if isinstance(component,Segment) or isinstance(component,Contact): if isinstance(component,Segment) or isinstance(component,Contact):
bb = component.getBoundingBox() bb = component.getBoundingBox()
padInstance.getTransformation().applyOn( bb ) padInstance.getTransformation().applyOn( bb )
if bb.intersect(innerBb): if bb.intersect(innerBb):
trace( 550, '\tTerm comp:%s bb:%s\n' % (component,bb) )
lg = rg.getLayerGauge( component.getLayer() ) lg = rg.getLayerGauge( component.getLayer() )
depth = lg.getDepth() depth = lg.getDepth()
if depth > self.conf.gaugeConf.topLayerDepth: continue if depth > self.conf.gaugeConf.topLayerDepth: continue
@ -1118,21 +1130,26 @@ class Corona ( object ):
segments = vsegments[ min(vsegments.keys()) ] segments = vsegments[ min(vsegments.keys()) ]
elif len(hsegments): elif len(hsegments):
segments = hsegments[ min(hsegments.keys()) ] segments = hsegments[ min(hsegments.keys()) ]
gapWidth = bb.getWidth()
trace( 550, '\tNorth/South but RDir H, gapWidth: %s\n' % DbU.getValueString(gapWidth) )
else: else:
if len(hsegments): if len(hsegments):
inPreferredDir = True inPreferredDir = True
segments = hsegments[ min(hsegments.keys()) ] segments = hsegments[ min(hsegments.keys()) ]
elif len(vsegments): elif len(vsegments):
segments = vsegments[ min(vsegments.keys()) ] segments = vsegments[ min(vsegments.keys()) ]
gapWidth = bb.getWidth()
trace( 550, '\tEast/West but RDir V, gapWidth: %s\n' % DbU.getValueString(gapWidth) )
coreWires = [] coreWires = []
if segments: if segments:
for segment, bb in segments: for segment, bb in segments:
side.updateGap ( gapWidth ) if not inPreferredDir:
if side.type == chip.North or side.type == chip.South:
trace( 550, '\tNorth/South "%s" but RDir H, gapWidth: %s\n'
% (chipIntNet.getName(),DbU.getValueString(bb.getWidth()) ) )
side.updateGap( bb.getWidth() )
else:
trace( 550, '\tEast/West "%s" but RDir V, gapWidth: %s\n'
% (chipIntNet.getName(),DbU.getValueString(bb.getHeight())) )
side.updateGap( bb.getHeight() )
side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) ) side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) )
count += 1 count += 1
else: else:

View File

@ -1180,6 +1180,10 @@ namespace Katana {
kflags |= (flags & AllowTerminalMoveUp) ? Flags::AllowTerminal : Flags::NoFlags; kflags |= (flags & AllowTerminalMoveUp) ? Flags::AllowTerminal : Flags::NoFlags;
kflags |= (flags & IgnoreContacts ) ? Flags::IgnoreContacts : Flags::NoFlags; kflags |= (flags & IgnoreContacts ) ? Flags::IgnoreContacts : Flags::NoFlags;
//float reserve = 1.0;
float reserve = 0.5;
if (_segment->base() and (_segment->base()->getRpDistance() > 2)) reserve = 1.0;
if (_segment->isFixed()) return false; if (_segment->isFixed()) return false;
if (not (flags & AllowLocalMoveUp)) { if (not (flags & AllowLocalMoveUp)) {
if (_segment->isLocal()) { if (_segment->isLocal()) {
@ -1189,7 +1193,7 @@ namespace Katana {
if (not (flags & AllowShortPivotUp)) return false; if (not (flags & AllowShortPivotUp)) return false;
if (not _segment->canPivotUp(1.0,(kflags & ~Flags::IgnoreContacts))) return false; if (not _segment->canPivotUp(1.0,(kflags & ~Flags::IgnoreContacts))) return false;
} }
if (not _segment->canMoveUp(0.5,kflags)) return false; if (not _segment->canMoveUp(reserve,kflags)) return false;
} }
} else { } else {
if (not _segment->canMoveUp(0.5,kflags)) return false; if (not _segment->canMoveUp(0.5,kflags)) return false;
@ -1701,7 +1705,6 @@ namespace Katana {
isSourceTerminal = false; isSourceTerminal = false;
} }
TrackElement* perpandicular = _event->getPerpandiculars()[0]; TrackElement* perpandicular = _event->getPerpandiculars()[0];
DataNegociate* data = perpandicular->getDataNegociate(); DataNegociate* data = perpandicular->getDataNegociate();

View File

@ -20,6 +20,7 @@
#include <iomanip> #include <iomanip>
#include "hurricane/Breakpoint.h" #include "hurricane/Breakpoint.h"
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Bug.h" #include "hurricane/Bug.h"
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
@ -89,13 +90,21 @@ namespace {
AutoSegment* refBase = refSegment->base(); AutoSegment* refBase = refSegment->base();
AutoSegment* base = segment->base(); AutoSegment* base = segment->base();
if ( base and refBase and refData if (base and refBase and refData) {
and ( base->getRpDistance() == 0) if ( ( base->getRpDistance() == 0)
and (refBase->getRpDistance() > 0) and (refBase->getRpDistance() > 0)
and (refData->getState() > DataNegociate::RipupPerpandiculars) and (refData->getState() > DataNegociate::RipupPerpandiculars)
and ( data->getState() == DataNegociate::RipupPerpandiculars) and ( data->getState() == DataNegociate::RipupPerpandiculars)
and ( data->getRipupCount() > 4)) { and ( data->getRipupCount() > 4)) {
cost.setAtRipupLimit(); cost.setAtRipupLimit();
}
if ( refSegment->isNonPref()
and segment->isUnbreakable()
and (data->getState() >= DataNegociate::Minimize)
and (data->getStateCount() >= 2) ) {
cost.setAtRipupLimit();
}
} }
cost.mergeRipupCount( data->getRipupCount() ); cost.mergeRipupCount( data->getRipupCount() );
@ -107,6 +116,10 @@ namespace {
} }
} }
if (data->getState() == DataNegociate::MaximumSlack) {
cost.setAtRipupLimit();
}
if (segment->isGlobal()) { if (segment->isGlobal()) {
cost.setOverlapGlobal(); cost.setOverlapGlobal();
if ( (cost.getFlags() & TrackCost::LocalAndTopDepth) if ( (cost.getFlags() & TrackCost::LocalAndTopDepth)
@ -229,6 +242,7 @@ namespace Katana {
using Hurricane::tab; using Hurricane::tab;
using Hurricane::ForEachIterator; using Hurricane::ForEachIterator;
using Hurricane::DebugSession; using Hurricane::DebugSession;
using Hurricane::UpdateSession;
using CRL::Histogram; using CRL::Histogram;
using CRL::addMeasure; using CRL::addMeasure;
using Anabatic::AutoContact; using Anabatic::AutoContact;
@ -592,6 +606,14 @@ namespace Katana {
event->process( _eventQueue, _eventHistory, _eventLoop ); event->process( _eventQueue, _eventHistory, _eventLoop );
count++; count++;
// if (event->getSegment()->getNet()->getId() == 239546) {
// UpdateSession::close();
// ostringstream message;
// message << "After processing an event from Net id:239546\n" << event;
// Breakpoint::stop( 0, message.str() );
// UpdateSession::open();
// }
//if (count and not (count % 500)) { //if (count and not (count % 500)) {
// _pack( count, false ); // _pack( count, false );
//} //}

View File

@ -1208,41 +1208,43 @@ namespace Katana {
uint32_t nextState = data->getState(); uint32_t nextState = data->getState();
Manipulator manipulator ( segment, *this ); Manipulator manipulator ( segment, *this );
switch ( data->getState() ) { if (segment->isNonPref() and (getCost(0)->isBlockage() or getCost(0)->isAtRipupLimit())) {
case DataNegociate::RipupPerpandiculars: cdebug_log(159,0) << "Non-preferred conflicts with a blockage or other's at ripup limit." << endl;
nextState = DataNegociate::Minimize; success = manipulator.avoidBlockage();
if (segment->isNonPref() and getCost(0)->isBlockage()) { }
cdebug_log(159,0) << "Non-preferred conflicts with a blockage." << endl;
success = manipulator.avoidBlockage(); if (not success) {
switch ( data->getState() ) {
case DataNegociate::RipupPerpandiculars:
nextState = DataNegociate::Minimize;
success = manipulator.ripupPerpandiculars();
if (success) break; if (success) break;
} case DataNegociate::Minimize:
success = manipulator.ripupPerpandiculars(); if (data->getStateCount() >= 2) {
if (success) break; nextState = DataNegociate::Slacken;
case DataNegociate::Minimize: }
if (data->getStateCount() >= 2) { success = manipulator.minimize();
nextState = DataNegociate::Slacken; if (success) break;
} case DataNegociate::Dogleg:
success = manipulator.minimize(); case DataNegociate::Slacken:
if (success) break; if ((success = manipulator.slacken(Flags::HalfSlacken))) {
case DataNegociate::Dogleg: nextState = DataNegociate::LocalVsGlobal;
case DataNegociate::Slacken: break;
if ((success = manipulator.slacken(Flags::HalfSlacken))) { }
nextState = DataNegociate::LocalVsGlobal; case DataNegociate::LocalVsGlobal:
if (segment->isUnbreakable()) {
nextState = DataNegociate::MaximumSlack;
success = true;
break;
}
case DataNegociate::ConflictSolveByHistory:
case DataNegociate::ConflictSolveByPlaceds:
case DataNegociate::MoveUp:
case DataNegociate::MaximumSlack:
case DataNegociate::Unimplemented:
nextState = DataNegociate::Unimplemented;
break; break;
} }
case DataNegociate::LocalVsGlobal:
if (segment->isUnbreakable()) {
nextState = DataNegociate::MaximumSlack;
success = true;
break;
}
case DataNegociate::ConflictSolveByHistory:
case DataNegociate::ConflictSolveByPlaceds:
case DataNegociate::MoveUp:
case DataNegociate::MaximumSlack:
case DataNegociate::Unimplemented:
nextState = DataNegociate::Unimplemented;
break;
} }
if (not success and (nextState != DataNegociate::Unimplemented)) if (not success and (nextState != DataNegociate::Unimplemented))

View File

@ -161,7 +161,6 @@ namespace Katana {
size_t begin; size_t begin;
getBeginIndex( position, begin, state ); getBeginIndex( position, begin, state );
cdebug_log(159,0) << " getSegment(position): begin:" << begin << endl;
if (state & (BeginIsTrackMin|EndIsTrackMax)) return NULL; if (state & (BeginIsTrackMin|EndIsTrackMax)) return NULL;
return getSegment(begin); return getSegment(begin);
@ -239,26 +238,21 @@ namespace Katana {
// I guess this has been written for the case of overlapping segments from the same // I guess this has been written for the case of overlapping segments from the same
// net, we find the first one of the overlapped sets. But what if they are not overlapping // net, we find the first one of the overlapped sets. But what if they are not overlapping
// but still from the same net? // but still from the same net?
cdebug_log(159,0) << " begin:" << begin << endl;
size_t sameNetDelta = 0; size_t sameNetDelta = 0;
if (begin < _segments.size()) { if (begin < _segments.size()) {
for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet()) for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet())
; --begin, ++sameNetDelta ); ; --begin, ++sameNetDelta );
} }
cdebug_log(159,0) << " begin:" << begin << endl;
state = 0; state = 0;
if ( (begin == 0) and (position < _segments[0]->getSourceU()) ) { if ( (begin == 0) and (position < _segments[0]->getSourceU()) ) {
state = BeforeFirstElement; state = BeforeFirstElement;
} else { } else {
if (begin and not sameNetDelta) begin -= 1; if (begin and not sameNetDelta) begin -= 1;
cdebug_log(159,0) << " begin:" << begin << endl;
size_t usedBegin = begin; size_t usedBegin = begin;
Interval usedInterval = getOccupiedInterval( usedBegin ); Interval usedInterval = getOccupiedInterval( usedBegin );
cdebug_log(159,0) << " position:" << DbU::getValueString(position)
<< " " << usedInterval << endl;
if (position < usedInterval.getVMax()) if (position < usedInterval.getVMax())
state = InsideElement; state = InsideElement;
else else