279 lines
9.5 KiB
C++
279 lines
9.5 KiB
C++
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
|
//
|
|
// +-----------------------------------------------------------------+
|
|
// | C O R I O L I S |
|
|
// | K i t e - D e t a i l e d R o u t e r |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./DataSymmetric.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
#include "anabatic/AutoSegment.h"
|
|
#include "katana/DataSymmetric.h"
|
|
#include "katana/Session.h"
|
|
|
|
|
|
namespace {
|
|
|
|
using namespace std;
|
|
|
|
|
|
class Message {
|
|
public:
|
|
inline Message ( size_t, string header="" );
|
|
inline size_t size () const;
|
|
inline ostringstream& newline ();
|
|
inline ostringstream& line ();
|
|
inline void setHeader ( string );
|
|
void print ( ostream& );
|
|
private:
|
|
size_t _indent;
|
|
string _header;
|
|
vector<string> _lines;
|
|
ostringstream _current;
|
|
};
|
|
|
|
|
|
inline Message::Message ( size_t indent, string header )
|
|
: _indent (indent)
|
|
, _header (header)
|
|
, _lines ()
|
|
, _current()
|
|
{ }
|
|
|
|
inline size_t Message::size () const { return _lines.size(); }
|
|
inline void Message::setHeader ( string header ) { _header = header; }
|
|
inline ostringstream& Message::line () { return _current; }
|
|
|
|
inline ostringstream& Message::newline ()
|
|
{
|
|
if (_current.str().size())
|
|
_lines.push_back(_current.str());
|
|
_current.str("");
|
|
return _current;
|
|
}
|
|
|
|
void Message::print ( ostream& o )
|
|
{
|
|
if (not _header.empty()) _indent = _header.size()+1;
|
|
|
|
string head ( _indent, ' ' );
|
|
for ( size_t i=0 ; i<_lines.size() ; ++i ) {
|
|
if ((i == 0) and not _header.empty()) o << _header << " ";
|
|
else o << head;
|
|
o << _lines[i] << endl;
|
|
}
|
|
}
|
|
|
|
|
|
} // Anonymous namespace.
|
|
|
|
|
|
namespace Katana {
|
|
|
|
using namespace std;
|
|
using Anabatic::AutoSegment;
|
|
|
|
|
|
DataSymmetric* DataSymmetric::create ( Net* net )
|
|
{
|
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
|
|
|
if (not state or not state->isSymmetric()) return NULL;
|
|
if (state->getSymNet() and not state->isSymMaster()) return NULL;
|
|
|
|
return new DataSymmetric ( net );
|
|
}
|
|
|
|
|
|
DataSymmetric::DataSymmetric ( Net* net )
|
|
: _valid (true)
|
|
, _net (net)
|
|
, _symNet (NULL)
|
|
, _state (NetRoutingExtension::get(_net))
|
|
, _paireds ()
|
|
, _symIndex(0)
|
|
{
|
|
_symNet = _state->getSymNet();
|
|
}
|
|
|
|
|
|
void DataSymmetric::addSymmetrical ( AutoSegment* symmetrical )
|
|
{
|
|
if (_paireds.size() > _symIndex) _paireds[_symIndex++][1] = symmetrical;
|
|
else _paireds.push_back( {{ NULL, symmetrical }} );
|
|
}
|
|
|
|
|
|
AutoSegment* DataSymmetric::getSymmetrical ( AutoSegment* segment ) const
|
|
{
|
|
for ( const array<AutoSegment*,2>& paired : _paireds ) {
|
|
if (segment == paired[0]) return paired[1];
|
|
if (segment == paired[1]) return paired[0];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool DataSymmetric::checkPairing ()
|
|
{
|
|
const uint64_t mask = ~(AutoSegment::SegIsReduced);
|
|
Message errors ( 0, "[ERROR]" );
|
|
|
|
// Temporary hardwired: M2 (depth 1) for H pitch, M3 (depth 2) for V pitch.
|
|
DbU::Unit hPitch = Session::getPitch( 1 );
|
|
DbU::Unit vPitch = Session::getPitch( 2 );
|
|
|
|
size_t refs = 0;
|
|
size_t syms = 0;
|
|
for ( const array<AutoSegment*,2>& paired : _paireds ) {
|
|
refs += (paired[0]) ? 1 : 0;
|
|
syms += (paired[1]) ? 1 : 0;
|
|
}
|
|
if (refs != syms) {
|
|
errors.newline() << "Segments symmetric sets size mismatch, reference:" << refs
|
|
<< " symmetricals:" << syms << ".";
|
|
_valid = false;
|
|
} else {
|
|
size_t index = 0;
|
|
for ( const array<AutoSegment*,2>& paired : _paireds ) {
|
|
if (paired[0]->isHorizontal() xor paired[1]->isHorizontal()) {
|
|
errors.newline() << "Direction mismatch @ [" << index << "]";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
_valid = false;
|
|
}
|
|
|
|
if (paired[0]->getLayer() != paired[1]->getLayer()) {
|
|
errors.newline() << "Layer mismatch @ [" << index << "]";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
_valid = false;
|
|
}
|
|
|
|
if (_state->isSymVertical()) {
|
|
if (paired[0]->isVertical()) {
|
|
if ( (paired[0]->getFlags() ^ paired[1]->getFlags()) & mask ) {
|
|
errors.newline() << "Flags mismatch at index " << index
|
|
<< " " << paired[0]->getFlags()
|
|
<< " vs. " << paired[1]->getFlags();
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
_valid = false;
|
|
}
|
|
|
|
if (std::abs( 2*getSymAxis() - paired[0]->getAxis() - paired[1]->getAxis() ) > 5*vPitch ) {
|
|
errors.newline() << "Mirror axis mismatch @ [" << index << "] "
|
|
<< DbU::getValueString(paired[1]->getAxis()) << " (should be: "
|
|
<< DbU::getValueString(2*getSymAxis() - paired[0]->getAxis()) << ")";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
errors.newline() << "| Tolerance (5*vPitch): " << DbU::getValueString(5*vPitch);
|
|
_valid = false;
|
|
}
|
|
} else {
|
|
if ( (paired[0]->getFlags() ^ AutoSegment::swapSourceTargetFlags(paired[1])) & mask ) {
|
|
errors.newline() << "Flags mismatch at index " << index
|
|
<< " " << paired[0]->getFlags()
|
|
<< " vs. " << paired[1]->getFlags()
|
|
<< " swp " << AutoSegment::swapSourceTargetFlags(paired[1]);
|
|
_valid = false;
|
|
}
|
|
|
|
if ( std::abs( paired[0]->getAxis() - paired[1]->getAxis() ) > 5*hPitch ) {
|
|
errors.newline() << "Axis mismatch index " << index << " "
|
|
<< DbU::getValueString(paired[1]->getAxis()) << " (should be:"
|
|
<< DbU::getValueString(paired[0]->getAxis()) << ")";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
errors.newline() << "| Tolerance (5*hPitch): " << DbU::getValueString(5*hPitch);
|
|
_valid = false;
|
|
}
|
|
}
|
|
} else {
|
|
if (paired[0]->isHorizontal()) {
|
|
if ( std::abs( 2*getSymAxis() - paired[0]->getAxis() - paired[1]->getAxis() ) > 5*hPitch ) {
|
|
errors.newline() << "Mirror axis mismatch index " << index << " "
|
|
<< DbU::getValueString(paired[1]->getAxis()) << " (should be:"
|
|
<< DbU::getValueString(2*getSymAxis() - paired[0]->getAxis()) << ")";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
errors.newline() << "| Tolerance (5*hPitch): " << DbU::getValueString(5*hPitch);
|
|
_valid = false;
|
|
}
|
|
} else {
|
|
if ( std::abs( paired[0]->getAxis() != paired[1]->getAxis() ) > 5*vPitch ) {
|
|
errors.newline() << "Axis mismatch index " << index << " "
|
|
<< DbU::getValueString(paired[1]->getAxis()) << " (should be:"
|
|
<< DbU::getValueString(paired[0]->getAxis()) << ")";
|
|
errors.newline() << "| " << paired[0];
|
|
errors.newline() << "| " << paired[1];
|
|
errors.newline() << "| Tolerance (5*vPitch): " << DbU::getValueString(5*vPitch);
|
|
_valid = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
++index;
|
|
}
|
|
}
|
|
|
|
|
|
errors.newline();
|
|
if (errors.size()) {
|
|
//cmess2 << " pairing failed." << endl;
|
|
errors.print( cmess2 );
|
|
} else {
|
|
//cmess2 << " paired." << endl;
|
|
}
|
|
|
|
return _valid;
|
|
}
|
|
|
|
|
|
void DataSymmetric::print ( ostream& o ) const
|
|
{
|
|
Message lines ( 0 );
|
|
|
|
lines.newline() << "Paired components of Net \"" << _net->getName() << "\"";
|
|
if (_symNet) lines.line() << " (symmetrical:\"" << _symNet->getName() << "\")";
|
|
|
|
size_t index = 0;
|
|
for ( const array<AutoSegment*,2>& paired : _paireds ) {
|
|
lines.newline() << "| " << setw(2) << index << " " << paired[0];
|
|
lines.newline() << "+ " << setw(2) << index << " " << paired[1];
|
|
++index;
|
|
}
|
|
|
|
lines.newline();
|
|
lines.print( o );
|
|
}
|
|
|
|
|
|
string DataSymmetric::_getString () const
|
|
{
|
|
return "<DataSymmetric " + getString(_net->getName()) + ">";
|
|
}
|
|
|
|
|
|
Record* DataSymmetric::_getRecord () const
|
|
{
|
|
Record* record = new Record ( getString(this) );
|
|
record->add( getSlot( "_valid" , _valid ) );
|
|
record->add( getSlot( "_net" , _net ) );
|
|
record->add( getSlot( "_symNet" , _symNet ) );
|
|
record->add( getSlot( "_state" , _state ) );
|
|
record->add( getSlot( "_paireds" , &_paireds ) );
|
|
record->add( getSlot( "_symIndex" , &_symIndex ) );
|
|
|
|
return record;
|
|
}
|
|
|
|
|
|
} // Katana namespace.
|