3 #include <QGraphicsScene>
4 #include <QGraphicsEllipseItem>
5 #include <QGraphicsLineItem>
31 debugColorMap.
clear();
34 for (
int i=0; i<4; i++)
43 for (
auto it = pattern.
begin(); it != pattern.
end(); ++it)
45 if (danglingWire.
contains(it.value()))
51 int hue = count++ * 25;
54 int cc = (count-10)%20;
55 int cd = (count-10)/20;
59 qDebug() << cc << cd << h << s << v;
62 int g = (20*count) % 128 + 128;
75 float dd =
DELTA / 2.;
79 retval->
setBrush(colorFromId(netId));
87 : mEntries(entries), mError(Ok)
89 memset(maxRoad,0,
sizeof(maxRoad));
92 int iHoriz = dir.iHorizontal();
94 if (
n>maxRoad[iHoriz]) maxRoad[iHoriz] =
n;
95 for (
int i=0; i<
n; i++)
98 mNets[mEntries.
id(dir,i)].addEntry(dir,i);
101 routeAllStraight(0,1);
102 routeAllStraight(2,3);
120 void NetLayoutJunction::findJunctions()
122 for (
auto it = mNets.begin(); it!= mNets.end(); ++it)
133 if ((hn.mRange.innerPos(vn.mIndex.laneIndex()) && vn.mRange.contains(hn.mIndex.laneIndex())) ||
134 (hn.mRange.contains(vn.mIndex.laneIndex()) && vn.mRange.innerPos(hn.mIndex.laneIndex())))
135 it->mKnots.append(
QPoint(vn.mIndex.laneIndex(),hn.mIndex.laneIndex()));
139 void NetLayoutJunction::routeAllMultiPin(NetLayoutDirection leftOrRight)
141 int nEntries = mEntries.
mEntries[leftOrRight.index()].
size();
145 for (
int iroad=0; iroad<nEntries; iroad++)
148 bool isRouted =
false;
150 auto itNet = mNets.find(
id);
151 Q_ASSERT(itNet != mNets.end());
153 if (itNet.value().pattern() == (
u32) (1 << leftOrRight.index() ))
161 for (
const NetLayoutJunctionRange& rng : mOccupied.
value(rinx))
163 if (rng.isEntry(leftOrRight.index()))
173 multiPinHash[
id].mLane = iroad;
175 multiPinHash[
id].mConnector.append(iroad);
178 for (
auto it = multiPinHash.
begin(); it!= multiPinHash.
end(); ++it)
180 if (it.value().mConnector.isEmpty())
continue;
182 routeSingleMultiPin(it.key(), leftOrRight, it.value());
188 void NetLayoutJunction::routeSingleMultiPin(
u32 netId, NetLayoutDirection leftOrRight,
const NetLayoutJunctionMultiPin& nmpin)
190 int ymin = nmpin.mLane;
191 int ymax = nmpin.mLane;
192 for (
int iroad : nmpin.mConnector)
194 if (iroad < ymin) ymin = iroad;
195 if (iroad > ymax) ymax = iroad;
199 if (leftOrRight.isLeft())
212 for (
int x=x0; x!=x1; x+=dx)
217 rngs.
append(NetLayoutJunctionRange(netId,ymin,ymax));
218 for (
int iroad : nmpin.mConnector)
221 if (leftOrRight.isLeft())
222 rngs.
append(NetLayoutJunctionRange(netId,x1,x));
224 rngs.
append(NetLayoutJunctionRange(netId,x,x1));
226 bool hasConflict =
false;
229 for (
int i=0; i<roads.
size();i++)
239 for (
int i=0; i<roads.
size();i++)
246 void NetLayoutJunction::calculateRect()
249 x0 = y0 = x1 = y1 = 0;
252 for (LaneIndex ri : mOccupied.
keys())
254 switch (ri.hvIndex())
259 if (y+1>y1) y1 = y+1;
264 if (x+1>x1) x1 = x+1;
272 mRect =
QRect(x0,y0,x1-x0,y1-y0);
275 for (
auto itNet = mNets.begin(); itNet != mNets.end(); ++itNet)
277 auto itWire = itNet->mWires.begin();
278 while (itWire != itNet->mWires.end())
283 itWire->mRange.setFirst(x0);
285 itWire->mRange.setFirst(y0);
290 itWire->mRange.setLast(x1-1);
292 itWire->mRange.setLast(y1-1);
294 if (itWire->mRange.length() <=0)
295 itWire = itNet->mWires.erase(itWire);
302 #ifdef JUNCTION_DEBUG
311 float xscene0 = bg.left() < 100 ? bg.left() - 100 : 0;
312 float xscene1 = bg.right() > 900 ? bg.right() + 100 : 1000;
313 float yscene0 = bg.top() < 100 ? bg.top() - 100 : 0;
314 float yscene1 = bg.bottom() > 900 ? bg.bottom() + 100 : 1000;
321 for (
auto netIt = mNets.constBegin(); netIt != mNets.constEnd(); ++netIt)
323 for(
QPoint jp : netIt.value().junctionPoints())
331 for (NetLayoutDirection dir(0); !dir.isMax(); ++dir)
334 for (
int ientry=0; ientry<nEntries; ientry++)
337 QColor col = colorFromId(
id);
342 switch (dir.direction()) {
364 void NetLayoutJunction::toSceneStep(
QGraphicsScene* scene,
int istep)
366 if (istep >= mOccupied.mHistory.
size())
return;
374 QColor col = colorFromId(pw.first);
376 float x0, x1, y0, y1;
378 const LaneIndex& ri = pw.second.mIndex;
379 const NetLayoutJunctionRange& rng = pw.second.mRange;
384 if (x0 < bg.left()) x0 = bg.left();
386 if (x1 > bg.right()) x1 = bg.right();
387 qDebug() <<
"---" << ri.laneIndex() << rng.first() << rng.last();
393 if (y0 < bg.top()) y0 = bg.top();
395 if (y1 > bg.bottom()) y1 = bg.bottom();
396 qDebug() <<
" | " << ri.laneIndex() << rng.first() << rng.last();
404 void NetLayoutJunction::routeT()
406 for (
auto itNet=mNets.begin(); itNet!=mNets.end();++itNet)
408 if (itNet.value().numberEntries() >= 3)
413 switch (itNet.value().pattern())
420 reducedPattern = itNet.value().laneIndex(i1) > itNet.value().laneIndex(i0) ? 5 : 6;
427 reducedPattern = itNet.value().laneIndex(i1) > itNet.value().laneIndex(i0) ? 10 : 9;
434 reducedPattern = itNet.value().laneIndex(i1) > itNet.value().laneIndex(i0) ? 5 : 9;
441 reducedPattern = itNet.value().laneIndex(i1) > itNet.value().laneIndex(i0) ? 10 : 6;
447 int roadLink = itNet.value().laneIndex(ilink);
452 qDebug() <<
"T-join not found";
459 for (
const NetLayoutJunctionWire& nljw : mainWires)
461 NetLayoutJunctionRange rng =
463 if (!minlen || rng.length() < rngT.length())
466 minlen = rng.length();
470 if (conflict(LaneIndex(itravers,roadLink),rngT))
471 itNet->setPattern(reducedPattern);
474 place(LaneIndex(itravers,roadLink),rngT);
481 void NetLayoutJunction::routeAllCorner(NetLayoutDirection dirHoriz, NetLayoutDirection dirVertic)
483 u32 searchPattern = dirHoriz.toPattern() | dirVertic.toPattern();
484 if (dirVertic.isUp())
486 it != mEntries.
mEntries[dirHoriz.index()].
end(); ++it)
488 NetLayoutJunctionNet
net = mNets.value(*it);
489 if (
net.hasPattern(searchPattern) && !
net.isPlaced())
490 routeSingleCorner(*it,dirHoriz,dirVertic);
496 NetLayoutJunctionNet
net = mNets.value(*it);
497 if (
net.hasPattern(searchPattern) && !
net.isPlaced())
498 routeSingleCorner(*it,dirHoriz,dirVertic);
502 void NetLayoutJunction::routeAllStraight(NetLayoutDirection dirFrom, NetLayoutDirection dirTo)
505 u32 searchPattern = dirFrom.toPattern() | dirTo.toPattern();
507 for (
u32 netId : mEntries.
mEntries[dirFrom.index()])
509 auto itNet = mNets.find(netId);
510 Q_ASSERT(itNet != mNets.end());
512 if (itNet.value().hasPattern(searchPattern))
514 int iroadIn = itNet.value().laneIndex(dirFrom);
515 int iroadOut = itNet.value().laneIndex(dirTo);
516 if (straightConnected.
contains(iroadIn) && straightConnected.
contains(iroadOut))
517 routeSingleSwap(netId, (searchPattern==3?0:1), iroadIn, iroadOut);
519 routeSingleStraight(netId, (searchPattern==3?0:1), iroadIn, iroadOut);
520 ++straightConnected[iroadIn];
521 ++straightConnected[iroadOut];
522 if (itNet.value().numberEntries() % 2 ==0)
528 bool NetLayoutJunction::conflict(
const LaneIndex&ri,
const NetLayoutJunctionRange& testRng)
const
530 auto itConflict = mOccupied.
find(ri);
531 if (itConflict == mOccupied.
end())
return false;
532 return itConflict.
value().conflict(testRng);
535 bool NetLayoutJunction::canJoin(
const LaneIndex &ri,
u32 netId,
int pos)
const
537 auto itJoin = mOccupied.
find(ri);
538 if (itJoin == mOccupied.
end())
return false;
539 return itJoin.
value().canJoin(netId,pos);
542 void NetLayoutJunction::place(
const LaneIndex &ri,
const NetLayoutJunctionRange &range)
544 NetLayoutJunctionOccupiedHash::AddOrMerge aom = mOccupied.
addOrMerge(ri,range);
546 auto netIt = mNets.find(range.netId());
547 Q_ASSERT(netIt!=mNets.end());
552 NetLayoutJunctionWire nljw(range,ri);
553 netIt->addWire(nljw);
558 NetLayoutJunctionWire nljw(*aom.mNewRange,ri);
559 netIt->replaceWire(*aom.mOldRange,nljw);
567 void NetLayoutJunction::routeSingleSwap(
u32 netId,
int iMain,
int iroadIn,
int iroadOut)
571 int iroadJump1 = maxRoad[iJump];
572 int iroadDetour = maxRoad[iMain];
583 NetLayoutJunctionRange rngJ0(netId, iroadIn, riDetour.laneIndex());
584 NetLayoutJunctionRange rngDt(netId, riJump0.laneIndex(), riJump1.laneIndex());
585 NetLayoutJunctionRange rngJ1(netId, iroadOut, riDetour.laneIndex());
589 if (conflict(riDetour,rngDt))
594 if (conflict(riJump1,rngJ1) ||
595 conflict(riMainOut,rngOut))
600 if (conflict(riJump0,rngJ0) ||
601 conflict(riMainIn,rngIn))
606 place(riMainIn,rngIn);
607 place(riJump0,rngJ0);
608 place(riDetour,rngDt);
609 place(riJump1,rngJ1);
610 place(riMainOut,rngOut);
615 void NetLayoutJunction::routeSingleStraight(
u32 netId,
int iMain,
int iroadIn,
int iroadOut)
618 if (iroadIn == iroadOut)
624 int iroadLo = iroadIn;
625 int iroadHi = iroadOut;
627 int isearchIncr = -1;
628 if (iroadIn > iroadOut)
632 iroadJump = maxRoad[iJump];
635 for (;;iroadJump+=isearchIncr)
640 qDebug() <<
"cannot route straight" << (iMain ?
"vertical" :
"horizontal")
641 << netId << iroadIn << iroadOut;
644 NetLayoutJunctionRange rngIn(netId,
647 NetLayoutJunctionRange rngJump(netId, iroadLo, iroadHi);
648 NetLayoutJunctionRange rngOut(netId,
655 if (!conflict(riJump,rngJump) &&
656 !conflict(riMainOut,rngOut) &&
657 !conflict(riMainIn,rngIn))
659 place(riJump,rngJump);
660 place(riMainIn,rngIn);
661 place(riMainOut,rngOut);
674 for (
auto it = nljo.
begin(); it!= nljo.
end(); ++it)
681 if (it->canJoin(rng))
694 #ifdef JUNCTION_DEBUG
702 auto netIt = mNets.find(netId);
703 Q_ASSERT(netIt != mNets.end());
705 int iroadHoriz = netIt.value().laneIndex(dirHoriz);
706 int iroadVertic = netIt.value().laneIndex(dirVertic);
723 int hstep = dirVertic.
isUp() ? -1 : 1;
725 int vstep = dirHoriz.
isLeft() ? -1 : 1;
728 int tryMax = 2 * mOccupied.
size();
729 for (
int i=0; i<4; i++)
733 NetLayoutJunctionRange rngVc(netId,iroadHoriz,hcroad);
734 NetLayoutJunctionRange rngHc(netId,iroadVertic,vcroad);
735 NetLayoutJunctionRange rngHe =
737 NetLayoutJunctionRange rngVe =
740 if (++icount > tryMax)
742 qDebug() <<
"giving up";
775 : mPattern(0), mEntries(0), mPlaced(false)
778 mLaneIndex[dir.index()] = -1;
784 mLaneIndex[dir.
index()] = laneInx;
790 return (mPattern & searchPattern) == searchPattern;
807 if (it->mIndex.hvIndex() == hvi && it->mRange.contains(pos))
815 const char* dirChar =
"LRUD";
818 if (mPattern & dir.toPattern())
820 if (!retval.
isEmpty()) retval +=
":";
821 retval +=
QString(
"%1%2").
arg(dirChar[dir.index()]).
arg(mLaneIndex[dir.index()]);
828 : mNetId(netId_), mFirst(first), mLast(last)
846 if (mNetId != other.mNetId)
return false;
847 if (mFirst > other.mLast)
return false;
848 if (other.mFirst > mLast)
return false;
854 return (mNetId == other.mNetId &&
855 mFirst == other.mFirst &&
856 mLast == other.mLast);
861 return (mFirst == wire.
mRange.mFirst && mLast == wire.
mRange.mLast);
867 if (mNetId == other.mNetId)
return false;
868 if (other.mLast < mFirst || mLast < other.mFirst)
return false;
874 if (!iGetLast)
return mFirst;
880 if (iTestMax)
return (mLast ==
MaxInf);
881 return (mFirst ==
MinInf);
886 if (other.mFirst < mFirst) mFirst = other.mFirst;
887 if (other.mLast > mLast) mLast = other.mLast;
894 if (r.
netId() != netId)
continue;
926 xout <<
"(" << pnt.
x() <<
"," << pnt.
y() <<
")\n";
948 retval +=
QString(
" entries.mEntries[%1]").
arg(dir.index());
static LaneIndex horizontal(int ilane)
static LaneIndex vertical(int ilane)
u32 id(NetLayoutDirection dir, int ilane) const
void dumpToFile(const QPoint &pnt) const
NetLayoutJunction(const NetLayoutJunctionEntries &entries)
QList< NetLayoutJunctionWire > wireAtPos(int pos, LaneIndex::HVIndex hvi)
QList< NetLayoutJunctionWire > mWires
void addEntry(NetLayoutDirection dir, int laneInx)
void replaceWire(const NetLayoutJunctionRange &rng, const NetLayoutJunctionWire &wire)
bool hasPattern(u32 searchPattern) const
NetLayoutJunctionRange * mNewRange
NetLayoutJunctionRange * mOldRange
enum hal::NetLayoutJunctionOccupiedHash::AddOrMerge::Type mType
AddOrMerge addOrMerge(const LaneIndex &ri, const NetLayoutJunctionRange &rng)
bool conflict(const NetLayoutJunctionRange &test) const
bool canJoin(u32 netId, int pos) const
bool contains(int pos) const
int endPosition(int iGetLast) const
bool conflict(const NetLayoutJunctionRange &other) const
void expand(const NetLayoutJunctionRange &other)
bool canJoin(const NetLayoutJunctionRange &other) const
static NetLayoutJunctionRange entryRange(NetLayoutDirection dir, int ilane, u32 netId)
NetLayoutJunctionRange(u32 netId_, int first, int last)
bool operator==(const NetLayoutJunctionRange &other) const
bool isEntry(int iTestMax) const
NetLayoutJunctionRange mRange
static ProjectManager * instance()
uint qHash(const LaneIndex &ri)
void setBrush(const QBrush &brush)
QColor fromHsv(int h, int s, int v, int a)
bool isValid() const const
QDateTime currentDateTime()
void setPen(const QPen &pen)
void addItem(QGraphicsItem *item)
void setBackgroundBrush(const QBrush &brush)
void setSceneRect(const QRectF &rect)
QHash::iterator find(const Key &key)
QList< Key > keys() const const
T & operator[](const Key &key)
const T value(const Key &key) const const
QList< T > values() const const
void append(const T &value)
const T & at(int i) const const
bool isEmpty() const const
QList::reverse_iterator rbegin()
QList::reverse_iterator rend()
T value(int i) const const
bool contains(const Key &key) const const
const T value(const Key &key, const T &defaultValue) const const
bool contains(const T &value) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const