// This file is part of the Coriolis Project. // Copyright (C) Laboratoire LIP6 - Departement ASIM // Universite Pierre et Marie Curie // // Main contributors : // Christophe Alexandre // Sophie Belloeil // Hugo Clément // Jean-Paul Chaput // Damien Dupuis // Christian Masson // Marek Sroka // // The Coriolis Project is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // The Coriolis Project is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with the Coriolis Project; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // // License-Tag // // Date : 29/01/2004 // Author : Christophe Alexandre // // Authors-Tag #include "Cell.h" #include "HyperNet.h" USING_NAMESPACE_HURRICANE #include "CTimer.h" #include "CDataBase.h" #include "CCellGauge.h" using namespace CRL; #include "Nimbus.h" using namespace NIMBUS; #include "Surface.h" #include "Row.h" #include "SimAnnealingPlacer.h" #include "BBPlacer.h" #include "Mauka.h" namespace MAUKA { namespace { Name MaukaName("Mauka"); } Mauka::Mauka(Cell* cell) // ************************* : Inherit(cell) , _params() , _displaySlot(NULL) , _instanceOccurrencesVector() , _instanceOccurrencesMap() , _instanceWidths() , _instanceNets() , _nets() , _netInstances() , _netInitX() , _netInitY() , _hasInitX() , _hasInitY() , _surface(NULL) , _simAnnealingPlacer(NULL) , _bbPlacer(NULL) {} Mauka* Mauka::Create(Cell* cell, double searchratio, Box placementbox) // ******************************************************************* { Mauka* mauka = new Mauka(cell); mauka->_PostCreate(placementbox, searchratio); return mauka; } void Mauka::_PostCreate(Box& placementbox, double searchratio) // *********************************************************** { Inherit::_PostCreate(); Construct(); //_simAnnealingPlacer = new SimAnnealingPlacer(this, 1, 0.0, 0.0); _simAnnealingPlacer = new SimAnnealingPlacer(this, 0.9, 0.05, 0.05); _displaySlot = DisplaySlot::Create(GetCell(),MaukaName,139,0,139); _surface = Surface::Create(this, placementbox, searchratio); _simAnnealingPlacer->Init(); //Plot(); } #if 0 void Mauka::ReInit() // ******************* { Box placementBox = _surface->GetBox(); _surface->Delete(); _simAnnealingPlacer->Delete(); _surface = Surface::Create(this, placementBox); _simAnnealingPlacer = SimAnnealingPlacer::Create(this); } #endif void Mauka::Run() { CTimer timer; timer.Start(); while (_simAnnealingPlacer->Iterate()) ; timer.Stop(); if (_verbosity.MajorStatsIsOn()) { _simAnnealingPlacer->DisplayResults(); } if (_params.plotBins) { //PlotBinsStats(); } if (_verbosity.SystemResourcesIsOn()) { cout << endl << " o Simulated Annealing run took " << timer.GetUserTime() << " s ..." << endl; } //Plot(); _bbPlacer = new BBPlacer(this); _bbPlacer->Run(); _bbPlacer->Save(); //Plot(); } namespace { void VerifyPathCellBox(const Occurrence& occurrence) //On occurrence Path set all cells Abox to (0,0,0,0) if Box is empty //This avoids bad Transfos on Path { Path path = occurrence.GetPath(); while (!path.IsEmpty()) { Instance* instance = path.GetHeadInstance(); Cell* model = instance->GetMasterCell(); if (model->GetAbutmentBox().IsEmpty()) { model->SetAbutmentBox(Box(Point(0,0), Point(0,0))); } path = path.GetTailPath(); } } } void Mauka::Construct() // ********************** { typedef map InstanceOccurrenceMap; typedef set InstanceSet; typedef map NetMap; InstanceSet instanceSet; NetMap netMap; unsigned instanceId = 0; unsigned netId = 0; Unit standardCellHeight = 0; for_each_occurrence(occurrence, GetCell()->GetLeafInstanceOccurrences()) { Instance* instance = static_cast(occurrence.GetEntity()); if (!instance->IsFixed()) { //cerr << "unplaced " << occurrence << occurrence.GetBoundingBox() << endl; Cell* model = instance->GetMasterCell(); Unit insWidth = model->GetAbutmentBox().GetWidth(); Unit insHeight = model->GetAbutmentBox().GetHeight(); if (standardCellHeight == 0) standardCellHeight = insHeight; else if (insHeight != standardCellHeight) { throw Error("All non-standard instances : " + GetString(instance->GetName()) + " must be placed"); } _instanceOccurrencesVector.push_back(occurrence); //VerifyPathCellBox(occurrence); _instanceWidths.push_back(insWidth); InstanceSet::iterator isit = instanceSet.find(instance); if (isit != instanceSet.end()) { cerr << "Unplaced Instance : " << *isit << endl; cerr << "Unplaced Occurrence : " << occurrence << endl; cerr << (*isit)->GetPlacementStatus() << endl; throw Error("Each unplaced instance must have one occurrence only"); } _instanceOccurrencesMap[occurrence] = instanceId++; instanceSet.insert(instance); _instanceNets.push_back(UVector()); } end_for; } if (_instanceOccurrencesVector.size() == 0) throw Error("No Instance to place..."); typedef set NetSet; NetSet treatedNets; for (InstanceOccurrencesVector::const_iterator iovit = _instanceOccurrencesVector.begin(); iovit != _instanceOccurrencesVector.end(); iovit++) { Instance* instance = static_cast(iovit->GetEntity()); for_each_plug(plug, instance->GetConnectedPlugs()) { Net* net = plug->GetNet(); if (net->IsGlobal()) continue; typedef list InstanceOccurrenceList; InstanceOccurrenceList instanceOccurrenceList; Occurrence rootNetOccurrence = GetHyperNetRootNetOccurrence(Occurrence(net, iovit->GetPath())); Net* rootNet = static_cast(rootNetOccurrence.GetEntity()); NetSet::iterator snit = treatedNets.find(rootNet); if (snit != treatedNets.end()) continue; treatedNets.insert(rootNet); HyperNet hyperNet(rootNetOccurrence); typedef list PointList; PointList pointList; for_each_occurrence(occurrence, hyperNet.GetNetOccurrences()) { Instance* instance = occurrence.GetPath().GetTailInstance(); if (instance && instance->IsLeaf()) { Occurrence instanceOccurrence = Occurrence(instance, occurrence.GetPath().GetHeadPath()); if (instance->IsFixed()) pointList.push_back(instanceOccurrence.GetBoundingBox().GetCenter()); else instanceOccurrenceList.push_back(instanceOccurrence); } end_for; } unsigned pointListSize = pointList.size(); Point fixedPoint(0,0); if (pointListSize > 0) { for (PointList::iterator plit = pointList.begin(); plit != pointList.end(); plit++) { fixedPoint.SetX(fixedPoint.GetX() + plit->GetX() / pointListSize); fixedPoint.SetY(fixedPoint.GetY() + plit->GetY() / pointListSize); } } if ((instanceOccurrenceList.size() < 2) && pointListSize == 0) continue; _netInstances.push_back(UVector()); _nets.push_back(net); if (pointListSize > 0) { _netInitX.push_back(fixedPoint.GetX()); _netInitY.push_back(fixedPoint.GetY()); _hasInitX.push_back(true); _hasInitY.push_back(true); } else { _netInitX.push_back(0); _netInitY.push_back(0); _hasInitX.push_back(false); _hasInitY.push_back(false); } netMap[net] = netId; for (InstanceOccurrenceList::iterator iolit = instanceOccurrenceList.begin(); iolit != instanceOccurrenceList.end(); iolit++) { InstanceOccurrenceMap::const_iterator iomit = _instanceOccurrencesMap.find(*iolit); if (iomit == _instanceOccurrencesMap.end()) { cerr << "cannot find " << iomit->first << endl; throw Error("Error in netsInstances construction in SimAnnealingPlacer"); } _netInstances.back().push_back(iomit->second); _instanceNets[iomit->second].push_back(netId); } ++netId; end_for; } } #if DEBUG //debug ... display netlist for (unsigned instanceId = 0; instanceId < _instanceOccurrencesVector.size(); instanceId++) { cerr << "instance " << _instanceOccurrencesVector[instanceId] << endl; cerr << "is connected to " << endl; for (UVector::const_iterator uvit = _instanceNets[instanceId].begin(); uvit != _instanceNets[instanceId].end(); uvit++) { unsigned netid = *uvit; cerr << _nets[netid] << endl; for (UVector::const_iterator nuvit = _netInstances[netid].begin(); nuvit != _netInstances[netid].end(); nuvit++) { cerr << _instanceOccurrencesVector[*nuvit] << endl; } cerr << endl; } cerr << endl; } #endif } bool Mauka::Iterate() // ****************** { bool canContinue = _simAnnealingPlacer->Iterate(); Save(); return canContinue; } void Mauka::_PreDelete() // ********************* { _surface->Delete(); if (_simAnnealingPlacer) delete _simAnnealingPlacer; if (_bbPlacer) delete _bbPlacer; _displaySlot->Delete(); Inherit::_PreDelete(); } Record* Mauka::_GetRecord() const // ************************ { Record* record = Inherit::_GetRecord(); if (record) { record->Add(GetSlot("Surface", _surface)); } return record; } const Name& Mauka::GetName() const // ******************************* { return MaukaName; } void Mauka::Save() const // ********************* { if (_bbPlacer) _bbPlacer->Save(); else if (_simAnnealingPlacer) _simAnnealingPlacer->Save(); } Mauka* GetMauka(const Cell* cell) // ****************************** { return static_cast(GetCEngine(cell, MaukaName)); } namespace { class TestSubRow : public Box { public: Unit _size; // sum of the contained instances width public: TestSubRow(const Box& box): Box(box), _size(0) {} }; typedef list TestSubRowsList; typedef vector InstanceOccurrencesVector; typedef list InstanceOccurrencesList; void DestroyTestSubRows(TestSubRowsList& testsubrowslist) { for (TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); tsrlit != testsubrowslist.end(); tsrlit++) { delete *tsrlit; } testsubrowslist.clear(); } struct SortInstanceOccurrencesByWidth { bool operator()(Occurrence occurrence1, Occurrence occurrence2) { Instance* instance1 = static_cast(occurrence1.GetEntity()); Instance* instance2 = static_cast(occurrence2.GetEntity()); return instance1->GetAbutmentBox().GetWidth() > instance2->GetAbutmentBox().GetWidth(); } }; bool TryDisplayInstancesInSubRows( InstanceOccurrencesVector& instanceoccurrencesvector, TestSubRowsList& testsubrowslist) { // Try Insert instances in subrows sort(instanceoccurrencesvector.begin(), instanceoccurrencesvector.end(), SortInstanceOccurrencesByWidth()); TestSubRowsList::iterator tsrlit = testsubrowslist.begin(); InstanceOccurrencesVector::const_iterator insIterator = instanceoccurrencesvector.begin(); InstanceOccurrencesVector::const_iterator lastLoopInsertedInsIterator = insIterator; while(insIterator != instanceoccurrencesvector.end()) { if (tsrlit == testsubrowslist.end()) { tsrlit = testsubrowslist.begin(); if (lastLoopInsertedInsIterator != insIterator) lastLoopInsertedInsIterator = insIterator; else { return false; } } TestSubRow* testSubRow = *tsrlit; Instance* instance = static_cast(insIterator->GetEntity()); Cell* model = instance->GetMasterCell(); Unit insWidth = model->GetAbutmentBox().GetWidth(); if (insWidth <= testSubRow->GetWidth() - testSubRow->_size) { testSubRow->_size += insWidth; ++insIterator; } ++tsrlit; } return true; } } bool TestMaukaConstruction(Cell* cell, GCell* gcell) // ************************************************* { Unit pitch = GetCDataBase()->GetDefaultCGPitch(); Unit sliceHeight = GetCDataBase()->GetDefaultCGSliceHeight(); const Box& box = gcell->GetBox(); if (box.IsEmpty() || box.IsPonctual() ||box.IsFlat()) throw Error("Wrong Box for GCell"); if (box.GetHeight() % sliceHeight) throw Error("Box Height must be a multiple of Slice Height"); InstanceOccurrencesList fixedInstanceOccurrenceList; InstanceOccurrencesVector toPlaceInstanceOccurrencesVector; //search for preplaced leaf instances Unit instanceToPlaceWidthMax = 0; for_each_occurrence(occurrence, cell->GetLeafInstanceOccurrencesUnder(gcell->GetBox())) { Instance* instance = static_cast(occurrence.GetEntity()); if (instance->IsFixed()) fixedInstanceOccurrenceList.push_back(occurrence); else { Cell* model = instance->GetMasterCell(); Unit insWidth = model->GetAbutmentBox().GetWidth(); toPlaceInstanceOccurrencesVector.push_back(occurrence); if (instanceToPlaceWidthMax > insWidth) instanceToPlaceWidthMax = insWidth; } end_for; } Unit binWidthMax = GetUnit((unsigned)( 2.0 * GetValue(instanceToPlaceWidthMax) / GetValue(pitch)) * GetValue(pitch)); Unit binWidthMin = GetUnit((unsigned)( GetValue(binWidthMax) / (GetValue(pitch) * 2)) * GetValue(pitch)); TestSubRowsList testSubRowsList; if (fixedInstanceOccurrenceList.size() != 0) { int width = (unsigned)(gcell->GetWidth() / pitch); //number of x pitch int height = (unsigned)(gcell->GetHeight() / sliceHeight); //number of y slices Mauka::PrePlaceTab prePlaceTab(height, Mauka::PrePlaceRow(width, false)); for (InstanceOccurrencesList::iterator iolit = fixedInstanceOccurrenceList.begin(); iolit != fixedInstanceOccurrenceList.end(); iolit++) { Instance* instance = static_cast(iolit->GetEntity()); Box instanceAbutmentBox = instance->GetAbutmentBox(); iolit->GetPath().GetTransformation().ApplyOn(instanceAbutmentBox); Box preplacedBox = gcell->GetIntersection(instanceAbutmentBox); Unit insWidth = preplacedBox.GetWidth(); Unit insHeight = preplacedBox.GetHeight(); int insPitchWidth = (int)(insWidth / pitch); // largeur ramene au pitch int insSliceHeight = (int)(insHeight / sliceHeight); // hauteur ramene a la hauteur du slice int ypos = (int)((preplacedBox.GetYMin() - gcell->GetYMin()) / sliceHeight); // position en y ramene au slice int xpos = (int)((preplacedBox.GetXMin() - gcell->GetXMin()) / pitch); // position en x ramene au pitch for (int yit = ypos; yit < ypos + insSliceHeight; yit++) { for (int xit = xpos; xit < xpos + insPitchWidth; xit++) { if ( (xit > width - 1) || (yit > height - 1) || (xit < 0 ) || (yit < 0 ) ) { cerr << " o ERROR : " << *iolit << " out of the abutment box" << endl; exit(1); } if (prePlaceTab[yit][xit] == false) { prePlaceTab[yit][xit] = true; } else { cerr << " o ERROR : " << *iolit << " badly placed .... There is already an instance at its position ...." << endl; exit (1); } } } } for (int y = 0; y < (int)prePlaceTab.size(); y++) { int x = 0; while (x < (int)prePlaceTab[y].size()) { while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == true)) ++x; Unit subRowXMin = gcell->GetXMin() + x * pitch; if (x >= (int)prePlaceTab[y].size()) break; while ((x < (int)prePlaceTab[y].size()) && (prePlaceTab[y][x] == false)) ++x; Unit subRowXMax = gcell->GetXMin() + x * pitch; if (subRowXMax - subRowXMin > binWidthMin) { testSubRowsList.push_back(new TestSubRow( Box(subRowXMin, gcell->GetYMin() + y * sliceHeight , subRowXMax, gcell->GetYMin() + (y+1) * sliceHeight) )); } } } } else { for (Unit ymin = gcell->GetYMin(); ymin <= gcell->GetYMax() - sliceHeight; ymin += sliceHeight) { testSubRowsList.push_back(new TestSubRow( Box(gcell->GetXMin(), ymin, gcell->GetXMax(), ymin + sliceHeight) )); } } bool tryInstanceInsertion = TryDisplayInstancesInSubRows(toPlaceInstanceOccurrencesVector, testSubRowsList); DestroyTestSubRows(testSubRowsList); return tryInstanceInsertion; } void Mauka::PlotBinsStats() const // ****************************** { ofstream out("binsstats.gpl"); out << "set noxtics" << endl << "set noytics" << endl << "set noborder" << endl << "set nokey" << endl << "set title '" << GetCell()->GetName() << "'" << endl << "#set terminal postscript eps color solid" << endl << "#set output 'binsstats.ps'" << endl; _surface->PlotBinsStats(out); } void Mauka::Plot() const // ********************* { static unsigned count = 0; string cellNameString = GetString(GetCell()->GetName()) + "_" + GetString(count) + ".gpl"; ++count; ofstream out(cellNameString.c_str()); out << "set noxtics" << endl << "set noytics" << endl << "set noborder" << endl << "set nokey" << endl << "set title '" << cellNameString << "'" << endl << "#set terminal postscript eps color solid" << endl << "#set output '" << cellNameString << ".ps'" << endl; Box boundingBox = _surface->GetBox(); boundingBox.Merge(PlotFixedPointsLabels(out)); out << "set xrange[" << boundingBox.GetXMin() << ":" << boundingBox.GetXMax() << "]" << endl << "set yrange[" << boundingBox.GetYMin() << ":" << boundingBox.GetYMax() << "]" << endl; out << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; // << "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4" << endl; _surface->Plot(out); if (_bbPlacer) _bbPlacer->Plot(out); else _simAnnealingPlacer->Plot(out); out << "pause -1 'press any key'" << endl; } Box Mauka::PlotFixedPointsLabels(ofstream& out) const // **************************************************** { Box boundingBox; out << "#FixedPoints" << endl; for (unsigned i = 0; i < _netInstances.size(); i++) { if (_hasInitX[i]) { out << "set label \"" << GetString(_nets[i]->GetName()) << "\" at " << _netInitX[i] << "," << _netInitY[i] << " center" << endl; } boundingBox.Merge(_netInitX[i], _netInitY[i]); } return boundingBox; } void Mauka::Hide() { if (_displaySlot != NULL) { _displaySlot->Hide(); } } void Mauka::Show() { if (_displaySlot != NULL) { _displaySlot->Show(); } } unsigned Mauka::GetRandomInstanceId() const { unsigned instanceId = (unsigned)((double)_instanceOccurrencesVector.size() * rand() / (RAND_MAX + 1.0)); return instanceId; } }