Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
|
|
|
// Copyright (c) UPMC 2021-2021, All Rights Reserved
|
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | C O R I O L I S |
|
|
|
|
// | A n a b a t i c - Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./AntennaProtect.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <sstream>
|
|
|
|
#include <tuple>
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
|
|
#include "hurricane/Breakpoint.h"
|
|
|
|
#include "hurricane/Net.h"
|
|
|
|
#include "hurricane/NetExternalComponents.h"
|
|
|
|
#include "hurricane/NetRoutingProperty.h"
|
|
|
|
#include "hurricane/Layer.h"
|
|
|
|
#include "hurricane/RoutingPad.h"
|
|
|
|
#include "hurricane/Pad.h"
|
|
|
|
#include "hurricane/Plug.h"
|
|
|
|
#include "hurricane/Instance.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "hurricane/Cell.h"
|
|
|
|
#include "crlcore/RoutingGauge.h"
|
|
|
|
#include "etesian/EtesianEngine.h"
|
|
|
|
#include "anabatic/AutoContactTerminal.h"
|
|
|
|
#include "anabatic/AutoSegment.h"
|
|
|
|
#include "anabatic/AnabaticEngine.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace CRL;
|
|
|
|
using namespace Hurricane;
|
|
|
|
using namespace Anabatic;
|
|
|
|
using Etesian::EtesianEngine;
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
class CompareByLength {
|
|
|
|
public:
|
2021-10-30 07:36:13 -05:00
|
|
|
inline bool operator() ( const Segment* lhs, const Segment* rhs ) const
|
2021-05-11 07:30:38 -05:00
|
|
|
{
|
|
|
|
DbU::Unit delta = lhs->getLength() - rhs->getLength();
|
|
|
|
if (delta < 0) return false;
|
|
|
|
if (delta > 0) return true;
|
|
|
|
return lhs->getId() < rhs->getId();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CompareBySegmentBox {
|
|
|
|
public:
|
2021-10-30 07:36:13 -05:00
|
|
|
inline bool operator() ( const Box& lhs, const Box& rhs ) const
|
2021-05-11 07:30:38 -05:00
|
|
|
{
|
|
|
|
bool lhsH = (lhs.getWidth() >= lhs.getHeight());
|
|
|
|
bool rhsH = (rhs.getWidth() >= rhs.getHeight());
|
|
|
|
if (lhsH xor rhsH) return lhsH;
|
|
|
|
|
|
|
|
DbU::Unit lhsLength = (lhsH) ? lhs.getWidth() : lhs.getHeight();
|
|
|
|
DbU::Unit rhsLength = (rhsH) ? rhs.getWidth() : rhs.getHeight();
|
|
|
|
return lhsLength > rhsLength;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
typedef tuple<RoutingPad*,uint32_t> RPInfosItem;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
class CompareRPInfos {
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
public:
|
2021-05-04 12:31:12 -05:00
|
|
|
inline bool operator () ( const RPInfosItem& lhs, const RPInfosItem& rhs ) const;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
inline bool CompareRPInfos::operator () ( const RPInfosItem& lhs, const RPInfosItem& rhs ) const
|
|
|
|
{ return std::get<0>(lhs)->getId() < std::get<0>(rhs)->getId(); }
|
|
|
|
|
|
|
|
|
|
|
|
typedef tuple<GCell*,uint32_t,GCell*> GCellInfosItem;
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
inline const uint32_t& elemFlags ( const GCellInfosItem& item ) { return std::get<1>(item); }
|
|
|
|
inline uint32_t& elemFlags ( GCellInfosItem& item ) { return std::get<1>(item); }
|
|
|
|
inline GCell* elemGCell ( const GCellInfosItem& item ) { return std::get<0>(item); }
|
2021-05-04 12:31:12 -05:00
|
|
|
|
|
|
|
class CompareGCellInfos {
|
|
|
|
public:
|
|
|
|
inline bool operator () ( const GCellInfosItem& lhs, const GCellInfosItem& rhs ) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline bool CompareGCellInfos::operator () ( const GCellInfosItem& lhs, const GCellInfosItem& rhs ) const
|
|
|
|
{
|
|
|
|
if (std::get<1>(lhs) != std::get<1>(rhs)) return std::get<1>(lhs) < std::get<1>(rhs);
|
|
|
|
return std::get<0>(lhs)->getId() < std::get<0>(rhs)->getId();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef set<RPInfosItem,CompareRPInfos> RoutingPadInfos;
|
|
|
|
typedef set<GCellInfosItem,CompareGCellInfos> GCellArea;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
inline DbU::Unit getBoxLength ( const Box& bb )
|
|
|
|
{ return (bb.getWidth() > bb.getHeight()) ? bb.getWidth() : bb.getHeight(); }
|
|
|
|
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
// -----------------------------------------------------------------
|
|
|
|
// Class : "::DiodeCluster".
|
|
|
|
|
|
|
|
class DiodeCluster {
|
|
|
|
public:
|
|
|
|
static const uint32_t IsDriver;
|
|
|
|
static const uint32_t IsSink;
|
|
|
|
static const uint32_t HasDiode;
|
|
|
|
static const uint32_t IsSegSource;
|
2021-05-04 12:31:12 -05:00
|
|
|
static const uint32_t InCluster;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
static string toStr ( uint32_t );
|
2021-06-08 05:19:40 -05:00
|
|
|
public:
|
|
|
|
template<typename DerivedT>
|
|
|
|
inline const DerivedT* as () const { return dynamic_cast<const DerivedT>( this ); }
|
|
|
|
template<typename DerivedT>
|
|
|
|
inline DerivedT* as () { return dynamic_cast<DerivedT>( this ); }
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
public:
|
2021-05-22 08:14:32 -05:00
|
|
|
DiodeCluster ( AnabaticEngine*, RoutingPad* );
|
|
|
|
virtual ~DiodeCluster ();
|
|
|
|
DbU::Unit getAntennaGateMaxWL () const;
|
|
|
|
DbU::Unit getAntennaDiodeMaxWL () const;
|
|
|
|
inline bool hasRp ( RoutingPad* ) const;
|
|
|
|
bool hasGCell ( GCell* ) const;
|
|
|
|
inline Net* getTopNet () const;
|
|
|
|
inline RoutingPad* getRefRp () const;
|
|
|
|
inline vector<GCellArea>& _getAreas ();
|
|
|
|
inline AnabaticEngine* _getAnabatic () const;
|
|
|
|
inline const RoutingPadInfos& getRoutingPads () const;
|
|
|
|
inline RoutingPadInfos& _getRoutingPads () ;
|
2021-06-08 05:19:40 -05:00
|
|
|
inline const set<size_t>& getNeighbors () const;
|
2021-05-22 08:14:32 -05:00
|
|
|
inline const vector<Instance*>& getDiodes () const;
|
|
|
|
inline vector<Instance*>& _getDiodes ();
|
2021-06-08 05:19:40 -05:00
|
|
|
inline uint32_t getForcedDiodes () const;
|
2021-05-22 08:14:32 -05:00
|
|
|
inline DbU::Unit getWL () const;
|
|
|
|
inline DbU::Unit& _getWL ();
|
|
|
|
void showArea () const;
|
|
|
|
virtual bool needsDiode () const = 0;
|
|
|
|
Box getBoundingBox () const;
|
2021-06-08 05:19:40 -05:00
|
|
|
inline void addNeighbor ( size_t );
|
|
|
|
inline void addForcedDiodes ( uint32_t );
|
2021-05-22 08:14:32 -05:00
|
|
|
void merge ( GCell*, uint32_t distance, GCell* back=NULL );
|
|
|
|
virtual void merge ( RoutingPad* );
|
|
|
|
virtual void merge ( Segment* ) = 0;
|
|
|
|
void mergeForcedHalo ( size_t iarea, GCell*, uint32_t distance );
|
|
|
|
virtual void mergeHalo ( Segment*, uint32_t flags );
|
|
|
|
virtual void inflateArea ();
|
|
|
|
Instance* _createDiode ( Etesian::Area*, const Box&, DbU::Unit uHint );
|
|
|
|
Instance* _createDiode ( Etesian::Area*, GCell*, GCell* );
|
|
|
|
virtual const vector<Instance*>& createDiodes ( Etesian::Area* );
|
|
|
|
bool connectDiodes ();
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
private:
|
2021-05-13 05:20:28 -05:00
|
|
|
AnabaticEngine* _anabatic;
|
|
|
|
DbU::Unit _WL;
|
|
|
|
RoutingPadInfos _routingPads;
|
|
|
|
vector<GCellArea> _areas;
|
|
|
|
vector<Instance*> _diodes;
|
2021-06-08 05:19:40 -05:00
|
|
|
set<size_t> _neighbors;
|
|
|
|
uint32_t _forcedDiodes;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const uint32_t DiodeCluster::IsDriver = (1 << 0);
|
|
|
|
const uint32_t DiodeCluster::IsSink = (1 << 1);
|
|
|
|
const uint32_t DiodeCluster::HasDiode = (1 << 2);
|
|
|
|
const uint32_t DiodeCluster::IsSegSource = (1 << 3);
|
2021-05-04 12:31:12 -05:00
|
|
|
const uint32_t DiodeCluster::InCluster = (1 << 4);
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
|
|
|
|
|
|
|
string DiodeCluster::toStr ( uint32_t flags )
|
|
|
|
{
|
|
|
|
string s;
|
|
|
|
s += (flags & IsDriver ) ? 'd' : '-';
|
|
|
|
s += (flags & IsSink ) ? 's' : '-';
|
|
|
|
s += (flags & HasDiode ) ? 'D' : '-';
|
|
|
|
s += (flags & IsSegSource) ? 'S' : '-';
|
2021-05-04 12:31:12 -05:00
|
|
|
s += (flags & InCluster ) ? 'C' : '-';
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
DiodeCluster::DiodeCluster ( AnabaticEngine* anabatic, RoutingPad* rp )
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
: _anabatic(anabatic)
|
|
|
|
, _WL(0)
|
|
|
|
, _routingPads()
|
2021-05-13 05:20:28 -05:00
|
|
|
, _areas(1)
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
, _diodes()
|
2021-06-08 05:19:40 -05:00
|
|
|
, _neighbors()
|
|
|
|
, _forcedDiodes(0)
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
|
|
|
merge( rp );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
DiodeCluster::~DiodeCluster ()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
2021-05-13 05:20:28 -05:00
|
|
|
inline AnabaticEngine* DiodeCluster::_getAnabatic () const { return _anabatic; }
|
|
|
|
inline vector<GCellArea>& DiodeCluster::_getAreas () { return _areas; }
|
|
|
|
inline Net* DiodeCluster::getTopNet () const { return getRefRp()->getNet(); }
|
|
|
|
inline DbU::Unit DiodeCluster::getWL () const { return _WL; }
|
|
|
|
inline DbU::Unit& DiodeCluster::_getWL () { return _WL; }
|
|
|
|
inline const RoutingPadInfos& DiodeCluster::getRoutingPads () const { return _routingPads; }
|
|
|
|
inline RoutingPadInfos& DiodeCluster::_getRoutingPads () { return _routingPads; }
|
|
|
|
inline const vector<Instance*>& DiodeCluster::getDiodes () const { return _diodes; }
|
|
|
|
inline vector<Instance*>& DiodeCluster::_getDiodes () { return _diodes; }
|
2021-06-08 05:19:40 -05:00
|
|
|
inline const set<size_t>& DiodeCluster::getNeighbors () const { return _neighbors; }
|
|
|
|
inline void DiodeCluster::addNeighbor ( size_t neighbor ) { _neighbors.insert(neighbor); }
|
|
|
|
inline uint32_t DiodeCluster::getForcedDiodes () const { return _forcedDiodes; }
|
|
|
|
inline void DiodeCluster::addForcedDiodes ( uint32_t count ) { _forcedDiodes += count; }
|
2021-05-04 12:31:12 -05:00
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
DbU::Unit DiodeCluster::getAntennaGateMaxWL () const
|
|
|
|
{
|
|
|
|
EtesianEngine* etesian = static_cast<EtesianEngine*>
|
|
|
|
( ToolEngine::get( _getAnabatic()->getCell(), EtesianEngine::staticGetName() ));
|
|
|
|
return etesian->getAntennaGateMaxWL();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit DiodeCluster::getAntennaDiodeMaxWL () const
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
2021-05-11 07:30:38 -05:00
|
|
|
EtesianEngine* etesian = static_cast<EtesianEngine*>
|
|
|
|
( ToolEngine::get( _getAnabatic()->getCell(), EtesianEngine::staticGetName() ));
|
2021-05-22 08:14:32 -05:00
|
|
|
return etesian->getAntennaDiodeMaxWL();
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool DiodeCluster::hasRp ( RoutingPad* rp ) const
|
2021-05-04 12:31:12 -05:00
|
|
|
{ return (_routingPads.find(make_tuple(rp,0)) != _routingPads.end()); }
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
|
|
|
|
|
|
|
inline bool DiodeCluster::hasGCell ( GCell* gcell ) const
|
|
|
|
{
|
|
|
|
if (not gcell) return false;
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( auto& item : _areas[0] ) {
|
2021-05-11 07:30:38 -05:00
|
|
|
if (elemGCell(item) == gcell) return true;
|
2021-05-04 12:31:12 -05:00
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline RoutingPad* DiodeCluster::getRefRp () const
|
|
|
|
{
|
2021-05-04 12:31:12 -05:00
|
|
|
if (not _routingPads.empty()) return std::get<0>( *_routingPads.begin() );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
void DiodeCluster::showArea () const
|
|
|
|
{
|
2021-05-13 05:20:28 -05:00
|
|
|
cdebug_log(147,1) << "GCell diode areas:" << endl;
|
|
|
|
for ( size_t i=0 ; i<_areas.size() ; ++i ) {
|
|
|
|
cdebug_log(147,0) << "GCell diode area [" << i << "]" << endl;
|
|
|
|
for ( auto& item : _areas[i] ) {
|
|
|
|
cdebug_log(147,0) << " | d=" << std::get<1>(item)
|
|
|
|
<< " " << std::get<0>(item)
|
|
|
|
<< " back=" << std::get<2>(item) << endl;
|
|
|
|
}
|
2021-05-04 12:31:12 -05:00
|
|
|
}
|
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
void DiodeCluster::merge ( RoutingPad* rp )
|
|
|
|
{
|
|
|
|
Plug* rpPlug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
|
|
|
|
if (rpPlug) {
|
2021-05-11 07:30:38 -05:00
|
|
|
DiodeCluster::merge( _getAnabatic()->getGCellUnder( rp->getPosition() ), 0 );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
if (rpPlug->getMasterNet()->getDirection() & Net::Direction::DirIn) {
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| Sink " << rp << endl;
|
2021-05-11 07:30:38 -05:00
|
|
|
_getRoutingPads().insert( make_tuple(rp,IsSink) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
} else {
|
2021-05-11 07:30:38 -05:00
|
|
|
_getRoutingPads().insert( make_tuple(rp,IsDriver) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
cdebug_log(147,0) << "| Driver " << rp << endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Pin* rpPin = dynamic_cast<Pin*>( rp->getPlugOccurrence().getEntity() );
|
|
|
|
if (rpPin) {
|
2021-05-11 07:30:38 -05:00
|
|
|
_getRoutingPads().insert( make_tuple(rp,IsDriver) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
cdebug_log(147,0) << "| Pin (considered driver) " << rp << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
void DiodeCluster::merge ( GCell* gcell, uint32_t distance, GCell* back )
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
|
|
|
if (not gcell) return;
|
2021-05-04 12:31:12 -05:00
|
|
|
if (hasGCell(gcell)) return;
|
|
|
|
if (back) distance += 20;
|
2021-05-13 05:20:28 -05:00
|
|
|
_areas[0].insert( make_tuple(gcell,distance,back) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiodeCluster::mergeForcedHalo ( size_t iarea, GCell* gcell, uint32_t distance )
|
|
|
|
{
|
|
|
|
if (not gcell) return;
|
|
|
|
while ( iarea >= _areas.size() ) _areas.push_back( GCellArea() );
|
|
|
|
_areas[iarea].insert( make_tuple(gcell,distance,(GCell*)NULL) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Box DiodeCluster::getBoundingBox () const
|
|
|
|
{
|
|
|
|
Box bb;
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( auto& item : _areas[0] ) bb.merge( elemGCell(item)->getBoundingBox() );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
return bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
void DiodeCluster::mergeHalo ( Segment* segment, uint32_t flags )
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
2021-05-11 07:30:38 -05:00
|
|
|
cerr << Error( "DiodeCluster::mergeHalo(Segment*): Unimplemented (%s). "
|
|
|
|
, getString(segment).c_str() ) << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
|
|
|
|
void DiodeCluster::inflateArea ()
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
2021-05-11 07:30:38 -05:00
|
|
|
cerr << Error( "DiodeCluster::inflateArea(): Unimplemented. " ) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Instance* DiodeCluster::_createDiode ( Etesian::Area* area, const Box& bb, DbU::Unit uHint )
|
|
|
|
{
|
|
|
|
cdebug_log(147,1) << "DiodeCluster::_createDiode(): under=" << bb
|
|
|
|
<< " uHint=" << DbU::getValueString(uHint) << endl;
|
2021-05-04 12:31:12 -05:00
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
Instance* diode = area->createDiodeUnder( getRefRp(), bb, uHint );
|
|
|
|
if (diode) {
|
|
|
|
cdebug_log(147,0) << "| New diode " << diode << endl;
|
|
|
|
_diodes.push_back( diode );
|
|
|
|
GCell* gcell = _anabatic->getGCellUnder( diode->getAbutmentBox().getCenter() );
|
|
|
|
Contact* contact = gcell->hasGContact( getTopNet() );
|
|
|
|
if (not contact)
|
|
|
|
contact = gcell->breakGoThrough( getTopNet() );
|
|
|
|
cdebug_log(147,0) << "| breakGoThrough(), contact= " << contact << endl;
|
2021-05-04 12:31:12 -05:00
|
|
|
}
|
2021-05-11 07:30:38 -05:00
|
|
|
|
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
return diode;
|
2021-05-04 12:31:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
Instance* DiodeCluster::_createDiode ( Etesian::Area* area, GCell* gcell, GCell* backGCell )
|
2021-05-04 12:31:12 -05:00
|
|
|
{
|
2021-05-11 07:30:38 -05:00
|
|
|
cdebug_log(147,1) << "DiodeCluster::_createDiode(): under=" << gcell << endl;
|
2021-05-04 12:31:12 -05:00
|
|
|
|
|
|
|
Box bb = gcell->getBoundingBox();
|
|
|
|
cdebug_log(147,0) << "> GCell area: " << bb << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
Instance* diode = area->createDiodeUnder( getRefRp(), bb, 0 );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
if (diode) {
|
2021-05-11 07:30:38 -05:00
|
|
|
cdebug_log(147,0) << "| New diode " << diode << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
_diodes.push_back( diode );
|
2021-03-29 12:03:26 -05:00
|
|
|
Transformation trans = getRefRp()->getPlugOccurrence().getPath().getTransformation();
|
|
|
|
Point center = diode->getAbutmentBox().getCenter();
|
|
|
|
trans.applyOn( center );
|
2021-05-04 12:31:12 -05:00
|
|
|
bool newContact = false;
|
|
|
|
Contact* contact = gcell->hasGContact( getTopNet() );
|
|
|
|
if (not contact) {
|
|
|
|
newContact = true;
|
|
|
|
contact = gcell->breakGoThrough( getTopNet() );
|
|
|
|
}
|
|
|
|
cdebug_log(147,0) << "| breakGoThrough(), contact= " << contact << endl;
|
|
|
|
|
|
|
|
if (backGCell and newContact) {
|
|
|
|
Contact* backContact = backGCell->breakGoThrough( getTopNet() );
|
|
|
|
if (backContact->getY() == contact->getY()) {
|
|
|
|
if (contact->getX() > backContact->getX())
|
|
|
|
std::swap( backContact, contact );
|
|
|
|
|
|
|
|
Horizontal::create( contact
|
|
|
|
, backContact
|
|
|
|
, _anabatic->getConfiguration()->getGHorizontalLayer()
|
|
|
|
, contact->getY()
|
|
|
|
, _anabatic->getConfiguration()->getGHorizontalPitch()
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
if (backContact->getX() == contact->getX()) {
|
|
|
|
if (contact->getY() > backContact->getY())
|
|
|
|
std::swap( backContact, contact );
|
|
|
|
|
|
|
|
Vertical::create( contact
|
|
|
|
, backContact
|
|
|
|
, _anabatic->getConfiguration()->getGHorizontalLayer()
|
|
|
|
, contact->getX()
|
|
|
|
, _anabatic->getConfiguration()->getGHorizontalPitch()
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
);
|
2021-05-04 12:31:12 -05:00
|
|
|
} else {
|
2021-05-11 07:30:38 -05:00
|
|
|
cerr << Error( "DiodeCluster::_createDiode(): Back GCell not aligned with diode GCell.\n"
|
2021-05-04 12:31:12 -05:00
|
|
|
" * %s\n"
|
|
|
|
" * %s"
|
|
|
|
, getString(gcell).c_str()
|
|
|
|
, getString(backGCell).c_str()
|
|
|
|
) << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-11 07:30:38 -05:00
|
|
|
cdebug_tabw(147,-1);
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
return diode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-13 05:20:28 -05:00
|
|
|
const vector<Instance*>& DiodeCluster::createDiodes ( Etesian::Area* area )
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
{
|
|
|
|
if (not needsDiode()) return _diodes;
|
2021-05-11 07:30:38 -05:00
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
DbU::Unit antennaDiodeMaxWL = getAntennaDiodeMaxWL();
|
|
|
|
size_t diodeCount = getWL() / antennaDiodeMaxWL;
|
2021-05-11 07:30:38 -05:00
|
|
|
if (not diodeCount) diodeCount = 1;
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
showArea();
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
cdebug_log(147,1) << "DiodeCluster::createDiodes() count=" << diodeCount
|
2021-05-13 05:20:28 -05:00
|
|
|
<< ", forcedHalo=" << (_areas.size()-1) << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
Instance* diode = NULL;
|
2021-06-08 05:19:40 -05:00
|
|
|
//for ( size_t i=(_areas.size() == 1)?0:1 ; i<_areas.size() ; ++i ) {
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( size_t i=0 ; i<_areas.size() ; ++i ) {
|
|
|
|
if (i) diodeCount = 1;
|
|
|
|
cdebug_log(147,0) << "Diode for area [" << i << "]" << endl;
|
|
|
|
for ( auto& item : _areas[i] ) {
|
|
|
|
GCell* gcell = std::get<0>( item );
|
|
|
|
GCell* backGCell = std::get<2>( item );
|
|
|
|
cdebug_log(147,0) << "| d=" << std::get<1>(item) << " " << gcell << endl;
|
|
|
|
diode = _createDiode( area, gcell, backGCell );
|
|
|
|
if (diode) {
|
|
|
|
if (_diodes.size() < diodeCount) {
|
|
|
|
diode = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2021-05-11 07:30:38 -05:00
|
|
|
}
|
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_tabw(147,-1);
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
|
|
|
return _diodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
bool DiodeCluster::connectDiodes ()
|
|
|
|
{
|
|
|
|
EtesianEngine* etesian = static_cast<EtesianEngine*>
|
|
|
|
( ToolEngine::get( _anabatic->getCell(), EtesianEngine::staticGetName() ));
|
|
|
|
|
|
|
|
Cell* diodeCell = etesian->getDiodeCell();
|
|
|
|
Net* diodeOutput = NULL;
|
|
|
|
for ( Net* net : diodeCell->getNets() ) {
|
|
|
|
if (net->isSupply() or not net->isExternal()) continue;
|
|
|
|
diodeOutput = net;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Net* topNet = getTopNet();
|
|
|
|
Net* diodeNet = topNet;
|
|
|
|
Plug* sinkPlug = dynamic_cast<Plug*>( getRefRp()->getPlugOccurrence().getEntity() );
|
|
|
|
Path path = Path();
|
|
|
|
|
|
|
|
if (sinkPlug) {
|
|
|
|
diodeNet = sinkPlug->getNet();
|
|
|
|
path = getRefRp()->getOccurrence().getPath().getHeadPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( Instance* diode : _diodes ) {
|
|
|
|
cdebug_log(147,0) << " Bind diode input:" << endl;
|
|
|
|
cdebug_log(147,0) << " " << diode << " @" << diode->getTransformation() << endl;
|
|
|
|
cdebug_log(147,0) << " topNet->getCell():" << topNet->getCell() << endl;
|
|
|
|
cdebug_log(147,0) << " " << getRefRp()->getOccurrence().getPath() << endl;
|
|
|
|
Plug* diodePlug = diode->getPlug( diodeOutput );
|
|
|
|
diodePlug->setNet( diodeNet );
|
|
|
|
RoutingPad* diodeRp = RoutingPad::create( topNet, Occurrence(diodePlug,path), RoutingPad::BiggestArea );
|
|
|
|
cdebug_log(147,0) << " " << getRefRp() << endl;
|
|
|
|
|
|
|
|
GCell* gcell = _anabatic->getGCellUnder( diodeRp->getPosition() );
|
|
|
|
if (gcell) {
|
|
|
|
Contact* contact = gcell->breakGoThrough( topNet );
|
|
|
|
contact->getBodyHook()->merge( diodeRp->getBodyHook() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
// Class : "::DiodeRps".
|
|
|
|
|
|
|
|
class DiodeRps : public DiodeCluster {
|
|
|
|
public:
|
|
|
|
DiodeRps ( AnabaticEngine*, RoutingPad* );
|
|
|
|
virtual bool needsDiode () const;
|
|
|
|
virtual void merge ( Segment* );
|
|
|
|
virtual void mergeHalo ( Segment*, uint32_t flags );
|
|
|
|
virtual void inflateArea ();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
DiodeRps::DiodeRps ( AnabaticEngine* anabatic, RoutingPad* rp )
|
|
|
|
: DiodeCluster(anabatic,rp)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
bool DiodeRps::needsDiode () const
|
|
|
|
{
|
2021-06-08 05:19:40 -05:00
|
|
|
if (getForcedDiodes()) return true;
|
2021-05-11 07:30:38 -05:00
|
|
|
for ( auto& infos : getRoutingPads() ) {
|
|
|
|
if (std::get<1>(infos) & IsSink) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiodeRps::merge ( Segment* segment )
|
|
|
|
{
|
|
|
|
_getWL() += segment->getLength();
|
|
|
|
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment );
|
|
|
|
if (not gcells->empty()) {
|
|
|
|
for ( size_t i=0 ; i<gcells->size() ; ++i ) {
|
|
|
|
DiodeCluster::merge( gcells->gcellAt(i), 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiodeRps::mergeHalo ( Segment* segment, uint32_t flags )
|
|
|
|
{
|
|
|
|
cdebug_log(147,0) << "DiodeRps::mergeHalo(): " << segment << endl;
|
|
|
|
if (not segment) return;
|
|
|
|
|
2021-06-08 05:19:40 -05:00
|
|
|
// if ( (dynamic_cast<Horizontal*>(segment))
|
|
|
|
// and (getWL() + segment->getLength() > getAntennaGateMaxWL())) {
|
|
|
|
if (dynamic_cast<Horizontal*>(segment)) {
|
2021-05-13 05:20:28 -05:00
|
|
|
cdebug_log(147,0) << " Put in forced halo." << segment << endl;
|
|
|
|
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment );
|
|
|
|
if (not gcells->empty()) {
|
|
|
|
size_t iarea = _getAreas().size();
|
2021-05-22 08:14:32 -05:00
|
|
|
size_t count = std::min( gcells->size(), (size_t)50 );
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( size_t i=0 ; i<count ; ++i ) {
|
|
|
|
size_t igcell = (flags & IsSegSource) ? i : (gcells->size()-1-i);
|
|
|
|
DiodeCluster::mergeForcedHalo( iarea, gcells->gcellAt(igcell), i );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment );
|
|
|
|
if (not gcells->empty()) {
|
|
|
|
size_t count = std::min( gcells->size(), (size_t)10 );
|
|
|
|
for ( size_t i=0 ; i<count ; ++i ) {
|
|
|
|
size_t igcell = (flags & IsSegSource) ? i : (gcells->size()-1-i);
|
|
|
|
DiodeCluster::merge( gcells->gcellAt(igcell), i+1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiodeRps::inflateArea ()
|
|
|
|
{
|
|
|
|
vector< tuple<GCell*,GCell*> > border;
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( auto& item : _getAreas()[0] ) {
|
2021-05-11 07:30:38 -05:00
|
|
|
GCell* current = std::get<0>( item );
|
|
|
|
if (std::get<2>(item)) continue;
|
|
|
|
|
|
|
|
GCell* neighbor = current->getEast();
|
|
|
|
if (neighbor and not neighbor->hasNet(getTopNet()))
|
|
|
|
border.push_back( make_tuple(neighbor,current) );
|
|
|
|
neighbor = current->getWest();
|
|
|
|
if (neighbor and not neighbor->hasNet(getTopNet()))
|
|
|
|
border.push_back( make_tuple(neighbor,current) );
|
|
|
|
}
|
|
|
|
|
2021-05-13 05:20:28 -05:00
|
|
|
for ( auto& item : _getAreas()[0] ) {
|
2021-05-11 07:30:38 -05:00
|
|
|
GCell* current = std::get<0>( item );
|
|
|
|
if (std::get<2>(item)) continue;
|
|
|
|
|
|
|
|
GCell* neighbor = current->getNorth();
|
|
|
|
if (neighbor and not neighbor->hasNet(getTopNet()))
|
|
|
|
border.push_back( make_tuple(neighbor,current) );
|
|
|
|
neighbor = current->getSouth();
|
|
|
|
if (neighbor and not neighbor->hasNet(getTopNet()))
|
|
|
|
border.push_back( make_tuple(neighbor,current) );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( auto& item : border ) {
|
|
|
|
DiodeCluster::merge( std::get<0>(item), 1, std::get<1>(item) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
// Class : "::DiodeWire".
|
|
|
|
|
|
|
|
class DiodeWire : public DiodeCluster {
|
|
|
|
public:
|
2021-06-08 05:19:40 -05:00
|
|
|
DiodeWire ( AnabaticEngine*, RoutingPad* );
|
|
|
|
virtual bool needsDiode () const;
|
|
|
|
virtual void merge ( Segment* );
|
|
|
|
virtual const vector<Instance*>& createDiodes ( Etesian::Area* );
|
|
|
|
inline const set<Segment*,Go::CompareById>& getSegments () const;
|
2021-05-11 07:30:38 -05:00
|
|
|
private:
|
|
|
|
set<Box,CompareBySegmentBox> _boxes;
|
|
|
|
set<Contact*,Go::CompareById> _contacts;
|
2021-06-08 05:19:40 -05:00
|
|
|
set<Segment*,Go::CompareById> _segments;
|
2021-05-11 07:30:38 -05:00
|
|
|
};
|
|
|
|
|
2021-06-08 05:19:40 -05:00
|
|
|
|
|
|
|
inline const set<Segment*,Go::CompareById>& DiodeWire::getSegments () const { return _segments; }
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
|
|
|
|
DiodeWire::DiodeWire ( AnabaticEngine* anabatic, RoutingPad* rp )
|
|
|
|
: DiodeCluster(anabatic,rp)
|
|
|
|
, _boxes()
|
|
|
|
, _contacts()
|
2021-06-08 05:19:40 -05:00
|
|
|
, _segments()
|
2021-05-11 07:30:38 -05:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
bool DiodeWire::needsDiode () const
|
2021-05-22 08:14:32 -05:00
|
|
|
{ return getWL() >= getAntennaDiodeMaxWL(); }
|
2021-05-11 07:30:38 -05:00
|
|
|
|
|
|
|
|
|
|
|
void DiodeWire::merge ( Segment* segment )
|
|
|
|
{
|
2021-06-08 05:19:40 -05:00
|
|
|
if (_segments.find(segment) != _segments.end()) return;
|
2021-05-11 07:30:38 -05:00
|
|
|
Box bb = segment->getBoundingBox();
|
|
|
|
cdebug_log(147,0) << "| merge: " << segment << endl;
|
2021-06-08 05:19:40 -05:00
|
|
|
_segments.insert( segment );
|
2021-05-11 07:30:38 -05:00
|
|
|
_boxes.insert( bb );
|
|
|
|
_getWL() += segment->getLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-13 05:20:28 -05:00
|
|
|
const vector<Instance*>& DiodeWire::createDiodes ( Etesian::Area* area )
|
2021-05-11 07:30:38 -05:00
|
|
|
{
|
2021-06-08 05:19:40 -05:00
|
|
|
cdebug_log(147,1) << "DiodeWire::createDiodes() on " << _boxes.size() << " boxes." << endl;
|
|
|
|
|
|
|
|
ostringstream m;
|
|
|
|
m << "Neighbors: [";
|
|
|
|
for ( size_t neighbor : getNeighbors() ) { m << " " << neighbor; }
|
|
|
|
m << " ]";
|
|
|
|
cdebug_log(147,0) << m.str() << endl;
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
DbU::Unit antennaDiodeMaxWL = getAntennaDiodeMaxWL();
|
2021-05-11 07:30:38 -05:00
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
size_t diodeCount = getWL() / antennaDiodeMaxWL;
|
2021-05-11 07:30:38 -05:00
|
|
|
if (not diodeCount) return _getDiodes();
|
|
|
|
|
|
|
|
for ( const Box& bb : _boxes ) {
|
|
|
|
bool bbH = (bb.getWidth() >= bb.getHeight());
|
|
|
|
DbU::Unit bbLength = (bbH) ? bb.getWidth() : bb.getHeight();
|
2021-05-22 08:14:32 -05:00
|
|
|
size_t segDiodeCount = bbLength / antennaDiodeMaxWL;
|
2021-05-11 07:30:38 -05:00
|
|
|
if (not segDiodeCount) ++segDiodeCount;
|
2021-05-22 08:14:32 -05:00
|
|
|
bool isH = (bb.getWidth() >= bb.getHeight());
|
2021-06-08 05:19:40 -05:00
|
|
|
cdebug_log(147,0) << "Processing wire diodes=" << segDiodeCount << " " << bb
|
2021-05-22 08:14:32 -05:00
|
|
|
<< " isH=" << isH
|
|
|
|
<< " length:" << DbU::getValueString(getBoxLength(bb)) << endl;
|
|
|
|
//if (bbLength < antennaDiodeMaxWL/4) continue;
|
2021-05-11 07:30:38 -05:00
|
|
|
|
|
|
|
if (bbH) {
|
|
|
|
DbU::Unit uHint = bb.getXMin();
|
|
|
|
DbU::Unit uMax = bb.getXMax();
|
|
|
|
while ( uHint < uMax ) {
|
|
|
|
_createDiode( area, bb, uHint );
|
2021-05-22 08:14:32 -05:00
|
|
|
uHint += antennaDiodeMaxWL;
|
2021-05-11 07:30:38 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( Point(bb.getXCenter(),bb.getYMin())
|
|
|
|
, Point(bb.getXCenter(),bb.getYMax()) );
|
|
|
|
if (gcells->size()) {
|
2021-05-22 08:14:32 -05:00
|
|
|
size_t gcellPeriod = antennaDiodeMaxWL / gcells->gcellAt(0)->getHeight();
|
2021-05-11 07:30:38 -05:00
|
|
|
for ( size_t i=0 ; i<gcells->size() ; ++i ) {
|
|
|
|
Instance* diode = _createDiode( area, gcells->gcellAt(i), NULL );
|
|
|
|
if (diode) {
|
|
|
|
i += gcellPeriod - (i%gcellPeriod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-06-08 05:19:40 -05:00
|
|
|
|
|
|
|
if (_getDiodes().size() >= diodeCount) {
|
|
|
|
cdebug_log(147,0) << "Added enough diodes " << _getDiodes().size() << endl;
|
|
|
|
break;
|
|
|
|
}
|
2021-05-11 07:30:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_getDiodes().size() < diodeCount) {
|
|
|
|
cerr << Error( "DiodeWire::createDiode(): On cluster of net \"%s\",\n"
|
|
|
|
" Allocated only %u diodes of %u."
|
|
|
|
, getString(getTopNet()->getName()).c_str()
|
|
|
|
, _getDiodes().size()
|
|
|
|
, diodeCount
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
return _getDiodes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
// Local functions.
|
|
|
|
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
} // Anonymous namespace.
|
|
|
|
|
|
|
|
|
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using namespace Hurricane;
|
|
|
|
using CRL::ToolEngine;
|
|
|
|
using Etesian::EtesianEngine;
|
|
|
|
|
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
//! \function AnabaticEngine::antennaProtect( Net* net, uint32_t& failed, uint32_t& total );
|
|
|
|
//! \param net The net to protect against antenna effects.
|
|
|
|
//! \param failed A reference to the global counter of diodes that we
|
|
|
|
//! where unsucessful to allocate.
|
|
|
|
//! \param total The total number of diode that where requesteds.
|
|
|
|
//! counting both successful and unsuccessful allocations.
|
|
|
|
//!
|
|
|
|
//! \section antennaSettings Configuration Variable for Antenna Effect
|
|
|
|
//!
|
|
|
|
//! <center>
|
|
|
|
//! <table class="UserDefined" width="50%">
|
|
|
|
//! <tr><td>\c etesian.antennaMaxWL
|
|
|
|
//! <td>The maximum wirelength whitout a diode effect
|
|
|
|
//! </table>
|
|
|
|
//! </center>
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! \section antennaAlgo A Brief Description of the Antenna Protection Algorithm.
|
|
|
|
//!
|
|
|
|
//! The brute force approach would be to put a diode near all sink
|
|
|
|
//! points of the net. To reduce that number, we create clusters whose
|
|
|
|
//! total wirelength is less than the one triggering an antenna effect.
|
|
|
|
//!
|
|
|
|
//! The antenna protection stage is called after the global routing
|
|
|
|
//! and before the detailed routing. The computed wirelength will be
|
|
|
|
//! slightly inaccurate but it allow us to directly amend the global
|
|
|
|
//! routing so the detailed router needs no modification.
|
|
|
|
//!
|
|
|
|
//! To build the clusters:
|
|
|
|
//!
|
|
|
|
//! <ol>
|
|
|
|
//! <li>Select an unreached (not part of a cluster) RoutingPad.</li>
|
|
|
|
//! <li>Perform a depth-first search (DFS) using the segments as edges
|
|
|
|
//! and the Hook rings as nodes. Use a stack to store the search
|
|
|
|
//! state. An element of the stack is a \c tuple of
|
|
|
|
//! \c(Hook*,Segment*,size_t,uint32_t) :
|
|
|
|
//!
|
|
|
|
//! <ol>
|
|
|
|
//! <li>\c Hook* : the hook of the Segment we are coming \e from.</li>
|
|
|
|
//! <li>\c Segment* : the segment we are to process.</li>
|
|
|
|
//! <li>\c size_t : the index, in the stack, of the predecessor
|
|
|
|
//! segment.</li>
|
|
|
|
//! <li>\c uint32_t : flags. If this segment is \b already part
|
|
|
|
//! of the cluster.
|
|
|
|
//! </ol>
|
|
|
|
//!
|
|
|
|
//! All the elements are kept in the stack until the cluster is
|
|
|
|
//! completed. The current top of the stack is given by the \c stackTop
|
|
|
|
//! index.
|
|
|
|
//!
|
|
|
|
//! When exploring a new node (ring of Hook), all the adjacent segments
|
|
|
|
//! are put on top of the stack. Their suitablility is assesssed only
|
|
|
|
//! when they are popped up.
|
|
|
|
//! </li>
|
|
|
|
//! <li>When looking at a new stack element (incrementing \c stackTop, not
|
|
|
|
//! really popping up):
|
|
|
|
//!
|
|
|
|
//! <ol>
|
|
|
|
//! <li>If the segment length is greater than half the maximum antenna
|
|
|
|
//! wirelength, skip it (assume it connects two clusters).</li>
|
|
|
|
//! <li>If the segment length, added to the cluster total length,
|
|
|
|
//! is greater than the antenna length, skip it.
|
|
|
|
//! <li>If the segment is connected to another RoutingPad, agglomerate
|
|
|
|
//! this one the the cluster and merge the segment and all it's
|
|
|
|
//! predecessors to the cluster. Using the back index and setting
|
|
|
|
//! the DiodeCluster::InCluster flags.
|
|
|
|
//! </ol>
|
|
|
|
//! </li>
|
|
|
|
//! <li>When we reach the end of the stack, close the cluster and build
|
|
|
|
//! it's halo. Go through each elements of the stack again and look
|
|
|
|
//! for segments not part of it, but directly connected to it
|
|
|
|
//! (that is, they have not the InCluster flags set, but their
|
|
|
|
//! immediate predecessor has).
|
|
|
|
//! </li>
|
|
|
|
//! </ol>
|
|
|
|
//!
|
|
|
|
//! Structure of a Cluster:
|
|
|
|
//!
|
|
|
|
//! <ol>
|
|
|
|
//! <li>A vector of RoutingPad.</li>
|
|
|
|
//! <li>A set of GCells, ordered by priority (distance).
|
|
|
|
//! <ol>
|
|
|
|
//! <li>A distance of zero means we are under the Segments belonging
|
|
|
|
//! to the cluster itself (directly connecting the RoutingPad).
|
|
|
|
//! </li>
|
|
|
|
//! <li>A distance between 1 to 9 means we are under the halo, that
|
|
|
|
//! is, Segments that <em>connects to</em> the cluster, with the
|
|
|
|
//! increasing distance.
|
|
|
|
//! </li>
|
|
|
|
//! <li>A distance between 10 to 19 means a GCell which is an
|
|
|
|
//! immediate neighbor of the core or halo segments.
|
|
|
|
//! </li>
|
|
|
|
//! </ol>
|
|
|
|
//! </li>
|
|
|
|
//! </ol>
|
|
|
|
//!
|
|
|
|
//! We try to create the cluster's diode in the GCell of the lowest distance
|
|
|
|
//! possible.
|
|
|
|
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
void AnabaticEngine::antennaProtect ( Net* net, uint32_t& failed, uint32_t& total )
|
|
|
|
{
|
2021-05-04 12:31:12 -05:00
|
|
|
// tuple is: Hook (S or T), From segment, back segment index, flags.
|
|
|
|
typedef tuple<Hook*,Segment*,size_t,uint32_t> StackItem;
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
DebugSession::open( net, 145, 150 );
|
|
|
|
cdebug_log(147,1) << "Net \"" << net->getName() << endl;
|
|
|
|
|
|
|
|
EtesianEngine* etesian = static_cast<EtesianEngine*>
|
|
|
|
( ToolEngine::get( getCell(), EtesianEngine::staticGetName() ));
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
DbU::Unit antennaGateMaxWL = etesian->getAntennaGateMaxWL();
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-06-08 05:19:40 -05:00
|
|
|
vector<DiodeCluster*> clusters;
|
|
|
|
map<RoutingPad*,size_t,DBo::CompareById> rpsDone;
|
|
|
|
map<Segment*,size_t,DBo::CompareById> clusterSegments;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
2021-05-04 12:31:12 -05:00
|
|
|
set<Segment*,DBo::CompareById> segmentsDone;
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
if (rpsDone.find(rp) != rpsDone.end()) continue;
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
cdebug_log(147,0) << "New Cluster [" << clusters.size() << "] from " << rp << endl;
|
2021-05-11 07:30:38 -05:00
|
|
|
DiodeCluster* cluster = new DiodeRps ( this, rp );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
clusters.push_back( cluster );
|
2021-06-08 05:19:40 -05:00
|
|
|
rpsDone.insert( make_pair( rp, clusters.size()-1 ) );
|
2021-05-04 12:31:12 -05:00
|
|
|
|
|
|
|
size_t stackTop = 0;
|
|
|
|
vector< StackItem > hooksStack;
|
|
|
|
hooksStack.push_back( make_tuple( rp->getBodyHook()
|
|
|
|
, (Segment*)NULL
|
|
|
|
, 0
|
|
|
|
, DiodeCluster::InCluster ) );
|
|
|
|
while ( stackTop < hooksStack.size() ) {
|
|
|
|
Hook* toHook = std::get<0>( hooksStack[stackTop] );
|
|
|
|
Segment* fromSegment = std::get<1>( hooksStack[stackTop] );
|
|
|
|
DbU::Unit branchWL = 0;
|
|
|
|
|
|
|
|
cdebug_log(147,0) << "| PROCESS [" << stackTop << "] " << fromSegment << endl;
|
|
|
|
if (fromSegment) {
|
2021-05-22 08:14:32 -05:00
|
|
|
if (fromSegment->getLength() > antennaGateMaxWL/2) {
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| Long connecting wire, skipping" << endl;
|
|
|
|
++stackTop;
|
|
|
|
continue;
|
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
size_t backIndex = stackTop;
|
|
|
|
while ( backIndex ) {
|
|
|
|
Segment* segment = std::get<1>( hooksStack[backIndex] );
|
|
|
|
branchWL += segment->getLength();
|
|
|
|
backIndex = std::get<2>( hooksStack[backIndex] );
|
|
|
|
if (not backIndex) break;
|
|
|
|
if (std::get<3>( hooksStack[backIndex] ) & DiodeCluster::InCluster) break;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
}
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| wl=" << DbU::getValueString(cluster->getWL())
|
|
|
|
<< " + " << DbU::getValueString(branchWL) << endl;
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
if (cluster->getWL() + branchWL > antennaGateMaxWL) {
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| Cluster above maximul WL, skipping" << endl;
|
|
|
|
++stackTop;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
rp = NULL;
|
|
|
|
for ( Hook* hook : toHook->getHooks() ) {
|
|
|
|
RoutingPad* toRp = dynamic_cast<RoutingPad*>( hook->getComponent() );
|
|
|
|
if (toRp) {
|
|
|
|
if (rpsDone.find(toRp) == rpsDone.end()) {
|
|
|
|
cdebug_log(147,0) << "> Agglomerate " << toRp << endl;
|
|
|
|
cluster->merge( toRp );
|
2021-06-08 05:19:40 -05:00
|
|
|
rpsDone.insert( make_pair( toRp, clusters.size()-1 ) );
|
2021-05-04 12:31:12 -05:00
|
|
|
rp = toRp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rp) {
|
|
|
|
size_t backIndex = stackTop;
|
|
|
|
cdebug_log(147,1) << "+ Backtrack" << endl;
|
|
|
|
while ( backIndex ) {
|
|
|
|
Segment* segment = std::get<1>( hooksStack[backIndex] );
|
|
|
|
if (segment->getLength() <= branchWL) branchWL -= segment->getLength();
|
|
|
|
else branchWL = 0;
|
|
|
|
cluster->merge( segment );
|
|
|
|
std::get<3>( hooksStack[backIndex] ) |= DiodeCluster::InCluster;
|
2021-06-08 05:19:40 -05:00
|
|
|
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| back=" << backIndex
|
|
|
|
<< " -> " << std::get<2>( hooksStack[backIndex] )
|
|
|
|
<< " " << DbU::getValueString(segment->getLength())
|
|
|
|
<< " " << segment << endl;
|
|
|
|
|
|
|
|
backIndex = std::get<2>( hooksStack[backIndex] );
|
|
|
|
if (std::get<3>( hooksStack[backIndex] ) & DiodeCluster::InCluster) {
|
|
|
|
cdebug_log(147,0) << "| stop=" << backIndex << " is part of the cluster" << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
for ( Hook* hook : toHook->getHooks() ) {
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
Segment* segment = dynamic_cast<Segment*>( hook->getComponent() );
|
|
|
|
if (segment) {
|
2021-05-04 12:31:12 -05:00
|
|
|
if (segment == fromSegment) continue;
|
|
|
|
cdebug_log(147,0) << "| progress wl=" << DbU::getValueString(cluster->getWL())
|
|
|
|
<< " + " << DbU::getValueString(branchWL)
|
|
|
|
<< " / " << DbU::getValueString(segment->getLength())
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
<< " " << segment << endl;
|
|
|
|
if (segmentsDone.find(segment) != segmentsDone.end()) continue;
|
|
|
|
segmentsDone.insert( segment );
|
2021-05-04 12:31:12 -05:00
|
|
|
uint32_t flags = (segment->getSourceHook() == hook) ? DiodeCluster::IsSegSource : 0;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
if (dynamic_cast<Segment::SourceHook*>(hook)) {
|
2021-05-04 12:31:12 -05:00
|
|
|
hooksStack.push_back( make_tuple( segment->getTargetHook(), segment, stackTop, flags ) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
} else {
|
2021-05-04 12:31:12 -05:00
|
|
|
hooksStack.push_back( make_tuple( segment->getSourceHook(), segment, stackTop, flags ) );
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-04 12:31:12 -05:00
|
|
|
|
|
|
|
++stackTop;
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_log(147,0) << "Cluster halo" << endl;
|
|
|
|
for ( size_t i=1 ; i<hooksStack.size() ; ++i ) {
|
|
|
|
Segment* segment = std::get<1>( hooksStack[i] );
|
|
|
|
uint32_t flags = std::get<3>( hooksStack[i] );
|
|
|
|
cdebug_log(147,0) << "| [" << i << "] flags=" << flags << " " << segment << endl;
|
|
|
|
if (not (flags & DiodeCluster::InCluster)) {
|
|
|
|
size_t j = std::get<2>( hooksStack[i] );
|
|
|
|
if (std::get<3>(hooksStack[j]) & DiodeCluster::InCluster) {
|
|
|
|
cdebug_log(147,0) << "> Put in halo." << endl;
|
|
|
|
cluster->mergeHalo( segment, flags );
|
|
|
|
}
|
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "Cluster border" << endl;
|
|
|
|
cluster->inflateArea();
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (clusters.size() > 1) {
|
2021-06-18 12:17:24 -05:00
|
|
|
NetData* netData = getNetData( net );
|
|
|
|
size_t rpClustersSize = clusters.size();
|
|
|
|
|
|
|
|
if (netData) {
|
|
|
|
for ( auto item : clusterSegments ) {
|
|
|
|
cdebug_log(147,0) << "No move up: " << item.first << endl;
|
|
|
|
netData->setNoMoveUp( item.first );
|
|
|
|
}
|
|
|
|
}
|
2021-06-08 05:19:40 -05:00
|
|
|
|
|
|
|
cdebug_log(147,0) << "Cluster wiring, rpClustersSize=" << rpClustersSize << endl;
|
2021-05-11 07:30:38 -05:00
|
|
|
for ( Segment* segment : net->getSegments() ) {
|
|
|
|
if (clusterSegments.find(segment) != clusterSegments.end()) continue;
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
cdebug_log(147,0) << "New Cluster [" << clusters.size()
|
|
|
|
<< "] wiring from " << segment << endl;
|
2021-05-11 07:30:38 -05:00
|
|
|
DiodeWire* cluster = new DiodeWire( this, clusters[0]->getRefRp() );
|
|
|
|
cluster->merge( segment );
|
|
|
|
clusters.push_back( cluster );
|
2021-06-08 05:19:40 -05:00
|
|
|
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
|
2021-05-11 07:30:38 -05:00
|
|
|
|
|
|
|
size_t stackTop = 0;
|
|
|
|
vector< StackItem > hooksStack;
|
|
|
|
hooksStack.push_back( make_tuple( segment->getSourceHook()
|
|
|
|
, segment
|
|
|
|
, 0
|
|
|
|
, DiodeCluster::IsSegSource ) );
|
|
|
|
hooksStack.push_back( make_tuple( segment->getTargetHook()
|
|
|
|
, segment
|
|
|
|
, 0
|
|
|
|
, 0 ) );
|
|
|
|
|
|
|
|
while ( stackTop < hooksStack.size() ) {
|
|
|
|
Hook* toHook = std::get<0>( hooksStack[stackTop] );
|
|
|
|
Segment* fromSegment = std::get<1>( hooksStack[stackTop] );
|
|
|
|
|
2021-05-22 08:14:32 -05:00
|
|
|
bool hasRp = false;
|
2021-05-11 07:30:38 -05:00
|
|
|
for ( Hook* hook : toHook->getHooks() ) {
|
2021-06-08 05:19:40 -05:00
|
|
|
RoutingPad* rp = dynamic_cast<RoutingPad*>( hook->getComponent() );
|
|
|
|
if (rp) {
|
2021-05-22 08:14:32 -05:00
|
|
|
hasRp = true;
|
2021-06-08 05:19:40 -05:00
|
|
|
auto irp = rpsDone.find( rp );
|
|
|
|
if (irp != rpsDone.end()) {
|
|
|
|
size_t neighbor = (*irp).second;
|
|
|
|
cdebug_log(147,0) << "| " << rp << " belongs to [" << neighbor << "]" << endl;
|
|
|
|
cluster->addNeighbor( neighbor );
|
|
|
|
}
|
2021-05-22 08:14:32 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not hasRp) {
|
|
|
|
for ( Hook* hook : toHook->getHooks() ) {
|
|
|
|
Segment* segment = dynamic_cast<Segment*>( hook->getComponent() );
|
|
|
|
if (segment) {
|
|
|
|
if (segment == fromSegment) continue;
|
2021-06-08 05:19:40 -05:00
|
|
|
auto iclusterSegment = clusterSegments.find( segment );
|
|
|
|
if (iclusterSegment != clusterSegments.end()) {
|
|
|
|
size_t neighbor = (*iclusterSegment).second;
|
|
|
|
cdebug_log(147,0) << "| " << segment << " belongs to [" << neighbor << "]" << endl;
|
|
|
|
if (neighbor < rpClustersSize)
|
|
|
|
cluster->addNeighbor( neighbor );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
|
2021-05-22 08:14:32 -05:00
|
|
|
cluster->merge( segment );
|
|
|
|
uint32_t flags = (segment->getSourceHook() == hook) ? DiodeCluster::IsSegSource : 0;
|
|
|
|
if (dynamic_cast<Segment::SourceHook*>(hook)) {
|
|
|
|
hooksStack.push_back( make_tuple( segment->getTargetHook(), segment, stackTop, flags ) );
|
|
|
|
} else {
|
|
|
|
hooksStack.push_back( make_tuple( segment->getSourceHook(), segment, stackTop, flags ) );
|
|
|
|
}
|
2021-05-11 07:30:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++stackTop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
total += clusters.size();
|
|
|
|
cdebug_log(147,1) << "Net \"" << net->getName() << " has " << clusters.size() << " diode clusters." << endl;
|
2021-06-08 05:19:40 -05:00
|
|
|
size_t i = clusters.size()-1;
|
|
|
|
while ( true ) {
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,1) << "Cluster [" << i << "] needsDiode=" << clusters[i]->needsDiode()
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
<< " bb=" << clusters[i]->getBoundingBox() << endl;
|
2021-05-11 07:30:38 -05:00
|
|
|
cdebug_log(147,0) << " WL=" << DbU::getValueString(clusters[i]->getWL()) << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
for ( auto& item : clusters[i]->getRoutingPads() ) {
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_log(147,0) << "| flags=" << DiodeCluster::toStr(std::get<1>(item))
|
|
|
|
<< " " << std::get<0>(item) << endl;
|
|
|
|
}
|
2021-06-08 05:19:40 -05:00
|
|
|
|
|
|
|
if (clusters[i]->needsDiode()) {
|
|
|
|
const vector<Instance*>& diodes = clusters[i]->createDiodes( etesian->getArea() );
|
|
|
|
if (not diodes.empty()) {
|
|
|
|
clusters[i]->connectDiodes();
|
|
|
|
} else {
|
|
|
|
cerr << Error( "EtesianEngine::antennaProtect(): For %s (rps:%u, clusters:%u)\n"
|
|
|
|
" Cannot find a diode nearby %s."
|
|
|
|
, getString(net).c_str()
|
|
|
|
, rpsDone.size()
|
|
|
|
, clusters.size()
|
|
|
|
, getString(clusters[i]->getRefRp()).c_str()
|
|
|
|
) << endl;
|
|
|
|
failed += 1;
|
|
|
|
for ( size_t icluster : clusters[i]->getNeighbors() ) {
|
|
|
|
clusters[icluster]->addForcedDiodes( 1 );
|
|
|
|
}
|
|
|
|
}
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
2021-06-08 05:19:40 -05:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
cdebug_tabw(147,-1);
|
2021-06-08 05:19:40 -05:00
|
|
|
if (i == 0) break;
|
|
|
|
--i;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
}
|
2021-05-11 07:30:38 -05:00
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
}
|
|
|
|
|
2021-05-11 07:30:38 -05:00
|
|
|
if ((rpsDone.size() == 2) and (clusters.size() == 2)) {
|
|
|
|
cerr << "Long bipoint " << net << endl;
|
|
|
|
}
|
|
|
|
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
for ( DiodeCluster* cluster : clusters ) delete cluster;
|
|
|
|
|
|
|
|
cdebug_tabw(147,-1);
|
|
|
|
DebugSession::close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AnabaticEngine::antennaProtect ()
|
|
|
|
{
|
|
|
|
//DebugSession::open( 145, 150 );
|
|
|
|
|
|
|
|
if (not ToolEngine::get( getCell(), EtesianEngine::staticGetName() )) {
|
|
|
|
cerr << Warning( "AnabaticEngine::antennaProtect(): No EtesianEngine found, skipped." ) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
EtesianEngine* etesian = static_cast<EtesianEngine*>
|
|
|
|
( ToolEngine::get( getCell(), EtesianEngine::staticGetName() ));
|
|
|
|
|
|
|
|
if (not etesian->getDiodeCell()) {
|
|
|
|
cerr << Warning( "AnabaticEngine::antennaProtect(): No diode cell found, skipped." ) << endl;
|
|
|
|
return;
|
|
|
|
}
|
2021-09-30 12:59:28 -05:00
|
|
|
if (etesian->getAntennaDiodeMaxWL() <= 0) {
|
|
|
|
cerr << Warning( "AnabaticEngine::antennaProtect(): Maximum antenna diode WL not set, skipped." ) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DbU::Unit segmentMaxWL = etesian->getAntennaDiodeMaxWL() / 2;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
|
2021-05-04 12:31:12 -05:00
|
|
|
cmess1 << " o Antenna effect protection." << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
startMeasures();
|
|
|
|
openSession();
|
|
|
|
|
|
|
|
uint32_t failed = 0;
|
|
|
|
uint32_t total = 0;
|
|
|
|
for ( Net* net : getCell()->getNets() ) {
|
|
|
|
if (net->isSupply()) continue;
|
More generic H-Tree support to accomodate the LS180 PLL internal clock.
The H-Tree support is now allowed for any net, not only the clocks and
not only top-level nets. This allow to better management of the LS180
internal clock signal.
* New: In Cell::flattenNets(Instance*,set<string>,uint64_t) new overload
of the function to allow the user to select nets that will *not*
be flattened. This makes the NoClockFlatten flag effectively obsolete,
we keep it for backward compatibility.
The net names can be of non top level ones. In that case, they must
use the name an HyperNet will get (the Occurrence name). For example:
"instance1.instance2.deep_net_name".
* New: In PyCell, update the wrapper for the new parameter of flattenNets(),
new utility function pyListToStringSet() to translate a Python list into
a C++ set of names.
* New: In EtesianEngine, add support for a list of nets to be excluded
from the flattening procedure. Those excluded nets will also be
excludeds from the Coloquinte nets *and* HFNS synthesis, as they
are likely to be manageds by a H-Tree.
* Change: In AnabaticEngine::_loadGrByNet(), now also skip nets that are
flagged as manually detailed route.
* New: In AnabaticEngine::antennaProtect(), do not try to insert diodes
on nets that are already fixed or detaled route. This replace the
clock exclusion.
* New: In cumulus/plugins.{block,htree,chip}, replace the concept
of clock-tree by the more generic H-Tree. That is, we can ask the P&R
to create H-Tree on any net of the design, not only the ones matcheds
as clock. The net does not even need to be top-level.
This is to manage the PLL internal clock generated by the PLL in
the LS180 chip.
Start to change all reference to "clock" into "H-Tree".
* Bug: In cumulus/plugins.chip.powerplanes.Builder._connectHTree(),
there was an inversion of the H & V routing gauges to compute the
track into which put the H-Tree center to corona edge wiring.
This was causing tracks to be used twice, seen in the ao68000 test
bench.
2021-05-30 17:02:23 -05:00
|
|
|
if ( NetRoutingExtension::isManualDetailRoute(net)
|
|
|
|
or NetRoutingExtension::isFixed(net))
|
|
|
|
continue;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
antennaProtect( net, failed, total );
|
|
|
|
}
|
2021-05-22 08:14:32 -05:00
|
|
|
cmess2 << Dots::asString ( " - Antenna gate maximum WL" , DbU::getValueString(etesian->getAntennaGateMaxWL()) ) << endl;
|
|
|
|
cmess2 << Dots::asString ( " - Antenna diode maximum WL" , DbU::getValueString(etesian->getAntennaDiodeMaxWL()) ) << endl;
|
|
|
|
cmess2 << Dots::asString ( " - Antenna segment maximum WL", DbU::getValueString(segmentMaxWL) ) << endl;
|
Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
antennaProtect(). First reason is that, after all, Coloquinte
do not handle so well the resizing of the cells "on the fly",
it overspill the boundaries sometimes. Second reason is that
as we cannot know the routing tree at this stage, we will not
be able to choose the correct points for diode insertions.
We only have a Steiner tree wich may not be the same as a
density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
not stored in a uniform way. Some where starting from the
placed sub-block, some where starting from the top level
(corona), making their processing (and remembering it) tricky.
Now, they are all expressed from the top cell (corona).
The coordinate system is now systematically the one of the
top block (*not* the block).
Create various overloaded functions EtesianEngine::toCell()
and EtesianEngine::toBlock() to ease Occurrence & coordinate
translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
Search is done by going through the whole slice range and
minimizing the distance to the hint. If it starts to be too
slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
level external pins was not taken into account (this at last
explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
antenna effect. This step must be done *after* global routing
and *before* detailed routing. This way we have access to the
real routing and can mend it (along with the netlist) to
insert diodes at the rigth points.
From the global routing we build clusters (DiodeCluster) of
RoutingPads connected through a set of wire whose total length
is below the antenna effect threshold. Long wires connecting the
clusters are also tagged because we need to put a diode between
them and the first RoutingPad of the cluster. This is to avoid
a long METAL2 wire connecting to the RoutingPad before the diode is
connected through METAL3 (in case of misalignment).
This protection is not even enough. For *very long* wires, we
needs to put *more* than one diode (this is to be implemented).
2021-01-27 04:38:00 -06:00
|
|
|
cmess2 << Dots::asInt ( " - Total needed diodes", total ) << endl;
|
|
|
|
cmess2 << Dots::asInt ( " - Failed to allocate" , failed ) << endl;
|
|
|
|
cmess2 << Dots::asPercentage( " - Success ratio" , (float)(total-failed)/(float)total ) << endl;
|
|
|
|
|
|
|
|
stopMeasures();
|
|
|
|
printMeasures( "antennas" );
|
|
|
|
|
|
|
|
Session::close();
|
|
|
|
//DebugSession::close();
|
|
|
|
Breakpoint::stop( 99, "After diodes insertions." );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Anabatic namespace.
|