1 
2 // This file is part of the Alliance Project.
3 // Copyright (C) Laboratoire LIP6 - Departement ASIM
4 // Universite Pierre et Marie Curie
5 //
6 // The Alliance Project  is free software;  you can  redistribute it and/or
7 // modify  it  under the  terms  of  the  GNU  General  Public License  as
8 // published by  the Free  Software Foundation; either  version 2  of  the
9 // License, or (at your option) any later version.
10 //
11 // The Alliance Project  is distributed in the hope that it will be useful,
12 // but  WITHOUT  ANY  WARRANTY;  without  even  the  implied  warranty  of
13 // MERCHANTABILITY  or  FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy  of  the  GNU  General  Public  License
17 // along with  the Alliance Project;  if  not,  write to the  Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 //
21 // License-Tag
22 //
23 // Date   : 29/01/2004
24 // Author : Christophe Alexandre  <Christophe.Alexandre@lip6.fr>
25 //
26 // Authors-Tag
27 #include <unistd.h>
28 #include <string.h>
29 #include <set>
30 #include <algorithm>
31 #include <string>
32 using namespace std;
33 
34 #include "mut.h"
35 #include "mph.h"
36 #include "mpu.h"
37 #include "mlo.h"
38 #include "mlu.h"
39 
40 #include "iocheader.h"
41 #include "PMove.h"
42 #include "PConstants.h"
43 #include "PCommon.h"
44 #include "PPlacement.h"
45 
46 struct CompPInsByWidth {
operator ()CompPInsByWidth47     bool operator()(PIns* Ins1, PIns* Ins2) {
48 	return (Ins1->GetWidth() > Ins2->GetWidth());
49     }
50 };
51 
~PPlacement()52 PPlacement::~PPlacement()
53 {
54     if (_verbose)
55     {
56 	cout << " o Destruction of DATABASE ...." << endl;
57     }
58 
59     for (PFixedInss::iterator fit = _fixedInss.begin();
60 	    fit != _fixedInss.end();
61 	    fit++)
62     {
63 	delete *fit;
64     }
65 
66     for (PToPlaceInss::iterator toit = _toPlaceInss.begin();
67 	    toit != _toPlaceInss.end();
68 	    toit++)
69     {
70 	delete *toit;
71     }
72 
73     for (PCons::iterator cit = _cons.begin();
74 	    cit != _cons.end();
75 	    cit++)
76     {
77 	delete *cit;
78     }
79 
80     for (PONets::iterator nit = _nets.begin();
81 	    nit != _nets.end();
82 	    nit++)
83     {
84 	delete *nit;
85     }
86 
87     for (PRows::iterator rit = _rows.begin();
88 	    rit != _rows.end();
89 	    rit++)
90     {
91 	delete *rit;
92     }
93 
94     for (PDetSubRows::iterator srit = _detSubRows.begin();
95 	    srit != _detSubRows.end();
96 	    srit++)
97     {
98 	delete *srit;
99     }
100 }
101 
102 void
Init(lofig * fig,int NbRows)103 PPlacement::Init(lofig* fig, int NbRows)
104 {
105     rflattenlofig(fig, YES, YES);
106     lofigchain(fig);
107     _fig = fig;
108     _dx = _dy = 0;
109     // construction des tables
110     PNetMap pnetmap;
111     PInsMap pinsmap;
112     PConMap pconmap;
113     PFixedMap fixedmap;
114     PLoconMap ploconmap;
115 
116     if (_prePlace)
117     {
118 	rflattenphfig(_prePlaceFig, YES, YES);
119 	for (phins* pins = _prePlaceFig->PHINS; pins; pins = pins->NEXT)
120 	{
121 	    fixedmap[pins->INSNAME] = 1;
122 	}
123 
124 	_dx = _prePlaceFig->XAB1;
125 	_dy = _prePlaceFig->YAB1;
126 
127 	for (phins* pins = _prePlaceFig->PHINS; pins; pins = pins->NEXT)
128 	{
129 	    // on elimine les tie et rowend
130 	    // qui peuvent etre dans la figure physique sans etre
131 	    // dans la figure logique ....
132 	    if (IsTie(pins))
133 	    {
134 		continue;
135 	    }
136 	    // on verifie que la loins existe en memoire
137 	    loins* ins = getloins(_fig, pins->INSNAME);
138 	    // verification de la coherence figure logique / figure physique
139 	    if (ins->FIGNAME != pins->FIGNAME)
140 	    {
141 		cerr << " o ERROR: The logical figure and the physical figure are not coherent:" << endl
142 		     << "   Logical Instance: " << ins->INSNAME << " -> logical model: "<< ins->FIGNAME << endl
143 		     << "   Physical Instance: " << pins->INSNAME << " -> physical model: "<< pins->FIGNAME << endl;
144 		exit(1);
145 	    }
146 	    PFixedIns* fixedins = InsertFixedIns(ins, pins, _dx, _dy);
147 	    pinsmap[ins->INSNAME] = fixedins;
148 	}
149 
150         if (_prePlaceFig->PHCON &&
151                 (_placeCons || _ringPlaceCons || _iocFile))
152         {
153             cerr << " o ERROR: impossible to have simultaneously preplaced connectors" << endl
154                  << "          and automatically placed connectors" << endl;
155             exit(1);
156 
157         }
158 
159         for (phcon* pcon = _prePlaceFig->PHCON; pcon; pcon = pcon->NEXT)
160         {
161             locon* lCon = getlocon(_fig, pcon->NAME);
162             //generates an error if no locon
163             PCon* pCon = InsertCon(lCon, pcon, _dx, _dy);
164             pconmap[pcon->NAME] = pCon;
165         }
166     }
167 
168 
169     for (loins* ins = fig->LOINS; ins; ins = ins->NEXT)
170     {
171 	PFixedMap::iterator fit = fixedmap.find(ins->INSNAME);
172 	if (fit == fixedmap.end())
173 	{
174 	    // on evite de compter deux fois le meme net pour
175 	    // chaque instance.....
176 	    phfig* phmodel = getphfig(ins->FIGNAME, '0');
177 	    int height = (int)((double)(phmodel->YAB2 - phmodel->YAB1) / PITCH + 0.5);
178 	    if (height != ROWHEIGHT)
179 	    {
180 		cerr << " o ERROR : All cells must have the same height: i cannot place the instance: "
181 		     << ins->INSNAME << endl;
182 		exit(1);
183 	    }
184 	    PToPlaceIns* toplaceins = InsertToPlaceIns(ins);
185 	    pinsmap[ins->INSNAME] = toplaceins;
186 	}
187     }
188     _nInsToPlace = _toPlaceInss.size();
189 
190     // Traitement des connecteurs ....
191     if (_placeCons || (_ringPlaceCons && !_iocFile))
192     {
193 	for (locon* con = fig->LOCON; con; con = con->NEXT)
194 	{
195 	    losig* sig = con->SIG;
196 	    if (!IsSpecialNet(sig))
197 	    {
198 		PCon* pcon = InsertCon(con);
199 		pconmap[con->NAME] = pcon;
200 	    }
201 	}
202     }
203 
204     for (locon* con = fig->LOCON; con; con = con->NEXT)
205 	ploconmap[con->NAME] = con;
206 
207     // traitement de l'emplacement des connecteurs
208     // creation des PCon si fichier ioc
209     if (_iocFile)
210     {
211 	ParseIocFile(ploconmap);
212 	for (PCons::iterator pcon = _cons.begin() ; pcon != _cons.end(); pcon++)
213 	  pconmap[(*pcon)->GetLocon()->NAME] = *pcon;
214     }
215 
216     for (losig* sig = fig->LOSIG; sig; sig = sig->NEXT)
217     {
218 	if (!IsSpecialNet(sig))
219 	{
220 	    set<loins*> siginsset;
221 	    int totreatinscpt = 0;
222 	    int elemcpt = 0;
223 	    for (chain_list* it = (chain_list *)(getptype(sig->USER, (long)LOFIGCHAIN)->DATA);
224 		    it;
225 		    it = it->NEXT)
226 	    {
227 		locon_list* con = (locon_list*)(it->DATA);
228 		if (con->TYPE == EXTERNAL) {
229 		    if ( (_prePlaceFig && _prePlaceFig->PHCON)
230                             || _placeCons || _ringPlaceCons || _iocFile) {
231                         PConMap::iterator cit = pconmap.find(con->NAME);
232                         if (cit != pconmap.end()) {
233                             ++totreatinscpt;
234                         }
235 		    }
236 		}
237 		else
238 		{
239             loins* ins = (loins*)(con->ROOT);
240 		    set<loins*>::iterator liit = siginsset.find(ins);
241 		    if (liit == siginsset.end())
242 		    {
243 			++totreatinscpt;
244 			siginsset.insert(ins);
245 		    }
246 		}
247 		++elemcpt;
248 	    }
249 	    if (elemcpt < 2)
250 	    {
251 		cerr << " o OCP Warning: strange net detected ...: " << endl;
252 		cerr << " o Net:" << endl;
253 		cerr << " o ";
254 		PrintLosig(cerr, sig);
255 		if (elemcpt == 0)
256 		    cerr << " o is not connected ......" << endl;
257 		if (elemcpt == 1)
258 		{
259 		    cerr << " o is connected to only one element: ";
260 		    chain_list* it = (chain_list *)(getptype(sig->USER, (long)LOFIGCHAIN)->DATA);
261 		    locon_list* con = (locon_list*)(it->DATA);
262 		    if (con->TYPE == EXTERNAL)
263 		    {
264 			cerr << "connector " << con->NAME;
265 		    }
266 		    else
267 		    {
268             loins* ins = (loins*)(con->ROOT);
269 			cerr << "instance " << ins->INSNAME;
270 		    }
271 		    cerr << endl;
272 		}
273 
274 	    }
275 
276 	    PONet* net = InsertNet(sig);
277 	    pnetmap[sig->INDEX] = net;
278 	}
279 	else {
280 	    cerr << " o Special Net detected : " << getsigname(sig) << endl;
281 	}
282     }
283 
284 
285     for (loins* ins = fig->LOINS ; ins ; ins = ins->NEXT)
286     {
287 	set<losig*> inssigset;
288 	PInsMap::iterator iit = pinsmap.find(ins->INSNAME);
289 	if (iit == pinsmap.end())
290 	{
291 	    cerr << "ins " << ins->INSNAME << " is not present in data...." << endl;
292 	    exit(1);
293 	}
294 	PElem::PNets& netvector = iit->second->GetNets();
295 	for (locon* con = ins->LOCON ; con ; con = con->NEXT)
296 	{
297 	    losig* sig = con->SIG;
298 	    set<losig*>::iterator lsit = inssigset.find(sig);
299 	    if (lsit == inssigset.end())
300 	    {
301 		if (!IsSpecialNet(sig))
302 		{
303 		    PNetMap::iterator nit = pnetmap.find(sig->INDEX);
304 		    if (nit == pnetmap.end())
305 		    {
306 			cerr << "net " << sig->INDEX << " is not present in data...." << endl;
307 			exit(1);
308 		    }
309 		    netvector.push_back(nit->second);
310 		    inssigset.insert(sig);
311 		}
312 	    }
313 	}
314     }
315 
316     if ( (_prePlaceFig && _prePlaceFig->PHCON)
317             || _placeCons || _ringPlaceCons || _iocFile)
318     {
319 	for (locon* con = fig->LOCON; con; con = con->NEXT)
320 	{
321 	    losig* sig = con->SIG;
322 	    if (!IsSpecialNet(sig))
323 	    {
324 		PConMap::iterator cit = pconmap.find(con->NAME);
325 		if (cit != pconmap.end())
326 		{
327 		  PElem::PNets& netvector = cit->second->GetNets();
328 		  PNetMap::iterator nit = pnetmap.find(sig->INDEX);
329 		  if (nit == pnetmap.end())
330 		  {
331 		      cerr << "net " << sig->INDEX
332 			  << " is not present in data...." << endl;
333 		      exit(1);
334 		  }
335 		  netvector.push_back(nit->second);
336 		}
337 	    }
338 	}
339     }
340 
341     for (losig* sig = fig->LOSIG ; sig ; sig=sig->NEXT)
342     {
343 	set<loins*> siginsset;
344 	if (!IsSpecialNet(sig))
345 	{
346 	    PNetMap::iterator nit = pnetmap.find(sig->INDEX);
347 	    if (nit == pnetmap.end())
348 	    {
349 		cerr << "net " << sig->INDEX << " is not present in data...." << endl;
350 		exit(1);
351 	    }
352 	    PNet::PElems& elemsvector = nit->second->GetElems();
353 	    for (chain_list* it = (chain_list *)(getptype(sig->USER, (long)LOFIGCHAIN)->DATA);
354 		    it;
355 		    it = it->NEXT)
356 	    {
357 		locon_list* con = (locon_list*)(it->DATA);
358 		if (con->TYPE == INTERNAL)
359 		{
360             loins* ins = (loins*)(con->ROOT);
361 		    set<loins*>::iterator liit = siginsset.find(ins);
362 		    if (liit == siginsset.end())
363 		    {
364 			PInsMap::iterator iit = pinsmap.find(ins->INSNAME);
365 			if (iit == pinsmap.end())
366 			{
367 			    cerr << "ins " << ins->INSNAME << " is not present in data...." << endl;
368 			    exit(1);
369 			}
370 			elemsvector.push_back(iit->second);
371 			siginsset.insert(ins);
372 		    }
373 		}
374 		else if ( (_prePlaceFig && _prePlaceFig->PHCON)
375                         || _placeCons || _ringPlaceCons || _iocFile)
376 		{
377 
378 		    PConMap::iterator cit = pconmap.find(con->NAME);
379 		    if (cit != pconmap.end())
380 		    {
381 			elemsvector.push_back(cit->second);
382 		    }
383 		}
384 
385 	    }
386 	}
387 
388     }
389 
390     if (_verbose)
391     {
392 	cout << " o Number total of instances is ....  " << _fixedInss.size()+ _toPlaceInss.size() << endl;
393 	cout << " o Number of instances to place is ....  " << _toPlaceInss.size() << endl;
394 	cout << " o Number of instances already placed is ....  " << _fixedInss.size() << endl;
395 	cout << " o Number of nets is .... " << _nets.size() << endl;
396     }
397 
398     // getting NetList Caracteristics
399 
400     _sumToPlaceInssWidth = 0.0;
401     _biggestToPlaceInsWidth = 0.0;
402     double inswidth = 0.0;
403     for (PToPlaceInss::const_iterator ins_it = _toPlaceInss.begin();
404 	    ins_it != _toPlaceInss.end(); ins_it++)
405     {
406         if (_biggestToPlaceInsWidth < (inswidth = (*ins_it)->GetWidth()))
407 	    _biggestToPlaceInsWidth = inswidth;
408         _sumToPlaceInssWidth += inswidth;
409     }
410 
411     if (_verbose)
412     {
413         cout << " o Sum of instances to place widths is ... " << _sumToPlaceInssWidth << endl;
414     }
415 
416     _binsMaxWidth = (double)(int)(2.0 * _biggestToPlaceInsWidth * (1.0 + _margin) + 0.5);
417     _binsMinWidth = (double)(int)(_binsMaxWidth / 2);
418 
419     if (_prePlace)
420     {
421 	InitPlaceWithPrePlace();
422 	if (_nInsToPlace > 0)
423 	{
424 	    if (_rows.begin() == _rows.end())
425 	    {
426 		cout << " o ERROR: No SPACE to place instances ....." << endl;
427 		exit(1);
428 	    }
429 	}
430     }
431     else
432 	if (_nInsToPlace > 0)
433 	    InitPlace(NbRows);
434 
435     // set positions of connectors in case of no ioc file
436     if (_placeCons && !_ringPlaceCons) GenerateConsPlacement();
437 
438     if (_ringPlaceCons && !_iocFile) GenerateRingConsPlacement();
439 
440     // set positions of connectors when ioc file is given
441     if (_iocFile) SetPosIocFile(pconmap);
442 
443     if (_nInsToPlace==0)
444 	return;
445 
446     // sorting instances by their Width (biggest -> smallest)
447     vector<PToPlaceIns*> ClassedInss;
448     ClassedInss.reserve(_nInsToPlace);
449     for (PToPlaceInss::iterator ifirst = _toPlaceInss.begin(); ifirst != _toPlaceInss.end(); ifirst++)
450     {
451         PToPlaceIns*   InsPt;
452         ClassedInss.push_back(InsPt);
453         ClassedInss.back() = *ifirst;
454     }
455     sort(ClassedInss.begin(), ClassedInss.end(), CompPInsByWidth());
456 
457     // Insertion of instances on rows
458     vector<PToPlaceIns*>::iterator iptfirst = ClassedInss.begin();
459     PRows::iterator rfirst = _rows.begin();
460     PRow::PSubRows::iterator subrfirst = (*rfirst)->GetSubRows().begin();
461 
462     PIns* InsInserting = *iptfirst;
463     while(1)
464     {
465         int NbOfBins;
466         int BinNumber;
467 
468         if (iptfirst == ClassedInss.end())
469         {
470             if (_verbose) cout << " o Initial Placement Computing ... done. " << endl;
471             break;
472             // end of insertion
473         }
474 
475 	if (subrfirst == (*rfirst)->GetSubRows().end()
476 		&& (++rfirst != _rows.end()))
477 	{
478 	    subrfirst = (*rfirst)->GetSubRows().begin();
479 	}
480 
481         if (rfirst == _rows.end())
482         {
483             if (InsInserting != *iptfirst)
484             {
485                 InsInserting = *iptfirst;
486                 rfirst = _rows.begin();
487 		subrfirst = (*rfirst)->GetSubRows().begin();
488             }
489             else
490             {
491                 // insertion of instances with respect of Bins margin
492                 // did not succed, inserting what's left.
493                 rfirst = _rows.begin();
494 		subrfirst = (*rfirst)->GetSubRows().begin();
495                 NbOfBins = (*subrfirst)->GetNBins();
496                 BinNumber = 0;
497                 while (iptfirst != ClassedInss.end())
498 		{
499                     if ((*iptfirst)->GetWidth() <=
500                            (*subrfirst)->GetWidth() - (*subrfirst)->GetSize())
501                     {
502                         (*subrfirst)->ForceIns(**(iptfirst++), BinNumber++);
503                     }
504                     else
505                         BinNumber++;
506                     if (BinNumber >= NbOfBins)
507                     {
508                         subrfirst++;
509                         BinNumber = 0;
510 			if (subrfirst != (*rfirst)->GetSubRows().end())
511 			    NbOfBins = (*subrfirst)->GetNBins();
512                     }
513 
514 		    if (subrfirst == (*rfirst)->GetSubRows().end()
515 			    && (++rfirst != _rows.end()))
516 		    {
517 			subrfirst = (*rfirst)->GetSubRows().begin();
518 			NbOfBins = (*subrfirst)->GetNBins();
519 		    }
520 
521                     if (rfirst == _rows.end())
522                     {
523                         if (InsInserting == *iptfirst)
524                         {
525                             // impossible to succed
526                             cerr << " o The is no enough free space, I need a bigger abutment box ......" << endl;
527                             cerr << " o There are still "
528                                 << ClassedInss.end() - iptfirst
529                                 << " Instances to place ..." << endl;
530                             exit(1);
531                         }
532                         rfirst = _rows.begin();
533 			subrfirst = (*rfirst)->GetSubRows().begin();
534 			NbOfBins = (*subrfirst)->GetNBins();
535 			BinNumber = 0;
536                         InsInserting = *iptfirst;
537                     }
538                 }
539             }
540         }
541         NbOfBins = (*subrfirst)->GetNBins();
542         BinNumber = 0;
543         while ((iptfirst != ClassedInss.end())
544                 && (BinNumber < NbOfBins)
545                 && ((*iptfirst)->GetWidth() <= (*subrfirst)->GetCapa() - (*subrfirst)->GetSize()))
546         {
547             if ((*subrfirst)->InsertIns(**iptfirst, BinNumber++))
548 	    {
549                 iptfirst++;
550 	    }
551         }
552 	subrfirst++;
553     }
554 
555 }
556 
557 // ======================================================================
558 // void SetPosIocFile(PConMap& pconmap)
559 // ======================================================================
560 void
SetPosIocFile(PConMap & pconmap)561 PPlacement::SetPosIocFile(PConMap& pconmap)
562 {
563   int topcount 	  = 0;
564   int bottomcount = 0;
565   int rightcount  = 0;
566   int leftcount   = 0;
567   int topspace	  = 0;
568   int bottomspace = 0;
569   int rightspace  = 0;
570   int leftspace   = 0;
571   int nbspacetop    = 0;
572   int nbspacebottom = 0;
573   int nbspaceright  = 0;
574   int nbspaceleft   = 0;
575 
576   con_list* pttop    = NULL;
577   con_list* ptbottom = NULL;
578   con_list* ptright  = NULL;
579   con_list* ptleft   = NULL;
580 
581   PPos position;
582 
583   int Width = (int)(BBox.GetMaxX() - BBox.GetMinX());
584   int Height = (int)(BBox.GetMaxY() - BBox.GetMinY());
585   if (_verbose) cout << " o Width of the abutment box : " << Width << endl
586     << " o Height of the abutment box : " << Height << endl;
587 
588   con_list* tmpnext;
589 
590   for(con_list* tmpcon = _PtList ; tmpcon; tmpcon = tmpnext)
591   {
592     tmpnext = tmpcon->NEXT;
593     switch (tmpcon->ORIENT)
594     {
595       case 'T' : tmpcon->NEXT = pttop;
596 		 pttop = tmpcon;
597 		 if (strcmp(tmpcon->NAME,"SPACE")==0)
598 		 {
599 		   topspace += tmpcon->VALUE;
600 		   nbspacetop++;
601 		 } else topcount++;
602 		 break;
603 
604       case 'B' : tmpcon->NEXT = ptbottom;
605 		 ptbottom = tmpcon;
606 		 if (strcmp(tmpcon->NAME,"SPACE")==0)
607 		 {
608 		   bottomspace += tmpcon->VALUE;
609 		   nbspacebottom++;
610 		 } else bottomcount++;
611 		 break;
612 
613       case 'R' : tmpcon->NEXT = ptright;
614 		 ptright = tmpcon;
615 		 if (strcmp(tmpcon->NAME,"SPACE")==0)
616 		 {
617 		   rightspace += tmpcon->VALUE;
618 		   nbspaceright++;
619 		 } else rightcount++;
620 		 break;
621 
622       case 'L' : tmpcon->NEXT = ptleft;
623 		 ptleft = tmpcon;
624 		 if (strcmp(tmpcon->NAME,"SPACE")==0)
625 		 {
626 		   leftspace += tmpcon->VALUE;
627 		   nbspaceleft++;
628 		 } else leftcount++;
629 		 break;
630     }
631   }
632 
633   if (topcount != 0)
634   {
635     double pos = 0.0;
636     if (topspace >= Width-topcount)
637     {
638       cerr << " o ERROR : in ioc file : space too important" << endl;
639       exit(1);
640     }
641     double conspace = ((double)(Width-topspace)/(double)(topcount-nbspacetop));
642     pos += conspace / 2.0;
643 
644     if (_verbose)
645 	cout << " o conspace : " << conspace
646 	    << " 1st connector : " << pos << endl;
647 
648     for(con_list* tmpcon = pttop ; tmpcon; tmpcon = tmpcon->NEXT)
649     {
650       if (strcmp(tmpcon->NAME,"SPACE") == 0)
651       {
652 	pos += (double)tmpcon->VALUE;
653 	pos -= conspace;
654       }
655       else
656       {
657 	if (_verbose) cout << " o adding connector  : " << tmpcon->NAME
658 	  << " x : " << (int)pos << " y : " << Height << endl;
659 	position.SetX((double)(int)pos);
660 	position.SetY(Height);
661 	// test a rajouter pour verifier si locon present ou pas!!!
662 	pconmap[tmpcon->NAME]->SetPos(position);
663 	pos += conspace;
664       }
665     }
666   }
667 
668   if (bottomcount != 0)
669   {
670     double pos = 0.0;
671     if (bottomspace >= Width-topcount)
672     {
673       cerr << " o ERROR : in ioc file : space too important" << endl;
674       exit(1);
675     }
676     double conspace = ((double)(Width-bottomspace)/
677 					(double)(bottomcount-nbspacebottom));
678     pos += conspace / 2.0;
679 
680     if (_verbose) cout << " o conspace : " << conspace << " 1st connector : " << pos << endl;
681 
682     for(con_list* tmpcon = ptbottom ; tmpcon; tmpcon = tmpcon->NEXT)
683     {
684       if (strcmp(tmpcon->NAME,"SPACE") == 0)
685       {
686 	pos += (double)tmpcon->VALUE;
687 	pos -= conspace;
688       }
689       else
690       {
691 	if (_verbose) cout << " o adding connector : " << tmpcon->NAME
692 	  << " x : " << (int)pos << " y : " << 0 << endl;
693 	position.SetX((double)(int)pos);
694 	position.SetY(0.0);
695 	// test a rajouter pour verifier si locon present ou pas!!!
696 	pconmap[tmpcon->NAME]->SetPos(position);
697 	pos += conspace;
698       }
699     }
700   }
701 
702   if (leftcount != 0)
703   {
704     double pos = 0.0, ppos = pos;
705     if (leftspace >= Width-topcount)
706     {
707       cerr << " o ERROR : in ioc file : space too important" << endl;
708       exit(1);
709     }
710     double conspace = ((double)(Height-leftspace)/
711 					(double)(leftcount-nbspaceleft));
712     if (_ringPlaceCons) ppos = pos;
713     pos += conspace / 2.0;
714 
715     for(con_list* tmpcon = ptleft ; tmpcon; tmpcon = tmpcon->NEXT)
716     {
717       if (strcmp(tmpcon->NAME,"SPACE") == 0)
718       {
719 	pos += (double)tmpcon->VALUE;
720 	pos -= conspace;
721       }
722       else
723       {
724         if (_ringPlaceCons)
725         {
726 	int delta = (int)pos % ROWHEIGHT;
727           if      (delta == 0) pos -=  2.0;
728           else if (delta == 1) pos +=  1.0;
729           else if (delta == 9) pos -=  1.0;
730           // Just in case there are so many connectors
731           if (pos < ppos) pos = ppos + 1;
732         }
733 
734 	if (_verbose) cout << " o adding connector : " << tmpcon->NAME
735 	  << " x : " << 0 << " y : " << (int)pos << endl;
736 	position.SetX(0.0);
737 	position.SetY((double)(int)pos);
738 	// test a rajouter pour verifier si locon present ou pas!!!
739 	pconmap[tmpcon->NAME]->SetPos(position);
740         if (_ringPlaceCons) ppos = pos;
741 	pos += conspace;
742       }
743     }
744   }
745 
746   if (rightcount != 0)
747   {
748     double pos = 0.0, ppos = pos;
749     if (rightspace >= Width-topcount)
750     {
751       cerr << " o ERROR : in ioc file : space too important" << endl;
752       exit(1);
753     }
754     double conspace = ((double)(Height-rightspace)/
755 					(double)(rightcount-nbspaceright));
756     if (_ringPlaceCons) ppos = pos;
757     pos += conspace / 2.0;
758 
759     for(con_list* tmpcon = ptright ; tmpcon; tmpcon = tmpcon->NEXT)
760     {
761       if (strcmp(tmpcon->NAME,"SPACE") == 0)
762       {
763 	pos += (double)tmpcon->VALUE;
764 	pos -= conspace;
765       }
766       else
767       {
768         if (_ringPlaceCons)
769         {
770 	int delta = (int)pos % ROWHEIGHT;
771          if      (delta == 0) pos -=  2.0;
772          else if (delta == 1) pos +=  1.0;
773          else if (delta == 9) pos -=  1.0;
774 	 // Just in case there are so many connectors
775 	 if (pos < ppos) pos = ppos + 1;
776         }
777 
778 	if (_verbose) cout << " o adding connector: " << tmpcon->NAME
779 	  << " x : " << Width << " y : " << (int)pos << endl;
780 	position.SetX(Width);
781 	position.SetY((double)(int)pos);
782 	// test a rajouter pour verifier si locon present ou pas!!!
783 	pconmap[tmpcon->NAME]->SetPos(position);
784         if (_ringPlaceCons) ppos = pos;
785 	pos += conspace;
786       }
787     }
788   }
789 }
790 // ======================================================================
791 // void ParseIocFile(PLoconMap& ploconmap)
792 // ======================================================================
793 
794 void
ParseIocFile(PLoconMap & ploconmap)795 PPlacement::ParseIocFile(PLoconMap& ploconmap)
796 {
797     PPos position;
798 
799     _PtList = iocparse(_iocFileName);
800 
801     char orientation;
802 
803     for(con_list* tmpcon = _PtList ; tmpcon ; tmpcon = tmpcon->NEXT)
804     {
805 	if (strcmp(tmpcon->NAME,"SPACE") != 0)
806 	{
807 	    if (ploconmap.find(tmpcon->NAME) == ploconmap.end())
808 	    {
809 		cerr << " o Error in ioc file ...." << endl
810 		    << "   The connector " << tmpcon->NAME
811 		    << " doesn't exist in your figure ...."
812 		    << endl;
813 		exit(1);
814 	    }
815 	    switch (tmpcon->ORIENT)
816 	    {
817 		case 'T':
818 		    orientation = NORTH;
819 		    break;
820 		case 'B':
821 		    orientation = SOUTH;
822 		    break;
823 		case 'L':
824 		    orientation = WEST;
825 		    break;
826 		case 'R':
827 		    orientation = EAST;
828 		    break;
829 		default:
830 		    cerr << "Unknown Orientation for connector: "
831 			<< tmpcon->NAME << endl;
832 		    exit(1);
833 	    }
834 	    position.SetX(0);
835 	    position.SetY(0);
836 	    InsertCon(ploconmap[tmpcon->NAME], position, orientation);
837 	}
838     }
839 }
840 
841 // ======================================================================
842 // void Place(lofig* fig, int NbRows);
843 // ======================================================================
844 void
Place(lofig * fig,int NbRows)845 PPlacement::Place(lofig* fig, int NbRows)
846 {
847     Init(fig, NbRows);
848     if (_boolPlot)
849     {
850 	PlotOnlyInstances("instances-init");
851 	PlotAll("init");
852     }
853     if (_nInsToPlace > 0)
854     {
855 	PlaceGlobal();
856 	if (_boolPlot)
857 	{
858 	  PlotAll("afterglobal");
859 	  PlotOnlyBins("binsafterglobal");
860 	}
861 	PlaceFinal();
862     }
863 }
864 
865 PFixedIns*
InsertFixedIns(const loins * ins,const phins * pins,const int dx,const int dy)866 PPlacement::InsertFixedIns(const loins* ins, const phins* pins, const int dx, const int dy)
867 {
868     PFixedIns* fixedins = new PFixedIns(ins, pins, dx, dy);
869     _fixedInss.push_back(fixedins);
870     return fixedins;
871 }
872 
873 PToPlaceIns*
InsertToPlaceIns(const loins * ins)874 PPlacement::InsertToPlaceIns(const loins* ins)
875 {
876     PToPlaceIns* toplaceins = new PToPlaceIns(ins);
877     _toPlaceInss.push_back(toplaceins);
878     return toplaceins;
879 }
880 
881 PCon*
InsertCon(const locon * con,phcon * phycon,int dx,int dy)882 PPlacement::InsertCon(const locon* con, phcon* phycon, int dx, int dy)
883 {
884     PCon* pcon = new PCon(con, phycon);
885     _cons.push_back(pcon);
886     return pcon;
887 }
888 
889 PCon*
InsertCon(const locon * con,PPos position,const char orientation)890 PPlacement::InsertCon(const locon* con, PPos position, const char orientation)
891 {
892     PCon* pcon = new PCon(con, position, orientation);
893     _cons.push_back(pcon);
894     return pcon;
895 }
896 
897 PONet*
InsertNet(const losig * sig)898 PPlacement::InsertNet(const losig* sig)
899 {
900     PONet* net = new PONet(sig);
901     _nets.push_back(net);
902     return net;
903 }
904 
905 ostream&
Print(ostream & os) const906 PPlacement::Print(ostream& os) const
907 {
908     PToPlaceInss::const_iterator ifirst = _toPlaceInss.begin();
909     PToPlaceInss::const_iterator ilast  = _toPlaceInss.end();
910     while (ifirst != ilast) {
911 	const PToPlaceIns& ins = **ifirst++;
912 	os << " + ins: " << ins << endl;
913 	PIns::PNets::const_iterator first = ins.GetConstNets().begin();
914 	PIns::PNets::const_iterator last  = ins.GetConstNets().end();
915 	while (first != last)
916 	    os << "   - net: " << *first++ << endl;
917     }
918 
919     PONets::const_iterator nfirst = _nets.begin();
920     PONets::const_iterator nlast  = _nets.end();
921     while (nfirst != nlast) {
922 	const PNet& net = **nfirst++;
923 	os << " + net: " << net << endl;
924 	PNet::PElems::const_iterator first = net.GetConstElems().begin();
925 	PNet::PElems::const_iterator last  = net.GetConstElems().end();
926 	while (first != last)
927 	    os << "   - ins: " << *first++ << endl;
928     }
929 
930     return os;
931 }
932 
933 // ======================================================================
934 // void PlotInstances(ofstream& out) const
935 // ======================================================================
936 void
PlotInstances(ofstream & out) const937 PPlacement::PlotInstances(ofstream& out) const
938 {
939 
940   out << "#rows" << endl;
941   for (PRows::const_iterator rit=_rows.begin(); rit!=_rows.end(); rit++)
942   {
943       (*rit)->Plot(out);
944   }
945   out << "EOF" << endl;
946   out << "#to place instances" << endl;
947   for (PToPlaceInss::const_iterator insit = _toPlaceInss.begin();
948 	  insit != _toPlaceInss.end(); insit++)
949   {
950       (*insit)->Plot(out);
951   }
952   out << "EOF" << endl;
953   out << "#preplaced instances" << endl;
954   for (PFixedInss::const_iterator insit = _fixedInss.begin();
955 	  insit != _fixedInss.end(); insit++)
956   {
957       (*insit)->Plot(out);
958   }
959   out << "EOF" << endl;
960 }
961 // ======================================================================
962 // void PlotAll(char *output) const
963 // ======================================================================
964 void
PlotAll(const string & output) const965 PPlacement::PlotAll(const string& output) const
966 {
967     string name = output + ".gpl";
968     ofstream out(name.c_str());
969 
970     out << "set noxtics\nset noytics\n"
971 	<< "set noborder\nset nokey\nset title '" << _fig->NAME << "'\n"
972 	<< "#set terminal postscript eps color solid\n#set output '"
973 	<< output << ".ps'\n"
974 	<< "set xrange[" << GetMinX() << ":" << GetMaxX() << "]\n"
975 	<< "set yrange[" << GetMinY() << ":" << GetMaxY() << "]\n"
976 	<< "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4\n"
977 	<< GetMinX() << " " << GetMinY() << endl
978 	<< GetMinX() << " " << GetMaxY() << endl
979 	<< GetMaxX() << " " << GetMaxY() << endl
980 	<< GetMaxX() << " " << GetMinY() << endl
981 	<< GetMinX() << " " << GetMinY() << endl << endl;
982 
983     PlotInstances(out);
984 
985     out << "#nets" << endl;
986     for (PONets::const_iterator nit=_nets.begin(); nit!=_nets.end(); nit++)
987     {
988 	(*nit)->Plot(out);
989     }
990     out << "EOF" << endl << "pause -1 'press any key'" << endl;
991 }
992 
993 // ======================================================================
994 // void PlotFinal(char *output) const
995 // ======================================================================
996 void
PlotFinal(const string & output) const997 PPlacement::PlotFinal(const string& output) const
998 {
999     string name = output + ".gpl";
1000     ofstream out(name.c_str());
1001 
1002     out << "set noxtics\nset noytics\n"
1003 	<< "set noborder\nset nokey\nset title '" << _fig->NAME << "'\n"
1004 	<< "#set terminal postscript eps color solid\n#set output '"
1005 	<< output << ".ps'\n"
1006 	<< "set xrange[" << GetMinX() << ":" << GetMaxX() << "]\n"
1007 	<< "set yrange[" << GetMinY() << ":" << GetMaxY() << "]\n"
1008 	<< "plot [:][:][:][:] '-' w l, '-' w l 2, '-' w l 3, '-' w l 4\n"
1009 	<< GetMinX() << " " << GetMinY() << endl
1010 	<< GetMinX() << " " << GetMaxY() << endl
1011 	<< GetMaxX() << " " << GetMaxY() << endl
1012 	<< GetMaxX() << " " << GetMinY() << endl
1013 	<< GetMinX() << " " << GetMinY() << endl << endl;
1014 
1015     out << "#preplaced instances" << endl;
1016     for (PFixedInss::const_iterator insit = _fixedInss.begin();
1017 	    insit != _fixedInss.end(); insit++)
1018     {
1019 	(*insit)->Plot(out);
1020     }
1021     out << "EOF" << endl;
1022 
1023     out << "#subrows" << endl;
1024     for (PDetSubRows::const_iterator srit = _detSubRows.begin() ;
1025 	  srit != _detSubRows.end() ;
1026 	  srit++)
1027     {
1028 	(*srit)->Plot(out);
1029     }
1030     out << "EOF" << endl;
1031 
1032     out << "#instances" << endl;
1033 
1034     for (PDetSubRows::const_iterator srit = _detSubRows.begin() ;
1035 	    srit != _detSubRows.end() ;
1036 	    srit++)
1037     {
1038 	for (PDetSubRow::PDetInsVector::const_iterator iit = (*srit)->GetConstInssVector().begin() ;
1039 		iit != (*srit)->GetConstInssVector().end() ;
1040 		iit++)
1041 	{
1042 	    (*iit)->Plot(out);
1043 	}
1044     }
1045     out << "EOF" << endl;
1046     out << "#nets" << endl;
1047 
1048     for (PONets::const_iterator nit=_nets.begin(); nit!=_nets.end(); nit++)
1049     {
1050 	(*nit)->Plot(out);
1051     }
1052     out << "EOF" << endl << "pause -1 'press any key'" << endl;
1053 }
1054 // ======================================================================
1055 // void PlotOnlyInstances(char* output) const
1056 // ======================================================================
1057 void
PlotOnlyInstances(const string & output) const1058 PPlacement::PlotOnlyInstances(const string& output) const
1059 {
1060     string name = output + ".gpl";
1061     ofstream out(name.c_str());
1062 
1063     out << "set noxtics\nset noytics\n"
1064 	<< "set noborder\nset nokey\nset title '" << _fig->NAME << "'\n"
1065 	<< "#set terminal postscript eps color solid\n#set output '"
1066 	<< output << ".ps'\n";
1067     out << "set xrange[" << GetMinX() << ":" << GetMaxX() << "]\n"
1068 	<< "set yrange[" << GetMinY() << ":" << GetMaxY() << "]\n"
1069 	<< "plot [:][:][:] '-' w l, '-' w l 2, '-' w l 3\n"
1070 	<< GetMinX() << " " << GetMinY() << endl
1071 	<< GetMinX() << " " << GetMaxY() << endl
1072 	<< GetMaxX() << " " << GetMaxY() << endl
1073 	<< GetMaxX() << " " << GetMinY() << endl
1074 	<< GetMinX() << " " << GetMinY() << endl << endl;
1075     PlotInstances(out);
1076     out << "pause -1 'press any key'" << endl;
1077 }
1078 // ======================================================================
1079 // void PlotOnlyBins(char* output) const
1080 // ======================================================================
1081 void
PlotOnlyBins(const string & output) const1082 PPlacement::PlotOnlyBins(const string& output) const
1083 {
1084     string name = output + ".gpl";
1085     ofstream out(name.c_str());
1086 
1087     out << "set noxtics\nset noytics\n"
1088 	<< "set noborder\nset nokey\nset title '" << _fig->NAME << "'\n"
1089 	<< "#set terminal postscript eps color solid\n#set output '"
1090 	<< output << ".ps'\n";
1091 
1092     if (_totalMoves != 0)
1093     {
1094 	for (PRows::const_iterator rit=_rows.begin(); rit!=_rows.end(); rit++)
1095 	{
1096 	    (*rit)->PlotLabel(out, _totalMoves);
1097 	}
1098     }
1099 
1100     out << "plot [:][:] '-' w l 1, '-' w l 2" << endl << "#bins" << endl;
1101     for (PRows::const_iterator rit=_rows.begin(); rit!=_rows.end(); rit++)
1102     {
1103 	(*rit)->Plot(out);
1104     }
1105 
1106     out << "EOF" << endl;
1107     out << "#preplaced instances" << endl;
1108     for (PFixedInss::const_iterator iit = _fixedInss.begin();
1109 	    iit != _fixedInss.end(); iit++)
1110     {
1111 	(*iit)->Plot(out);
1112     }
1113     out << "EOF" << endl;
1114     out << "pause -1 'press any key'" << endl;
1115 }
1116 // ======================================================================
1117 // void PlotStat()
1118 // ======================================================================
1119 void
PlotStat()1120 PPlacement::PlotStat()
1121 {
1122     ofstream out("stat.gpl");
1123 
1124   out << "set title 'all stats'" << endl
1125     << "#set terminal postscript color solid" << endl
1126     << "#set output 'stat.ps'" << endl
1127     << "plot 'alldata.dat' using 1:2 title 'temperature' with lines,"
1128     << "'alldata.dat' using 1:3 title 'cost' with lines,"
1129     << "'alldata.dat' using 1:4 title 'rowcost' with lines,"
1130     << "'alldata.dat' using 1:5 title 'bincost' with lines,"
1131     << "'alldata.dat' using 1:6 title 'netcost' with lines,"
1132     << "'alldata.dat' using 1:7 title 'success ratio' with lines,"
1133     << "'alldata.dat' using 1:8 title 'dist' with lines,"
1134     << "'alldata.dat' using 1:9 title 'delta' with lines" << endl
1135     << "pause -1 'press any key'" << endl;
1136 }
1137 
1138 // ======================================================================
1139 // void GenerateConsPlacement()
1140 // ======================================================================
1141 void
GenerateConsPlacement()1142 PPlacement::GenerateConsPlacement()
1143 {
1144     //creation d'un placement aleatoire des connecteurs.
1145     unsigned faces[4];
1146     double aspectRatio = GetWidth() / GetHeight();
1147     double repartition = aspectRatio + 1.0;
1148     unsigned nbConsNorthSouth = (unsigned)( aspectRatio * _cons.size() / repartition);
1149     unsigned nbConsEastWest = _cons.size() - nbConsNorthSouth;
1150 
1151     //faces north est sud ouest
1152     faces[0] = nbConsNorthSouth / 2;
1153     faces[2] = nbConsNorthSouth - faces[0];
1154     faces[1] = nbConsEastWest / 2;
1155     faces[3] = nbConsEastWest - faces[1];
1156 
1157     PCons::iterator cit = _cons.begin();
1158 
1159     unsigned minx = (unsigned)BBox.GetMinX();
1160     unsigned miny = (unsigned)BBox.GetMinY();
1161     unsigned maxx = (unsigned)BBox.GetMaxX();
1162     unsigned maxy = (unsigned)BBox.GetMaxY();
1163 
1164     unsigned pos = 0;
1165     unsigned interval = 0;
1166     int spaceLeft = 0;
1167 
1168     //placement au nord.
1169     if (faces[0])
1170     {
1171 	interval = (maxx - minx) / faces[0];
1172 	spaceLeft = (maxx - minx) % faces[0];
1173 	pos = minx + interval / 2;
1174 	while(faces[0]--)
1175 	{
1176 	    if (spaceLeft-- > 0)
1177 		pos += 1;
1178 	    (*cit)->SetOrient(NORTH);
1179 	    (*cit++)->SetPos(PPos(pos , maxy));
1180 	    pos += interval;
1181 	}
1182     }
1183 
1184     //placement a l'est.
1185     if (faces[1])
1186     {
1187 	interval = (maxy - miny) / faces[1];
1188 	spaceLeft = (maxy - miny) % faces[1];
1189 	pos = miny + interval / 2;
1190 	while(faces[1]--)
1191 	{
1192 	    if (spaceLeft-- > 0)
1193 		pos += 1;
1194 	    (*cit)->SetOrient(EAST);
1195 	    (*cit++)->SetPos(PPos(maxx , pos));
1196 	    pos += interval;
1197 	}
1198     }
1199 
1200     //placement au sud.
1201     if (faces[2])
1202     {
1203 	interval = (maxx - minx) / faces[2];
1204 	spaceLeft = (maxx - minx) % faces[2];
1205 	pos = minx + interval / 2;
1206 	while(faces[2]--)
1207 	{
1208 	    if (spaceLeft-- > 0)
1209 		pos += 1;
1210 	    (*cit)->SetOrient(SOUTH);
1211 	    (*cit++)->SetPos(PPos(pos , miny));
1212 	    pos += interval;
1213 	}
1214     }
1215 
1216     //placement a l'ouest.
1217     if (faces[3])
1218     {
1219 	interval = (maxy - miny) / faces[3];
1220 	spaceLeft = (maxy - miny) % faces[3];
1221 	pos = miny + interval / 2;
1222 	while(faces[3]--)
1223 	{
1224 	    if (spaceLeft-- > 0)
1225 		pos += 1;
1226 	    (*cit)->SetOrient(WEST);
1227 	    (*cit++)->SetPos(PPos(minx , pos));
1228 	    pos += interval;
1229 	}
1230     }
1231 }
1232 
1233 // ======================================================================
1234 // void GenerateRingConsPlacement()
1235 // this method will be deleted in the future ( .... I HOPE ;) .. )
1236 // His purpose is to give a ring suitable connectors placement
1237 // ======================================================================
1238 void
GenerateRingConsPlacement()1239 PPlacement::GenerateRingConsPlacement()
1240 {
1241     //creation d'un placement aleatoire des connecteurs pour ring.
1242     unsigned faces[2];
1243     unsigned nbConsNorth = _cons.size() / 2;
1244     unsigned nbConsSouth = _cons.size() - nbConsNorth;
1245 
1246     //faces north est sud ouest
1247     faces[0] = nbConsNorth;
1248     faces[1] = nbConsSouth;
1249 
1250     PCons::iterator cit = _cons.begin();
1251 
1252     unsigned minx = (unsigned)BBox.GetMinX();
1253     unsigned miny = (unsigned)BBox.GetMinY();
1254     unsigned maxx = (unsigned)BBox.GetMaxX();
1255     unsigned maxy = (unsigned)BBox.GetMaxY();
1256 
1257     unsigned pos = 0;
1258     unsigned interval = 0;
1259     int spaceLeft = 0;
1260 
1261     //placement au nord.
1262     if (faces[0])
1263     {
1264 	interval = (maxx - minx) / faces[0];
1265 	spaceLeft = (maxx - minx) % faces[0];
1266 	pos = minx + interval / 2;
1267 	while(faces[0]--)
1268 	{
1269 	    if (spaceLeft-- > 0)
1270 		pos += 1;
1271 	    (*cit)->SetOrient(NORTH);
1272 	    (*cit++)->SetPos(PPos(pos , maxy));
1273 	    pos += interval;
1274 	}
1275     }
1276 
1277     //placement au sud.
1278     if (faces[1])
1279     {
1280 	interval = (maxx - minx) / faces[1];
1281 	spaceLeft = (maxx - minx) % faces[1];
1282 	pos = minx + interval / 2;
1283 	while(faces[1]--)
1284 	{
1285 	    if (spaceLeft-- > 0)
1286 		pos += 1;
1287 	    (*cit)->SetOrient(SOUTH);
1288 	    (*cit++)->SetPos(PPos(pos , miny));
1289 	    pos += interval;
1290 	}
1291     }
1292 }
1293 
1294 // ======================================================================
1295 // void InitPlace(int NbRows)
1296 // private method
1297 // ======================================================================
1298 void
InitPlace(int NbRows)1299 PPlacement::InitPlace(int NbRows)
1300 {
1301     // no preplacement
1302     // we make a rectangle of rows with for each one subrow
1303     // of size = size of the row
1304     // composed of bins of constant size
1305     int NRows = NbRows;
1306 
1307     if (_verbose)
1308 	cout << " o Computing Initial Placement ..." << endl;
1309 
1310     if (_verbose)
1311     {
1312 	cout << " o User Margin : " << 100.0 * _margin << "%" << endl;
1313     }
1314 
1315     double rowwidth = SquareShape(_margin, _sumToPlaceInssWidth,
1316 	    _binsMinWidth, NRows);
1317 
1318     if (_verbose)
1319     {
1320       cout << " o Number of Rows : " << NRows << endl;
1321     }
1322 
1323     // computing Effective Margin
1324     double realSurface = NRows * rowwidth;
1325     _realMargin = 1.0 - _sumToPlaceInssWidth / realSurface;
1326     if (_verbose)
1327     {
1328         cout << " o Real Margin : " << 100.0 * _realMargin << "%" << endl;
1329     }
1330 
1331 
1332     _rows.reserve(NRows);
1333 
1334     double Y = 0.0;
1335     unsigned rowidx = 0;
1336     bool RowOrientation = false;
1337     _rowZeroOrientation = RowOrientation;
1338     for (int i = 0; i < NRows; i++)
1339     {
1340 	_rows.push_back(new PRow(1));
1341         double XMin = 0.0;
1342 	_rows.back()->Init(Y, XMin, *this, RowOrientation);
1343 	_rowsYMax[Y + ROWHEIGHT] = rowidx;
1344 	_rowsYMinInv[Y] = rowidx;
1345 	++rowidx;
1346 	PSubRow& subrow = *(_rows.back()->_subRows[0]);
1347 	subrow.Init(_rows.back(), Y, XMin, rowwidth, _realMargin, _binsMaxWidth, _binsMinWidth);
1348 	_rows.back()->_subRowsXMax[rowwidth + XMin] = 0;
1349 	_rows.back()->_subRowsXMaxInv[rowwidth + XMin] = 0;
1350         Y += ROWHEIGHT;
1351 	RowOrientation = !RowOrientation;
1352     }
1353 
1354     // Computing Placement BBox
1355     double MaxX = 0.0, MaxY = 0.0, RowMaxX = 0.0, RowMaxY = 0.0;
1356     for (PRows::iterator rit = _rows.begin(); rit != _rows.end(); rit++)
1357     {
1358         RowMaxX = (*rit)->GetMaxX();
1359         RowMaxY = (*rit)->GetMaxY();
1360         if (MaxX < RowMaxX)
1361             MaxX = RowMaxX;
1362         if (MaxY < RowMaxY)
1363             MaxY = RowMaxY;
1364     }
1365     BBox.SetMinX(0.0);
1366     BBox.SetMinY(0.0);
1367     BBox.SetMaxX(RowMaxX);
1368     BBox.SetMaxY(RowMaxY);
1369 }
1370 
1371 // ======================================================================
1372 // void InitPlaceWithPrePlace()
1373 // private method
1374 // ======================================================================
1375 void
InitPlaceWithPrePlace()1376 PPlacement::InitPlaceWithPrePlace()
1377 {
1378     // abutment box
1379     if (!_prePlaceFig)
1380     {
1381         cerr << " o ERROR: impossible to init preplacement with empty preplacement figure" << endl;
1382         exit(1);
1383     }
1384 
1385     int Width = _prePlaceFig->XAB2 - _prePlaceFig->XAB1;
1386     int Height = _prePlaceFig->YAB2 - _prePlaceFig->YAB1;
1387 
1388     // VERIFICATION OF THE PREPLACEMENT
1389     // abutment box
1390     if (Width % PITCH != 0)
1391     {
1392 	cerr << " o ERROR : abutment box's width must be a multiple of 5 lambdas"
1393 	    << endl;
1394 	exit(1);
1395     }
1396 
1397     if (Height % (PITCH * ROWHEIGHT) != 0)
1398     {
1399 	cerr << " o ERROR : abutment box's height must be a multiple of 50 lambdas"
1400 	    << endl;
1401 	exit(1);
1402     }
1403 
1404     Width =(int)(Width / PITCH);
1405     Height = (int)(Height / (PITCH * ROWHEIGHT));
1406 
1407     PrePlaceTab tabpreplace(Height, PrePlaceRow(Width, false));
1408 
1409     // find the orientation of the first row.
1410     phins* refpins = _prePlaceFig->PHINS;
1411 
1412     if (refpins)
1413     {
1414         int ycoord = (int)((refpins->YINS - _dy) / (ROWHEIGHT * PITCH));
1415         phfig* refpinsmodel = getphfig(refpins->FIGNAME, 'P');
1416         int refpinsheight = (int)((refpinsmodel->YAB2 - refpinsmodel->YAB1)
1417                 / (ROWHEIGHT * PITCH));
1418         char transf = refpins->TRANSF;
1419 
1420         if (ycoord % 2 == 0)
1421         {
1422           if ((refpinsheight == 2) || (transf == NOSYM) || (transf == SYM_X))
1423             _rowZeroOrientation = true;
1424           else
1425             _rowZeroOrientation = false;
1426         } else {
1427           if ((refpinsheight == 2) || (transf == NOSYM) || (transf == SYM_X))
1428             _rowZeroOrientation = false;
1429           else
1430             _rowZeroOrientation = true;
1431         }
1432 
1433         // tests for each instance
1434         for (phins* pins = _prePlaceFig->PHINS; pins; pins = pins->NEXT)
1435         {
1436             phfig_list* phmodel = getphfig(pins->FIGNAME, '0');
1437             int pinswidth = phmodel->XAB2 - phmodel->XAB1;
1438             int pinsheight = phmodel->YAB2 - phmodel->YAB1;
1439 
1440             pinswidth = (int)(pinswidth / PITCH);			// largeur ramene au pitch
1441             pinsheight = (int)(pinsheight / PITCH);			// hauteur ramene au pitch
1442             int pinsheightrow = (int)(pinsheight / ROWHEIGHT);	// hauteur ramene a l'unite
1443                                                                     // (taille des lignes)
1444             int ypos = (int)((pins->YINS - _dy) / PITCH);		// position en y ramene au pitch
1445             int xpos = (int)((pins->XINS - _dx) / PITCH);		// position en x ramene au pitch
1446             int ycoord = (int)(ypos / ROWHEIGHT);			// position en y ramene a l'unite
1447 
1448             if ((pins->YINS - _dy) % 50 != 0)
1449             {
1450                 cerr << " o ERROR : in preplacement file : y position of "
1451                     << pins->INSNAME << " is incorrect" << endl;
1452                 exit (1);
1453             }
1454 
1455             if ((pins->XINS - _dx) % 5 != 0)
1456             {
1457                 cerr << " o ERROR : in preplacement file : x position of "
1458                     << pins->INSNAME << " is incorrect" << endl;
1459                 exit (1);
1460             }
1461 
1462             if (   (pins->TRANSF == ROT_P) || (pins->TRANSF == ROT_M)
1463                 || (pins->TRANSF == SY_RP) || (pins->TRANSF == SY_RM) )
1464             {
1465                 cerr << " o ERROR : " << pins->INSNAME << " : incorrect rotation" << endl;
1466                 exit(1);
1467             }
1468 
1469             // check if orientation of instance matches
1470             bool insOrient;
1471             if ((pinsheightrow == 2) || (pins->TRANSF == NOSYM) || (pins->TRANSF == SYM_X))
1472               insOrient = true;
1473             else
1474               insOrient = false;
1475 
1476             if (   ((ycoord % 2 == 0) && (insOrient != _rowZeroOrientation))
1477                 || ((ycoord % 2 != 0) && (insOrient == _rowZeroOrientation)) )
1478             {
1479               cerr << " o ERROR : " << pins->INSNAME << " badly oriented" << endl
1480                    << "   Incoherence with " << refpins->INSNAME << endl;
1481               exit(1);
1482             }
1483 
1484             for (int yit = ycoord; yit < ycoord + pinsheightrow; yit++)
1485             {
1486               for (int xit = xpos; xit < xpos + pinswidth; xit++)
1487               {
1488                 if (   (xit > Width - 1) || (yit > Height - 1)
1489                     || (xit < 0    ) || (yit < 0     ) )
1490                 {
1491                   cerr << " o ERROR : " << pins->INSNAME
1492                        << " out of the abutment box" << endl;
1493                   exit(1);
1494                 }
1495 
1496                 if (tabpreplace[yit][xit] == false)
1497                 {
1498                     tabpreplace[yit][xit] = true;
1499                 }
1500                 else{
1501                   cerr << " o ERROR : " << pins->INSNAME << " badly placed .... There is already an instance at its position ...." << endl;
1502                   exit (1);
1503                 }
1504               }
1505             }
1506         }
1507     }
1508 
1509     // create rows and subrows
1510     if (_nInsToPlace > 0)
1511     {
1512 	int nbrows = 0;
1513 	for (int yit = 0; yit < Height; yit++)
1514 	{
1515 	  if (CheckCreateRow(tabpreplace, yit, Width) > 0) ++nbrows;
1516 	}
1517 
1518 
1519 	_rows.reserve(nbrows);
1520 
1521 	bool orientation = _rowZeroOrientation;
1522 	int numrows = 0;
1523 	for (int yit = 0; yit < Height; yit++)
1524 	{
1525 	  int numsubrows = CheckCreateRow(tabpreplace, yit, Width);
1526 	  if (numsubrows > 0)
1527 	  {
1528             PRow* row = new PRow(*this, (double)(yit * ROWHEIGHT), Width, numsubrows, orientation);
1529             _rows.push_back(row);
1530 	    _rowsYMax[(yit + 1) * ROWHEIGHT] = numrows;
1531 	    _rowsYMinInv[yit * ROWHEIGHT] = numrows;
1532 	    ++numrows;
1533 	    CreateSubRows(_rows.back(), tabpreplace, yit, numsubrows, Width);
1534 	  }
1535 	  orientation = !orientation;
1536 	}
1537     }
1538     BBox.SetMinX(0.0);
1539     BBox.SetMinY(0.0);
1540     BBox.SetMaxX(Width);
1541     BBox.SetMaxY(Height * ROWHEIGHT);
1542 }
1543 
1544 // ======================================================================
1545 // void CreateSubRows(PRow* row, PrePlaceTab& tabpreplace,int coordy, int nbsubrows, int Width)
1546 // private method
1547 // ======================================================================
1548 void
CreateSubRows(PRow * row,PrePlaceTab & tabpreplace,int coordy,int nbsubrows,int Width)1549 PPlacement::CreateSubRows(PRow* row, PrePlaceTab& tabpreplace,
1550    					int coordy, int nbsubrows, int Width)
1551 {
1552   int coordx = 0;
1553   int subrowscreated = 0;
1554 
1555   while (coordx < Width)
1556   {
1557     while (( coordx < Width  			  )
1558 	&& ( tabpreplace[coordy][coordx] == true ))
1559       ++coordx;
1560 
1561     if (coordx >= Width)
1562 	break;
1563 
1564     int xmin = coordx;
1565 
1566     while (( coordx < Width  			 )
1567 	&& ( tabpreplace[coordy][coordx] == false ))
1568       ++coordx;
1569 
1570     int xmax = coordx;
1571 
1572     if ( (xmax - xmin) >= _binsMinWidth)
1573     {
1574 	row->_subRows[subrowscreated]->Init(row, (double)(coordy * ROWHEIGHT), (double)xmin,(double)xmax,
1575 		(double)_margin, _binsMaxWidth, _binsMinWidth);
1576 	row->_subRowsXMax[(double)xmax] = subrowscreated;
1577 	++subrowscreated;
1578     }
1579     for (PRow::PSubRowsXMax::iterator srymit = row->_subRowsXMax.begin();
1580 	    srymit != row->_subRowsXMax.end();
1581 	    srymit++)
1582     {
1583 	row->_subRowsXMaxInv[srymit->first] = srymit->second;
1584     }
1585   }
1586   if (subrowscreated != nbsubrows)
1587   {
1588       cerr << " o INTERNAL ERROR : in subrow creation" << endl;
1589       exit (1);
1590   }
1591 }
1592 
1593 // ======================================================================
1594 // void CheckCreateRow(PrePlaceTab& tabpreplace, int coordy, int Width)
1595 // private method
1596 // ======================================================================
1597 int
CheckCreateRow(PrePlaceTab & tabpreplace,int coordy,int Width)1598 PPlacement::CheckCreateRow(PrePlaceTab& tabpreplace, int coordy, int Width)
1599 {
1600   int coordx = 0;
1601   int nbsubrows = 0;
1602 
1603   while (coordx < Width)
1604   {
1605     while (  ( coordx < Width  			)
1606 	  && ( tabpreplace[coordy][coordx] == true	))
1607       ++coordx;
1608 
1609     if (coordx >= Width)
1610 	break;
1611 
1612     int xmin = coordx;
1613 
1614     while (  ( coordx < Width  			)
1615 	  && ( tabpreplace[coordy][coordx] == false	))
1616       ++coordx;
1617 
1618     int xmax = coordx;
1619 
1620     if ( (xmax - xmin) >= _binsMinWidth)
1621 	++nbsubrows;
1622   }
1623 
1624   return (nbsubrows);
1625 }
1626 
1627 // ======================================================================
1628 // PRow& GetRow(const PRow* row, const double dist)
1629 // private method
1630 // ======================================================================
1631 PRow&
GetRow(const PRow * row,const double dist)1632 PPlacement::GetRow(const PRow* row, const double dist)
1633 {
1634     // returns randomly a row at maximum distance from yorig
1635     double bornesup, borneinf;
1636 
1637 
1638     if ((bornesup = (row->GetMinY() + row->GetHeight() / 2.0) + (double)(int)(dist * GetHeight() + 0.5) ) > GetMaxY())
1639         bornesup = GetMaxY();
1640 
1641     if ((borneinf = (row->GetMinY() + row->GetHeight() / 2.0) - (double)(int)(dist * GetHeight() + 0.5) ) < GetMinY())
1642         borneinf = GetMinY();
1643 
1644     PRowsYMax::iterator rinf = _rowsYMax.upper_bound(borneinf);
1645     PRowsYMax::iterator rsup = _rowsYMinInv.upper_bound(bornesup);
1646 
1647     unsigned randidx = rinf->second + (unsigned)((double)(rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0)));
1648     return *_rows[randidx];
1649 }
1650 
GetBinsCapa() const1651 double PPlacement::GetBinsCapa() const
1652 {
1653     double binsCapa = 0.0;
1654     for (PRows::const_iterator rit = _rows.begin(); rit != _rows.end(); rit++)
1655     {
1656         binsCapa += (*rit)->GetBinsCapa();
1657     }
1658     return binsCapa;
1659 }
1660 
GetSubRowsCapa() const1661 double PPlacement::GetSubRowsCapa() const
1662 {
1663     double subRowsCapa = 0.0;
1664     for (PRows::const_iterator rit = _rows.begin(); rit != _rows.end(); rit++)
1665     {
1666         subRowsCapa += (*rit)->GetSubRowsCapa();
1667     }
1668     return subRowsCapa;
1669 }
1670 
GetBinsSize() const1671 double PPlacement::GetBinsSize() const
1672 {
1673     double binsSize = 0.0;
1674     for (PRows::const_iterator rit = _rows.begin(); rit != _rows.end(); rit++)
1675     {
1676         binsSize += (*rit)->GetBinsSize();
1677     }
1678     return binsSize;
1679 }
1680