276 lines
7.7 KiB
C++
276 lines
7.7 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@asim.lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./RoutingEventQueue.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include "hurricane/Bug.h"
|
|
#include "kite/DataNegociate.h"
|
|
#include "kite/TrackSegment.h"
|
|
#include "kite/RoutingEventQueue.h"
|
|
#include "kite/Session.h"
|
|
|
|
|
|
namespace Kite {
|
|
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::setw;
|
|
using std::max;
|
|
using std::make_heap;
|
|
using std::push_heap;
|
|
using std::pop_heap;
|
|
|
|
using Hurricane::tab;
|
|
using Hurricane::Bug;
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "RoutingEventQueue".
|
|
|
|
|
|
RoutingEventQueue::RoutingEventQueue ()
|
|
: _topEventLevel (0)
|
|
, _pushRequests ()
|
|
, _events ()
|
|
{ }
|
|
|
|
|
|
RoutingEventQueue::~RoutingEventQueue ()
|
|
{ clear (); }
|
|
|
|
|
|
void RoutingEventQueue::load ( const vector<TrackElement*>& segments )
|
|
{
|
|
for ( size_t i=0 ; i<segments.size() ; i++ ) {
|
|
if (segments[i]->getDataNegociate()->getRoutingEvent()) {
|
|
cinfo << "[INFO] Already have a RoutingEvent - " << segments[i] << endl;
|
|
continue;
|
|
}
|
|
if (segments[i]->getTrack()) {
|
|
cinfo << "[INFO] Already in Track - " << segments[i] << endl;
|
|
continue;
|
|
}
|
|
RoutingEvent* event = RoutingEvent::create(segments[i]);
|
|
event->updateKey();
|
|
_events.insert( event );
|
|
}
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::add ( TrackElement* segment, unsigned int level )
|
|
{
|
|
if (segment->getTrack()) {
|
|
cinfo << "[INFO] Already in Track " << (void*)segment->base()->base()
|
|
<< ":" << segment << endl;
|
|
return;
|
|
}
|
|
|
|
RoutingEvent* event = RoutingEvent::create(segment);
|
|
event->setEventLevel( level );
|
|
push( event );
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::commit ()
|
|
{
|
|
cdebug_log(159,1) << "RoutingEventQueue::commit()" << endl;
|
|
|
|
size_t addeds = _pushRequests.size();
|
|
size_t before = _events.size();
|
|
|
|
RoutingEventSet::iterator ipushEvent = _pushRequests.begin();
|
|
for ( ; ipushEvent != _pushRequests.end() ; ipushEvent++ ) {
|
|
(*ipushEvent)->updateKey();
|
|
|
|
_topEventLevel = max( _topEventLevel, (*ipushEvent)->getEventLevel() );
|
|
_events.insert( (*ipushEvent) );
|
|
|
|
cdebug_log(159,0) << "| " << (*ipushEvent) << endl;
|
|
}
|
|
_pushRequests.clear();
|
|
#if defined(CHECK_ROUTINGEVENT_QUEUE)
|
|
_keyCheck();
|
|
#endif
|
|
size_t after = _events.size();
|
|
if (after-before != addeds) {
|
|
cerr << Bug( "RoutingEventQueue::commit(): less than %d events pusheds (%d)."
|
|
, addeds,(after-before) ) << endl;
|
|
}
|
|
|
|
cdebug_tabw(159,-1);
|
|
}
|
|
|
|
|
|
RoutingEvent* RoutingEventQueue::pop ()
|
|
{
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::iterator ievent;
|
|
RoutingEvent* event = NULL;
|
|
|
|
#if defined(CHECK_ROUTINGEVENT_QUEUE)
|
|
_keyCheck ();
|
|
#endif
|
|
|
|
if (not _events.empty()) {
|
|
size_t beforeSize = _events.size();
|
|
|
|
ievent = _events.end();
|
|
ievent--;
|
|
event = (*ievent);
|
|
_events.erase( ievent );
|
|
|
|
size_t afterSize = _events.size();
|
|
|
|
if (afterSize+1 != beforeSize) {
|
|
cerr << Bug( "RoutingEventQueue::pop(): more than one event popped: %d."
|
|
, (beforeSize-afterSize) ) << endl;
|
|
}
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::repush ( RoutingEvent* event )
|
|
{
|
|
#if defined(CHECK_ROUTINGEVENT_QUEUE)
|
|
_keyCheck ();
|
|
#endif
|
|
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::iterator ievent = _events.find(event);
|
|
size_t count = _events.count(event);
|
|
if (count > 1) {
|
|
cerr << Bug("RoutingEventQueue::repush(): %d events matches key %p.",count,event) << endl;
|
|
#if defined(CHECK_ROUTINGEVENT_QUEUE)
|
|
_keyCheck ();
|
|
#endif
|
|
}
|
|
|
|
if (ievent != _events.end()) {
|
|
_events.erase( ievent );
|
|
}
|
|
push ( event );
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::repushInvalidateds ()
|
|
{
|
|
const vector<AutoSegment*>& invalidateds0 = Session::getInvalidateds();
|
|
TrackSegmentSet invalidateds1;
|
|
for ( size_t i=0 ; i<invalidateds0.size() ; i++ ) {
|
|
TrackSegment* segment = dynamic_cast<TrackSegment*>( Session::lookup(invalidateds0[i]) );
|
|
if (segment)
|
|
invalidateds1.insert( segment );
|
|
}
|
|
|
|
TrackSegmentSet::iterator isegment = invalidateds1.begin();
|
|
for ( ; isegment != invalidateds1.end() ; isegment++ ) {
|
|
RoutingEvent* event = (*isegment)->getDataNegociate()->getRoutingEvent();
|
|
if ( event
|
|
and not event->isUnimplemented()
|
|
and not event->isDisabled ()
|
|
and not event->isProcessed () ) {
|
|
repush( event );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::prepareRepair ()
|
|
{
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::const_iterator ievent = _events.begin ();
|
|
for ( ; ievent != _events.end(); ++ievent ) {
|
|
(*ievent)->getSegment()->base()->toOptimalAxis();
|
|
}
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::clear ()
|
|
{
|
|
if (not _events.empty()) {
|
|
cerr << Bug("RoutingEvent queue is not empty, %d events remains."
|
|
,_events.size()) << endl;
|
|
}
|
|
_events.clear();
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::dump () const
|
|
{
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::const_iterator ievent = _events.begin ();
|
|
for ( ; ievent != _events.end(); ievent++ ) {
|
|
cerr << "Deter| Queue:"
|
|
<< (*ievent)->getEventLevel()
|
|
<< "," << setw(6) << (*ievent)->getPriority()
|
|
<< " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getLength())
|
|
<< " " << (*ievent)->getSegment()->isHorizontal()
|
|
<< " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getAxis())
|
|
<< " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getSourceU())
|
|
<< ": " << (*ievent)->getSegment() << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void RoutingEventQueue::_keyCheck () const
|
|
{
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::const_iterator ievent = _events.begin ();
|
|
for ( ; ievent != _events.end(); ievent++ ) {
|
|
multiset<RoutingEvent*,RoutingEvent::Compare>::const_iterator ieventByKey
|
|
= _events.find ( *ievent );
|
|
|
|
if ( ieventByKey != ievent ) {
|
|
if ( ieventByKey == _events.end() ) {
|
|
cerr << Bug("Key mismatch in RoutingEvent Queue:\n"
|
|
" %p:%s wasn't found by key."
|
|
,*ievent,getString(*ievent).c_str()
|
|
) << endl;
|
|
} else {
|
|
cerr << Bug("Key mismatch in RoutingEvent Queue:\n"
|
|
" %p:%s has same key of\n"
|
|
" %p:%s"
|
|
,*ievent,getString(*ievent).c_str()
|
|
,*ieventByKey,getString(*ieventByKey).c_str()
|
|
) << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
string RoutingEventQueue::_getString () const
|
|
{
|
|
string s = "<" + _getTypeName();
|
|
|
|
s += ":" + getString(size());
|
|
s += ">";
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
Record* RoutingEventQueue::_getRecord () const
|
|
{
|
|
Record* record = new Record ( getString(this) );
|
|
record->add ( getSlot ( "_events", &_events ) );
|
|
|
|
return record;
|
|
}
|
|
|
|
|
|
} // Kite namespace.
|