From 2bd18313d10fa7ff92216f931cfd9f5b8a4ffe44 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 25 Sep 2019 18:35:03 +0200 Subject: [PATCH] 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. --- anabatic/src/GCell.cpp | 3 +- cumulus/src/plugins/chip/Chip.py | 4 +- cumulus/src/plugins/chip/PadsCorona.py | 45 +++++++++++------ katana/src/Manipulator.cpp | 7 ++- katana/src/NegociateWindow.cpp | 36 +++++++++++--- katana/src/SegmentFsm.cpp | 68 +++++++++++++------------- katana/src/Track.cpp | 6 --- 7 files changed, 104 insertions(+), 65 deletions(-) diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index 3abe863f..6bdd2945 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -1499,7 +1499,8 @@ namespace Anabatic { size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t count = 0; 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; if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0; diff --git a/cumulus/src/plugins/chip/Chip.py b/cumulus/src/plugins/chip/Chip.py index 7fe5f25a..e5ac9f73 100644 --- a/cumulus/src/plugins/chip/Chip.py +++ b/cumulus/src/plugins/chip/Chip.py @@ -126,8 +126,8 @@ class PlaceRoute ( object ): if not self.conf.useClockTree: self.railsNb -= 1 innerBb = Box( self.conf.coreSize ) - innerBb.inflate( (railsNb * vRailWidth + (railsNb+1) * vRailSpace + self.conf.getSliceHeight()) * 2 - , (railsNb * hRailWidth + (railsNb+1) * hRailSpace + self.conf.getSliceHeight()) * 2 ) + innerBb.inflate( railsNb * vRailWidth + (railsNb+1) * vRailSpace + , railsNb * hRailWidth + (railsNb+1) * hRailSpace ) coronaAb = self.conf.corona.getAbutmentBox() if innerBb.getWidth() > coronaAb.getWidth(): diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index 24878d7f..73ed7b83 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -38,6 +38,7 @@ from Hurricane import RoutingPad from Hurricane import Instance import CRL from CRL import RoutingLayerGauge +import helpers from helpers import trace from helpers.io import ErrorMessage from helpers.io import WarningMessage @@ -661,6 +662,9 @@ class CoreWire ( object ): rg = self.conf.gaugeConf.routingGauge mask = self.padSegment.getLayer().getMask() + trace( 550, ',+', '\tCoreWire._computeCoreLayers()\n' ) + trace( 550, '\tbbSegment: %s\n' % (self.bbSegment) ) + self.symSegmentLayer = None for layerGauge in rg.getLayerGauges(): if layerGauge.getDepth() > self.conf.gaugeConf.topLayerDepth: break @@ -683,28 +687,35 @@ class CoreWire ( object ): self.symSegmentLayer = rg.getLayerGauge( depth+1 ).getLayer() 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() , Layer.EnclosureH|Layer.EnclosureV ) \ + self.symContactLayer.getMinimalSize() - arrayWidth = (self.bbSegment.getWidth() - contactMinSize) / CoreWire.viaPitch - trace( 550, '\tcontactMinSize: %sl, width: %sl, arrayWidth: %d\n' - % (DbU.toLambda(contactMinSize),DbU.toLambda(self.bbSegment.getWidth()),arrayWidth) ) - if arrayWidth < 0: arrayWidth = 0 - if arrayWidth < 3: + arrayWidth = self.symContactSize[0] + arrayCount = (arrayWidth - contactMinSize) / CoreWire.viaPitch + trace( 550, '\tCoreWire.viaPitch: %sl\n' % (DbU.toLambda(CoreWire.viaPitch)) ) + trace( 550, '\tcontactMinSize: %sl, arrayWidth: %sl, arrayCount: %d\n' + % (DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) ) + if arrayCount < 0: arrayCount = 0 + if arrayCount < 3: if self.side & (chip.North|chip.South): - self.arraySize = ( arrayWidth+1, 2 ) + self.arraySize = ( arrayCount+1, 2 ) 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, ',-' ) return raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \ % self.chipNet.getName() ) + trace( 550, ',-' ) return @@ -1086,10 +1097,11 @@ class Corona ( object ): for component in padNet.getExternalComponents(): if isinstance(component,Segment) or isinstance(component,Contact): - bb = component.getBoundingBox() padInstance.getTransformation().applyOn( bb ) if bb.intersect(innerBb): + trace( 550, '\tTerm comp:%s bb:%s\n' % (component,bb) ) + lg = rg.getLayerGauge( component.getLayer() ) depth = lg.getDepth() if depth > self.conf.gaugeConf.topLayerDepth: continue @@ -1118,21 +1130,26 @@ class Corona ( object ): segments = vsegments[ min(vsegments.keys()) ] elif len(hsegments): segments = hsegments[ min(hsegments.keys()) ] - gapWidth = bb.getWidth() - trace( 550, '\tNorth/South but RDir H, gapWidth: %s\n' % DbU.getValueString(gapWidth) ) else: if len(hsegments): inPreferredDir = True segments = hsegments[ min(hsegments.keys()) ] elif len(vsegments): segments = vsegments[ min(vsegments.keys()) ] - gapWidth = bb.getWidth() - trace( 550, '\tEast/West but RDir V, gapWidth: %s\n' % DbU.getValueString(gapWidth) ) coreWires = [] if 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 ) ) count += 1 else: diff --git a/katana/src/Manipulator.cpp b/katana/src/Manipulator.cpp index ad81b722..4229b217 100644 --- a/katana/src/Manipulator.cpp +++ b/katana/src/Manipulator.cpp @@ -1180,6 +1180,10 @@ namespace Katana { kflags |= (flags & AllowTerminalMoveUp) ? Flags::AllowTerminal : 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 (not (flags & AllowLocalMoveUp)) { if (_segment->isLocal()) { @@ -1189,7 +1193,7 @@ namespace Katana { if (not (flags & AllowShortPivotUp)) 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 { if (not _segment->canMoveUp(0.5,kflags)) return false; @@ -1701,7 +1705,6 @@ namespace Katana { isSourceTerminal = false; } - TrackElement* perpandicular = _event->getPerpandiculars()[0]; DataNegociate* data = perpandicular->getDataNegociate(); diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index 50f77a6d..8f7bc91a 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -20,6 +20,7 @@ #include #include "hurricane/Breakpoint.h" #include "hurricane/DebugSession.h" +#include "hurricane/UpdateSession.h" #include "hurricane/Warning.h" #include "hurricane/Bug.h" #include "hurricane/RoutingPad.h" @@ -89,13 +90,21 @@ namespace { AutoSegment* refBase = refSegment->base(); AutoSegment* base = segment->base(); - if ( base and refBase and refData - and ( base->getRpDistance() == 0) - and (refBase->getRpDistance() > 0) - and (refData->getState() > DataNegociate::RipupPerpandiculars) - and ( data->getState() == DataNegociate::RipupPerpandiculars) - and ( data->getRipupCount() > 4)) { - cost.setAtRipupLimit(); + if (base and refBase and refData) { + if ( ( base->getRpDistance() == 0) + and (refBase->getRpDistance() > 0) + and (refData->getState() > DataNegociate::RipupPerpandiculars) + and ( data->getState() == DataNegociate::RipupPerpandiculars) + and ( data->getRipupCount() > 4)) { + cost.setAtRipupLimit(); + } + + if ( refSegment->isNonPref() + and segment->isUnbreakable() + and (data->getState() >= DataNegociate::Minimize) + and (data->getStateCount() >= 2) ) { + cost.setAtRipupLimit(); + } } cost.mergeRipupCount( data->getRipupCount() ); @@ -107,6 +116,10 @@ namespace { } } + if (data->getState() == DataNegociate::MaximumSlack) { + cost.setAtRipupLimit(); + } + if (segment->isGlobal()) { cost.setOverlapGlobal(); if ( (cost.getFlags() & TrackCost::LocalAndTopDepth) @@ -229,6 +242,7 @@ namespace Katana { using Hurricane::tab; using Hurricane::ForEachIterator; using Hurricane::DebugSession; + using Hurricane::UpdateSession; using CRL::Histogram; using CRL::addMeasure; using Anabatic::AutoContact; @@ -592,6 +606,14 @@ namespace Katana { event->process( _eventQueue, _eventHistory, _eventLoop ); 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)) { // _pack( count, false ); //} diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index 71e5e85b..ea8f44b1 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -1208,41 +1208,43 @@ namespace Katana { uint32_t nextState = data->getState(); Manipulator manipulator ( segment, *this ); - switch ( data->getState() ) { - case DataNegociate::RipupPerpandiculars: - nextState = DataNegociate::Minimize; - if (segment->isNonPref() and getCost(0)->isBlockage()) { - cdebug_log(159,0) << "Non-preferred conflicts with a blockage." << endl; - success = manipulator.avoidBlockage(); + if (segment->isNonPref() and (getCost(0)->isBlockage() or getCost(0)->isAtRipupLimit())) { + cdebug_log(159,0) << "Non-preferred conflicts with a blockage or other's at ripup limit." << endl; + success = manipulator.avoidBlockage(); + } + + if (not success) { + switch ( data->getState() ) { + case DataNegociate::RipupPerpandiculars: + nextState = DataNegociate::Minimize; + success = manipulator.ripupPerpandiculars(); if (success) break; - } - success = manipulator.ripupPerpandiculars(); - if (success) break; - case DataNegociate::Minimize: - if (data->getStateCount() >= 2) { - nextState = DataNegociate::Slacken; - } - success = manipulator.minimize(); - if (success) break; - case DataNegociate::Dogleg: - case DataNegociate::Slacken: - if ((success = manipulator.slacken(Flags::HalfSlacken))) { - nextState = DataNegociate::LocalVsGlobal; + case DataNegociate::Minimize: + if (data->getStateCount() >= 2) { + nextState = DataNegociate::Slacken; + } + success = manipulator.minimize(); + if (success) break; + case DataNegociate::Dogleg: + case DataNegociate::Slacken: + if ((success = manipulator.slacken(Flags::HalfSlacken))) { + nextState = DataNegociate::LocalVsGlobal; + 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; - } - 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)) diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index b7bc78fd..e83df655 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -161,7 +161,6 @@ namespace Katana { size_t begin; getBeginIndex( position, begin, state ); - cdebug_log(159,0) << " getSegment(position): begin:" << begin << endl; if (state & (BeginIsTrackMin|EndIsTrackMax)) return NULL; return getSegment(begin); @@ -239,26 +238,21 @@ namespace Katana { // 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 // but still from the same net? - cdebug_log(159,0) << " begin:" << begin << endl; size_t sameNetDelta = 0; if (begin < _segments.size()) { for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet()) ; --begin, ++sameNetDelta ); } - cdebug_log(159,0) << " begin:" << begin << endl; state = 0; if ( (begin == 0) and (position < _segments[0]->getSourceU()) ) { state = BeforeFirstElement; } else { if (begin and not sameNetDelta) begin -= 1; - cdebug_log(159,0) << " begin:" << begin << endl; size_t usedBegin = begin; Interval usedInterval = getOccupiedInterval( usedBegin ); - cdebug_log(159,0) << " position:" << DbU::getValueString(position) - << " " << usedInterval << endl; if (position < usedInterval.getVMax()) state = InsideElement; else