coriolis/katana/src/DataSymmetric.cpp

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.