Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel
Conflicts: oroshi/python/CapacitorRoutedSingle.py Hidden tabulations remaining
This commit is contained in:
commit
e2d6929fbe
|
@ -25,7 +25,7 @@ Documentation
|
|||
|
||||
The complete documentation is available here, both in pdf & html:
|
||||
|
||||
./documentation/_build/html/index.html
|
||||
./documentation/output/html
|
||||
./documentation/UsersGuide/UsersGuide.pdf
|
||||
|
||||
The documentation of the latest *stable* version is also
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/RegularLayer.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "hurricane/Pin.h"
|
||||
#include "hurricane/NetExternalComponents.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
|
@ -55,6 +56,7 @@ namespace Anabatic {
|
|||
using Hurricane::BasicLayer;
|
||||
using Hurricane::RegularLayer;
|
||||
using Hurricane::Segment;
|
||||
using Hurricane::Pin;
|
||||
using Hurricane::Plug;
|
||||
using Hurricane::Path;
|
||||
using Hurricane::Occurrence;
|
||||
|
@ -458,13 +460,18 @@ namespace Anabatic {
|
|||
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
|
||||
for ( Component* component : masterNet->getComponents() ) {
|
||||
cdebug_log(112,0) << "@ " << component << endl;
|
||||
if (not NetExternalComponents::isExternal(component)) continue;
|
||||
if (not NetExternalComponents::isExternal(component)) {
|
||||
cdebug_log(112,0) << " Not an external component, skip." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
Segment* segment = dynamic_cast<Segment*>(component);
|
||||
if (not segment) continue;
|
||||
if (segment->getLayer()->getMask() != metal1->getMask()) continue;
|
||||
Component* candidate = dynamic_cast<Segment*>(component);
|
||||
if (not candidate
|
||||
or (candidate->getLayer()->getMask() != metal1->getMask()) )
|
||||
candidate = dynamic_cast<Pin*>(component);
|
||||
if (not candidate) continue;
|
||||
|
||||
Box bb = transformation.getBox( component->getBoundingBox() );
|
||||
Box bb = transformation.getBox( candidate->getBoundingBox() );
|
||||
DbU::Unit trackPos = 0;
|
||||
DbU::Unit minPos = DbU::Max;
|
||||
DbU::Unit maxPos = DbU::Min;
|
||||
|
@ -497,7 +504,7 @@ namespace Anabatic {
|
|||
|
||||
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
|
||||
cdebug_log(112,0) << "| " << transformation << endl;
|
||||
cdebug_log(112,0) << "| " << bb << " of:" << segment << endl;
|
||||
cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl;
|
||||
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
|
||||
|
||||
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
|
||||
|
|
|
@ -401,14 +401,14 @@ namespace Anabatic {
|
|||
for ( Hook* hook : fromHook->getHooks() ) {
|
||||
cdebug_log(145,0) << "Hook: " << hook << endl;
|
||||
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
|
||||
<< "[" << (int)_connexity.fields.globals
|
||||
<< "+" << (int)_connexity.fields.M1
|
||||
<< "+" << (int)_connexity.fields.M2
|
||||
<< "+" << (int)_connexity.fields.M3
|
||||
<< "+" << (int)_connexity.fields.Pin
|
||||
<< "+" << (int)_connexity.fields.Pad
|
||||
<< "] " << _gcell
|
||||
<< endl;
|
||||
<< "[" << (int)_connexity.fields.globals
|
||||
<< "+" << (int)_connexity.fields.M1
|
||||
<< "+" << (int)_connexity.fields.M2
|
||||
<< "+" << (int)_connexity.fields.M3
|
||||
<< "+" << (int)_connexity.fields.Pin
|
||||
<< "+" << (int)_connexity.fields.Pad
|
||||
<< "] " << _gcell
|
||||
<< endl;
|
||||
|
||||
Segment* toSegment = dynamic_cast<Segment*>( hook->getComponent() );
|
||||
if (toSegment) {
|
||||
|
@ -507,6 +507,16 @@ namespace Anabatic {
|
|||
|
||||
if (_gcell == NULL) throw Error( missingGCell );
|
||||
|
||||
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
|
||||
<< "[" << (int)_connexity.fields.globals
|
||||
<< "+" << (int)_connexity.fields.M1
|
||||
<< "+" << (int)_connexity.fields.M2
|
||||
<< "+" << (int)_connexity.fields.M3
|
||||
<< "+" << (int)_connexity.fields.Pin
|
||||
<< "+" << (int)_connexity.fields.Pad
|
||||
<< "] " << _gcell
|
||||
<< endl;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -543,6 +553,15 @@ namespace Anabatic {
|
|||
void NetBuilder::construct ()
|
||||
{
|
||||
cdebug_log(145,1) << "NetBuilder::construct() [" << _connexity.connexity << "] in " << _gcell << endl;
|
||||
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
|
||||
<< "[" << (int)_connexity.fields.globals
|
||||
<< "+" << (int)_connexity.fields.M1
|
||||
<< "+" << (int)_connexity.fields.M2
|
||||
<< "+" << (int)_connexity.fields.M3
|
||||
<< "+" << (int)_connexity.fields.Pin
|
||||
<< "+" << (int)_connexity.fields.Pad
|
||||
<< "] " << _gcell
|
||||
<< endl;
|
||||
|
||||
if (not isTwoMetals()) {
|
||||
_southWestContact = NULL;
|
||||
|
@ -586,6 +605,7 @@ namespace Anabatic {
|
|||
case Conn_3G_2M1:
|
||||
case Conn_3G_3M1:
|
||||
case Conn_3G_4M1:
|
||||
case Conn_3G_5M1:
|
||||
case Conn_3G_2M3:
|
||||
case Conn_3G_3M3:
|
||||
case Conn_3G_4M3:
|
||||
|
@ -616,17 +636,22 @@ namespace Anabatic {
|
|||
case Conn_4G: _do_xG(); break;
|
||||
// End xG cascaded cases.
|
||||
// Optimized specific cases.
|
||||
case Conn_1G_1PinM1: _do_1G_1PinM1 (); break;
|
||||
case Conn_2G_1PinM1: _do_2G_1PinM1 (); break;
|
||||
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break;
|
||||
case Conn_2G_1PinM2:
|
||||
case Conn_3G_1PinM2: _do_xG_1PinM2 (); break;
|
||||
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
|
||||
case Conn_2G_1PinM3:
|
||||
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
|
||||
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2(); break;
|
||||
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break;
|
||||
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2(); break;
|
||||
case Conn_1G_1PinM1: _do_1G_1PinM1 (); break;
|
||||
case Conn_2G_1PinM1: _do_2G_1PinM1 (); break;
|
||||
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break;
|
||||
case Conn_2G_1PinM2:
|
||||
case Conn_3G_1PinM2: _do_xG_1PinM2 (); break;
|
||||
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
|
||||
case Conn_2G_1PinM3:
|
||||
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
|
||||
case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
|
||||
case Conn_1G_1M1_1PinM2:
|
||||
case Conn_1G_2M1_1PinM2: _do_1G_xM1_1PinM2(); break;
|
||||
case Conn_2G_1M1_1PinM2:
|
||||
case Conn_2G_2M1_1PinM2: _do_2G_xM1_1PinM2(); break;
|
||||
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2 (); break;
|
||||
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break;
|
||||
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2 (); break;
|
||||
default:
|
||||
if (not isTwoMetals())
|
||||
throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n"
|
||||
|
@ -1068,7 +1093,28 @@ namespace Anabatic {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilder::_do_1G_1M1_1PinM3 ()
|
||||
{
|
||||
throw Error ( "%s::_do_1G_1M1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilder::_do_1G_xM1_1PinM2 ()
|
||||
{
|
||||
throw Error ( "%s::_do_1G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilder::_do_2G_xM1_1PinM2 ()
|
||||
{
|
||||
throw Error ( "%s::_do_2G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilder::_do_globalSegment ()
|
||||
{
|
||||
throw Error ( "%s::_do_globalSegment() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||
|
|
|
@ -251,6 +251,45 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
AutoContact* NetBuilderHV::doRp_AccessNorthPin ( GCell* gcell, RoutingPad* rp )
|
||||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
|
||||
|
||||
AutoContact* rpSourceContact = NULL;
|
||||
AutoContact* rpContactTarget = NULL;
|
||||
AutoContact* turn = NULL;
|
||||
|
||||
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
|
||||
|
||||
Net* net = rp->getNet();
|
||||
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
|
||||
Pin::AccessDirection pinDir = pin->getAccessDirection();
|
||||
if (pinDir == Pin::AccessDirection::NORTH) {
|
||||
turn = AutoContactTurn::create( gcell, net, Session::getRoutingLayer(1) );
|
||||
AutoSegment* segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
|
||||
segment->setAxis( rp->getX(), Flags::Force );
|
||||
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
|
||||
rpSourceContact = turn;
|
||||
|
||||
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
|
||||
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
|
||||
rpSourceContact = turn;
|
||||
|
||||
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
|
||||
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
|
||||
|
||||
segment->setAxis( axis, Flags::Force );
|
||||
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
|
||||
cdebug_log(145,0) << segment << endl;
|
||||
} else {
|
||||
turn = rpSourceContact;
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return turn;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilderHV::_do_1G_1M1 ()
|
||||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
@ -744,9 +783,8 @@ namespace Anabatic {
|
|||
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
||||
AutoContact* rpSourceContact = NULL;
|
||||
AutoContact* rpContactTarget = NULL;
|
||||
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
|
||||
rpSourceContact = doRp_AccessNorthPin( getGCell(), getRoutingPads()[0] );
|
||||
|
||||
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
|
||||
|
@ -804,15 +842,19 @@ namespace Anabatic {
|
|||
|
||||
setSouthWestContact( turn1 );
|
||||
setNorthEastContact( htee1 );
|
||||
} else {
|
||||
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, vtee1, Flags::Vertical );
|
||||
|
||||
} else if (north() and south()) {
|
||||
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( vtee1, turn1, Flags::Vertical );
|
||||
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
|
||||
|
||||
setSouthWestContact( vtee1 );
|
||||
setNorthEastContact( turn1 );
|
||||
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( turn1, vtee1, Flags::Horizontal );
|
||||
|
||||
setBothCornerContacts( vtee1 );
|
||||
} else { // Remaining case is East & West.
|
||||
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
|
||||
|
||||
setBothCornerContacts( htee1 );
|
||||
}
|
||||
} else {
|
||||
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
@ -830,6 +872,144 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
bool NetBuilderHV::_do_1G_xM1_1PinM2 ()
|
||||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
||||
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
|
||||
|
||||
vector<RoutingPad*> rpsM1;
|
||||
RoutingPad* pinM2 = NULL;
|
||||
for ( RoutingPad* rp : getRoutingPads() ) {
|
||||
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
|
||||
else rpsM1.push_back( rp );
|
||||
}
|
||||
|
||||
AutoContact* turn = NULL;
|
||||
AutoContact* tee = NULL;
|
||||
AutoContact* pinM2Contact = NULL;
|
||||
AutoContact* rpM1Contact = NULL;
|
||||
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoProtect );
|
||||
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], HAccess );
|
||||
|
||||
if (north() or south()) {
|
||||
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( rpM1Contact , tee , Flags::Horizontal );
|
||||
AutoSegment::create( pinM2Contact, turn, Flags::Horizontal );
|
||||
AutoSegment::create( tee , turn, Flags::Vertical );
|
||||
} else {
|
||||
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( rpM1Contact , turn, Flags::Horizontal );
|
||||
AutoSegment::create( pinM2Contact, tee , Flags::Horizontal );
|
||||
AutoSegment::create( tee , turn, Flags::Vertical );
|
||||
}
|
||||
setBothCornerContacts( tee );
|
||||
|
||||
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
|
||||
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
|
||||
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
|
||||
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilderHV::_do_2G_xM1_1PinM2 ()
|
||||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
||||
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
|
||||
|
||||
vector<RoutingPad*> rpsM1;
|
||||
RoutingPad* pinM2 = NULL;
|
||||
for ( RoutingPad* rp : getRoutingPads() ) {
|
||||
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
|
||||
else rpsM1.push_back( rp );
|
||||
}
|
||||
|
||||
AutoContact* pinM2Contact = NULL;
|
||||
AutoContact* rpM1Contact = NULL;
|
||||
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoFlags );
|
||||
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], NoFlags );
|
||||
|
||||
if (north() and south()) {
|
||||
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* vtee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( pinM2Contact, htee, Flags::Horizontal );
|
||||
AutoSegment::create( rpM1Contact , htee, Flags::Vertical );
|
||||
AutoSegment::create( htee , vtee, Flags::Horizontal );
|
||||
setBothCornerContacts( vtee );
|
||||
} else if (east() and west()) {
|
||||
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
|
||||
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
|
||||
AutoSegment::create( htee1 , turn , Flags::Horizontal );
|
||||
AutoSegment::create( htee2 , turn , Flags::Vertical );
|
||||
setBothCornerContacts( htee2 );
|
||||
} else {
|
||||
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
|
||||
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
|
||||
AutoSegment::create( htee1 , htee2, Flags::Horizontal );
|
||||
AutoSegment::create( htee2 , turn , Flags::Vertical );
|
||||
setNorthEastContact( htee2 );
|
||||
setSouthWestContact( turn );
|
||||
}
|
||||
|
||||
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
|
||||
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
|
||||
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
|
||||
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilderHV::_do_1G_1M1_1PinM3 ()
|
||||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
||||
AutoContact* rpSourceContact = NULL;
|
||||
|
||||
RoutingPad* pinM3 = getRoutingPads()[0];
|
||||
RoutingPad* rpM1 = getRoutingPads()[1];
|
||||
if (dynamic_cast<Pin*>(rpM1->getOccurrence().getEntity())) std::swap( rpM1, pinM3 );
|
||||
|
||||
AutoContact* contact1 = doRp_Access( getGCell(), rpM1, HAccess );
|
||||
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( contact1, htee, Flags::Horizontal );
|
||||
|
||||
rpSourceContact = doRp_AccessNorthPin( getGCell(), pinM3 );
|
||||
|
||||
if (north() or south()) {
|
||||
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
|
||||
AutoSegment::create( turn , htee, Flags::Horizontal );
|
||||
} else {
|
||||
AutoSegment::create( rpSourceContact, htee, Flags::Vertical );
|
||||
}
|
||||
setBothCornerContacts( htee );
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NetBuilderHV::_do_2G_1M1 ()
|
||||
{
|
||||
return _do_xG_1M1();
|
||||
|
@ -1349,6 +1529,120 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void NetBuilderHV::singleGCell ( AnabaticEngine* anbt, Net* net )
|
||||
{
|
||||
cdebug_log(145,1) << "NetBuilderHV::singleGCell() " << net << endl;
|
||||
|
||||
vector<RoutingPad*> rpM1s;
|
||||
Component* rpM2 = NULL;
|
||||
RoutingPad* rpPin = NULL;
|
||||
|
||||
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) {
|
||||
rpPin = rp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 1)
|
||||
rpM2 = rp;
|
||||
else
|
||||
rpM1s.push_back( rp );
|
||||
}
|
||||
|
||||
if ( (rpM1s.size() < 2) and not (rpM2 or rpPin) ) {
|
||||
cerr << Error( "For %s, less than two Plugs/Pins (%d)."
|
||||
, getString(net).c_str()
|
||||
, rpM1s.size() ) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rpM1s.empty()) {
|
||||
cerr << Error( "No METAL1 in Single GCell for Net \"%s\".", getString(net->getName()).c_str() ) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
return;
|
||||
}
|
||||
|
||||
sortRpByX( rpM1s, NetBuilder::NoFlags ); // increasing X.
|
||||
|
||||
GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() );
|
||||
GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() );
|
||||
|
||||
if (not gcell1) {
|
||||
cerr << Error( "No GCell under %s.", getString(*(rpM1s.begin())).c_str() ) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
return;
|
||||
}
|
||||
if (gcell1 != gcell2) {
|
||||
cerr << Error( "Not under a single GCell %s.", getString(*(rpM1s.rbegin())).c_str() ) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
return;
|
||||
}
|
||||
|
||||
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
|
||||
|
||||
AutoContact* turn1 = NULL;
|
||||
AutoContact* turn2 = NULL;
|
||||
AutoContact* source = NULL;
|
||||
AutoContact* target = NULL;
|
||||
|
||||
for ( size_t irp=1 ; irp<rpM1s.size() ; ++irp ) {
|
||||
doRp_AutoContacts( gcell1, rpM1s[irp-1], source, turn1, DoSourceContact );
|
||||
doRp_AutoContacts( gcell1, rpM1s[irp ], target, turn1, DoSourceContact );
|
||||
|
||||
if (source->getUConstraints(Flags::Vertical).intersect(target->getUConstraints(Flags::Vertical))) {
|
||||
uint64_t flags = checkRoutingPadSize( rpM1s[irp-1] );
|
||||
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
|
||||
if (Session::getConfiguration()->isHV()) {
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
AutoSegment::create( source, turn1, Flags::Horizontal );
|
||||
source = turn1;
|
||||
}
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
AutoSegment::create( source, turn1 , Flags::Vertical );
|
||||
source = turn1;
|
||||
}
|
||||
flags = checkRoutingPadSize( rpM1s[irp] );
|
||||
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
|
||||
if (Session::getConfiguration()->isHV()) {
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
AutoSegment::create( target, turn1, Flags::Horizontal );
|
||||
target = turn1;
|
||||
}
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
AutoSegment::create( target, turn1 , Flags::Vertical );
|
||||
target = turn1;
|
||||
}
|
||||
AutoSegment::create( source, target, Flags::Horizontal );
|
||||
} else {
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
turn2 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
|
||||
AutoSegment::create( source, turn1 , Flags::Horizontal );
|
||||
AutoSegment::create( turn1 , turn2 , Flags::Vertical );
|
||||
AutoSegment::create( turn2 , target, Flags::Horizontal );
|
||||
}
|
||||
}
|
||||
|
||||
if (rpM2) {
|
||||
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
|
||||
doRp_AutoContacts( gcell1, rpM2 , target, turn1, DoSourceContact );
|
||||
turn1 = AutoContactTurn::create( gcell1, rpM2->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( source, turn1 , Flags::Horizontal );
|
||||
AutoSegment::create( turn1 , target, Flags::Vertical );
|
||||
}
|
||||
|
||||
if (rpPin) {
|
||||
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
|
||||
target = doRp_AccessNorthPin( gcell1, rpPin );
|
||||
turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( source, turn1 , Flags::Horizontal );
|
||||
AutoSegment::create( turn1 , target, Flags::Vertical );
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
}
|
||||
|
||||
|
||||
string NetBuilderHV::getTypeName () const
|
||||
{ return "NetBuilderHV"; }
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace Anabatic {
|
|||
inline bool isHorizontal () const;
|
||||
inline bool hasNet ( const Net* ) const;
|
||||
inline unsigned int getCapacity () const;
|
||||
inline unsigned int getRawCapacity () const;
|
||||
inline unsigned int getReservedCapacity () const;
|
||||
inline unsigned int getCapacity ( size_t depth ) const;
|
||||
inline unsigned int getRealOccupancy () const;
|
||||
|
@ -137,6 +138,7 @@ namespace Anabatic {
|
|||
inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); }
|
||||
inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); }
|
||||
inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; }
|
||||
inline unsigned int Edge::getRawCapacity () const { return (_capacities) ? _capacities->getCapacity() : 0; }
|
||||
inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; }
|
||||
inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; }
|
||||
inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; }
|
||||
|
|
|
@ -221,6 +221,9 @@ namespace Anabatic {
|
|||
virtual bool _do_xG_xM2 ();
|
||||
virtual bool _do_1G_1M3 ();
|
||||
virtual bool _do_xG_xM3 ();
|
||||
virtual bool _do_1G_xM1_1PinM2 ();
|
||||
virtual bool _do_2G_xM1_1PinM2 ();
|
||||
virtual bool _do_1G_1M1_1PinM3 ();
|
||||
virtual bool _do_globalSegment ();
|
||||
virtual void singleGCell ( AnabaticEngine*, Net* );
|
||||
AutoContact* _doHChannel ();
|
||||
|
@ -242,73 +245,79 @@ namespace Anabatic {
|
|||
+ ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
|
||||
+ ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
|
||||
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
|
||||
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
|
||||
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
|
||||
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
|
||||
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
|
||||
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
|
||||
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
|
||||
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
|
||||
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
|
||||
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
|
||||
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
|
||||
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
|
||||
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
|
||||
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
|
||||
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
|
||||
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
|
||||
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
|
||||
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
|
||||
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
|
||||
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
|
||||
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
|
||||
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
|
||||
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
|
||||
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
|
||||
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
|
||||
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
|
||||
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
|
||||
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
|
||||
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
|
||||
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
|
||||
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
|
||||
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
|
||||
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
|
||||
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
|
||||
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
|
||||
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
|
||||
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
|
||||
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
|
||||
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
|
||||
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
|
||||
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
|
||||
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
|
||||
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
|
||||
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
|
||||
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
|
||||
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
|
||||
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
|
||||
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
|
||||
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
|
||||
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
|
||||
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
|
||||
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
|
||||
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
|
||||
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
|
||||
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
|
||||
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
|
||||
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
|
||||
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
|
||||
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
|
||||
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
|
||||
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
|
||||
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
|
||||
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
|
||||
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
|
||||
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
|
||||
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
|
||||
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
|
||||
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
|
||||
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
|
||||
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
|
||||
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
|
||||
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
|
||||
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
|
||||
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
|
||||
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
|
||||
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
|
||||
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
|
||||
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
|
||||
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
|
||||
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
|
||||
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
|
||||
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
|
||||
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
|
||||
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
|
||||
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
|
||||
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
|
||||
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
|
||||
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
|
||||
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
|
||||
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
|
||||
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
|
||||
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
|
||||
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
|
||||
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
|
||||
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
|
||||
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
|
||||
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
|
||||
, Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
|
||||
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
|
||||
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
|
||||
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
|
||||
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
|
||||
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
|
||||
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
|
||||
// Connexity Name | G|M1|M2|M3|Pad|Pin|
|
||||
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
|
||||
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
|
||||
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
|
||||
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
|
||||
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
|
||||
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
|
||||
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
|
||||
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
|
||||
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
|
||||
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
|
||||
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
|
||||
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
|
||||
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
|
||||
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
|
||||
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
|
||||
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
|
||||
, Conn_2G_1M1_1PinM2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 1 )
|
||||
, Conn_2G_2M1_1PinM2 = CONNEXITY_VALUE( 2, 2, 1, 0, 0 , 1 )
|
||||
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
|
||||
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
|
||||
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
|
||||
, Conn_1G_1M1_1PinM3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 1 )
|
||||
};
|
||||
|
||||
#undef CONNEXITY_VALUE
|
||||
|
|
|
@ -28,33 +28,38 @@ namespace Anabatic {
|
|||
|
||||
class NetBuilderHV : public NetBuilder {
|
||||
public:
|
||||
NetBuilderHV ();
|
||||
virtual ~NetBuilderHV ();
|
||||
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
|
||||
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
|
||||
NetBuilderHV ();
|
||||
virtual ~NetBuilderHV ();
|
||||
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
|
||||
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
|
||||
AutoContact* doRp_AccessNorthPin ( GCell*, RoutingPad* );
|
||||
private:
|
||||
virtual bool _do_1G_1M1 ();
|
||||
virtual bool _do_1G_xM1 ();
|
||||
virtual bool _do_xG ();
|
||||
virtual bool _do_2G ();
|
||||
virtual bool _do_2G_1M1 ();
|
||||
virtual bool _do_xG_1Pad ();
|
||||
virtual bool _do_1G_1PinM1 ();
|
||||
virtual bool _do_2G_1PinM1 ();
|
||||
virtual bool _do_1G_1PinM2 ();
|
||||
virtual bool _do_xG_1PinM2 ();
|
||||
virtual bool _do_1G_1PinM3 ();
|
||||
virtual bool _do_xG_1PinM3 ();
|
||||
virtual bool _do_xG_1M1 ();
|
||||
virtual bool _do_xG_1M1_1M2 ();
|
||||
virtual bool _do_xG_xM1_xM3 ();
|
||||
virtual bool _do_4G_1M2 ();
|
||||
virtual bool _do_xG_xM2 ();
|
||||
virtual bool _do_1G_1M3 ();
|
||||
virtual bool _do_xG_xM3 ();
|
||||
virtual bool _do_globalSegment ();
|
||||
public:
|
||||
virtual string getTypeName () const;
|
||||
virtual bool _do_1G_1M1 ();
|
||||
virtual bool _do_1G_xM1 ();
|
||||
virtual bool _do_xG ();
|
||||
virtual bool _do_2G ();
|
||||
virtual bool _do_2G_1M1 ();
|
||||
virtual bool _do_xG_1Pad ();
|
||||
virtual bool _do_1G_1PinM1 ();
|
||||
virtual bool _do_2G_1PinM1 ();
|
||||
virtual bool _do_1G_1PinM2 ();
|
||||
virtual bool _do_xG_1PinM2 ();
|
||||
virtual bool _do_1G_1PinM3 ();
|
||||
virtual bool _do_xG_1PinM3 ();
|
||||
virtual bool _do_xG_1M1 ();
|
||||
virtual bool _do_xG_1M1_1M2 ();
|
||||
virtual bool _do_xG_xM1_xM3 ();
|
||||
virtual bool _do_4G_1M2 ();
|
||||
virtual bool _do_xG_xM2 ();
|
||||
virtual bool _do_1G_1M3 ();
|
||||
virtual bool _do_xG_xM3 ();
|
||||
virtual bool _do_1G_xM1_1PinM2 ();
|
||||
virtual bool _do_2G_xM1_1PinM2 ();
|
||||
virtual bool _do_1G_1M1_1PinM3 ();
|
||||
virtual bool _do_globalSegment ();
|
||||
virtual void singleGCell ( AnabaticEngine*, Net* );
|
||||
public:
|
||||
virtual string getTypeName () const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
|
||||
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
|
||||
buildDir=${commonRoot}/build
|
||||
installDir=${commonRoot}/install
|
||||
|
||||
export ALLIANCE_TOP=${installDir}
|
||||
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
cd ${srcDir}
|
||||
# Skip doc generation to avoid pulling TeXLive in docker images.
|
||||
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
|
||||
./autostuff clean
|
||||
./autostuff
|
||||
mkdir -p ${buildDir}
|
||||
cd ${buildDir}
|
||||
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
|
||||
make -j1 install
|
|
@ -187,8 +187,8 @@ class Builder:
|
|||
if self._ninja: command += [ "-G", "Ninja" ]
|
||||
if self._macports: command += [ "-D", "WITH_MACPORTS:STRING=TRUE" ]
|
||||
if self._noSystemBoost: command += [ "-D", "Boost_NO_SYSTEM_PATHS:STRING=TRUE"
|
||||
, "-D", "BOOST_INCLUDEDIR:STRING=/usr/include/boost169"
|
||||
, "-D", "BOOST_LIBRARYDIR:STRING=/usr/lib64/boost169"
|
||||
#, "-D", "BOOST_INCLUDEDIR:STRING=/usr/include/boost169"
|
||||
#, "-D", "BOOST_LIBRARYDIR:STRING=/usr/lib64/boost169"
|
||||
]
|
||||
if self._qt5: command += [ "-D", "WITH_QT5:STRING=TRUE" ]
|
||||
if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ]
|
||||
|
@ -198,6 +198,7 @@ class Builder:
|
|||
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir
|
||||
, "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir
|
||||
#, "-D", "CMAKE_MODULE_PATH:STRING=%s" % cmakeModules
|
||||
#, "-D", "Boost_DEBUG:STRING=TRUE"
|
||||
, toolSourceDir ]
|
||||
|
||||
if not os.path.isdir(toolBuildDir):
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
FindLibbfd.cmake
|
||||
FindQwt.cmake
|
||||
FindSphinx.cmake
|
||||
FindPelican.cmake
|
||||
GetGitRevisionDescription.cmake
|
||||
GetGitRevisionDescription.cmake.in
|
||||
)
|
||||
|
|
|
@ -39,6 +39,15 @@
|
|||
message("-- Distribution is ${DISTRIBUTION}")
|
||||
endmacro(check_distribution)
|
||||
|
||||
#
|
||||
# Specific setup for MacOS X.
|
||||
#
|
||||
if(WITH_MACPORTS)
|
||||
set(Boost_PYVER "27")
|
||||
else()
|
||||
set(Boost_PYVER "")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Get the svn revision version and configure a svn.h.in file based on this version
|
||||
# The include directory name is passed as argument
|
||||
|
@ -85,9 +94,11 @@
|
|||
set(ADDTIONAL_FLAGS "")
|
||||
set(CXX_STANDARD "c++11")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
|
||||
#set(CMAKE_C_FLAGS_DEBUG " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
|
||||
set(CMAKE_C_FLAGS_DEBUG " -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
|
||||
set(CMAKE_C_FLAGS_RELEASE " -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
|
||||
#set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
|
||||
|
||||
|
||||
|
@ -175,15 +186,6 @@
|
|||
endmacro(hurricane_check_libraries)
|
||||
|
||||
|
||||
#
|
||||
# Find Boost, checking different versions.
|
||||
#
|
||||
if(WITH_MACPORTS)
|
||||
set(Boost_PYVER "27")
|
||||
else()
|
||||
set(Boost_PYVER "")
|
||||
endif()
|
||||
|
||||
macro(setup_boost)
|
||||
#set(Boost_USE_STATIC_LIBS ON)
|
||||
#message(STATUS "Always uses Boost static libraries.")
|
||||
|
@ -191,7 +193,7 @@
|
|||
find_package(Boost 1.35.0 REQUIRED)
|
||||
else(ARGC LESS 1)
|
||||
foreach(component ${ARGV})
|
||||
if(${component} EQUAL "python")
|
||||
if(${component} STREQUAL "python")
|
||||
set(component ${component}${Boost_PYVER})
|
||||
endif()
|
||||
set(components ${components} ${component})
|
||||
|
@ -278,11 +280,13 @@
|
|||
else()
|
||||
find_path(QWT_INCLUDE_DIR NAMES qwt.h
|
||||
PATHS /usr/include/qwt-qt4
|
||||
/opt/local/libexec/qt4/include
|
||||
/usr/include/qt4
|
||||
/usr/include
|
||||
PATH_SUFFIXES qwt )
|
||||
find_library(QWT_LIBRARY NAMES qwt-qt4 qwt
|
||||
PATHS /usr/lib${LIB_SUFFIX} )
|
||||
PATHS /opt/local/libexec/qt4/lib
|
||||
/usr/lib${LIB_SUFFIX} )
|
||||
endif()
|
||||
|
||||
if( QWT_INCLUDE_DIR AND QWT_LIBRARY)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
find_program( PELICAN_EXECUTABLE NAMES pelican
|
||||
HINTS $ENV{PELICAN_DIR}
|
||||
PATH_SUFFIXES bin
|
||||
DOC "Pelican blog generator"
|
||||
)
|
||||
|
||||
include( FindPackageHandleStandardArgs )
|
||||
find_package_handle_standard_args( Pelican DEFAULT_MSG PELICAN_EXECUTABLE )
|
||||
mark_as_advanced( PELICAN_EXECUTABLE )
|
|
@ -130,7 +130,6 @@ def guessOs ():
|
|||
|
||||
print "[WARNING] Unrecognized OS: \"%s\"." % lines[0][:-1]
|
||||
print " (using: \"%s\")" % osType
|
||||
|
||||
ldLibraryPath = os.getenv('LD_LIBRARY_PATH')
|
||||
if ldLibraryPath and 'devtoolset' in ldLibraryPath: useDevtoolset = False
|
||||
|
||||
|
@ -187,6 +186,7 @@ if __name__ == "__main__":
|
|||
parser.add_option ( "--shared" , action="store_true" , dest="shared" )
|
||||
parser.add_option ( "--no-python" , action="store_true" , dest="nopython" )
|
||||
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" )
|
||||
parser.add_option ( "--remove" , action="store_true" , dest="remove" )
|
||||
( options, args ) = parser.parse_args ()
|
||||
|
||||
if options.release: buildType = "Release"
|
||||
|
@ -207,6 +207,32 @@ if __name__ == "__main__":
|
|||
strippedLibraryPath = scrubPath( "LD_LIBRARY_PATH" )
|
||||
strippedPythonPath = scrubPath( "PYTHONPATH" )
|
||||
|
||||
if options.remove:
|
||||
shellScript = 'echo "Removing Coriolis environment";'
|
||||
if osType == "Darwin":
|
||||
ldVar = 'DYLD_LIBRARY_PATH'
|
||||
else:
|
||||
ldVar = 'LD_LIBRARY_PATH'
|
||||
|
||||
if isBourneShell:
|
||||
shellScript += 'export PATH={};hash -r;'.format(strippedPath)
|
||||
shellScript += 'BOOTSTRAP_TOP="";CORIOLIS_TOP="";export -n BOOTSTRAP_TOP CORIOLIS_TOP;'
|
||||
if strippedLibraryPath:
|
||||
shellScript += 'export {}={};'.format(ldVar, strippedLibraryPath)
|
||||
else:
|
||||
shellScript += '{0}=""; export -n {0};'.format(ldVar)
|
||||
else:
|
||||
shellScript += 'setenv PATH {};rehash;'.format(strippedPath)
|
||||
shellScript += 'unsetenv BOOTSTRAP_TOP CORIOLIS_TOP;'
|
||||
if strippedLibraryPath:
|
||||
shellScript += 'setenv {} {};'.format(ldVar, strippedLibraryPath)
|
||||
else:
|
||||
shellScript += 'unsetenv {};'.format(ldVar)
|
||||
|
||||
print(shellScript)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
shellScriptSh = \
|
||||
'echo "%(MESSAGE)s";' \
|
||||
'echo "Switching to Coriolis 2.x (%(buildDir)s)";' \
|
||||
|
@ -273,16 +299,25 @@ if __name__ == "__main__":
|
|||
if not options.nopython:
|
||||
pyVersion = sys.version_info
|
||||
version = "%d.%d" % (pyVersion[0],pyVersion[1])
|
||||
if osType.startswith("Linux.SL") \
|
||||
or osType.startswith("Linux.sl") \
|
||||
or osType.startswith("Linux.el") \
|
||||
or osType.startswith("Linux.fc") \
|
||||
or osType.startswith("Cygwin"):
|
||||
sitePackagesDir = "%s/python%s/site-packages" % (absLibDir,version)
|
||||
elif osType.startswith("Darwin"):
|
||||
sitePackagesDir = "%s/%s/site-packages" % (absLibDir,version)
|
||||
else:
|
||||
sitePackagesDir = "%s/python%s/dist-packages" % (absLibDir,version)
|
||||
#if osType.startswith("Linux.SL") \
|
||||
# or osType.startswith("Linux.sl") \
|
||||
# or osType.startswith("Linux.el") \
|
||||
# or osType.startswith("Linux.fc") \
|
||||
# or osType.startswith("Cygwin"):
|
||||
# sitePackagesDir = "%s/python%s/site-packages" % (absLibDir,version)
|
||||
#elif osType.startswith("Darwin"):
|
||||
# sitePackagesDir = "%s/%s/site-packages" % (absLibDir,version)
|
||||
#else:
|
||||
# sitePackagesDir = "%s/python%s/dist-packages" % (absLibDir,version)
|
||||
|
||||
sitePackagesDir = "sitePackageDir_has_been_not_found"
|
||||
for pyPackageDir in [ "%s/python%s/site-packages" % (absLibDir,version)
|
||||
, "%s/python%s/dist-packages" % (absLibDir,version)
|
||||
, "%s/%s/site-packages" % (absLibDir,version)
|
||||
]:
|
||||
if os.path.isdir(pyPackageDir):
|
||||
sitePackagesDir = pyPackageDir
|
||||
break
|
||||
|
||||
strippedPythonPath = "%s:" % (sitePackagesDir) + strippedPythonPath
|
||||
strippedPythonPath = "%s/crlcore:" % (sitePackagesDir) + strippedPythonPath
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
FROM debian9.coriolis
|
||||
|
||||
COPY root/dot.bashrc /root/.bashrc
|
||||
|
||||
CMD [ "/bin/bash", "-i" ]
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
FROM debian9.system
|
||||
|
||||
COPY root/socInstaller.py /root/socInstaller.py
|
||||
RUN mkdir -p coriolis-2.x/src \
|
||||
&& git clone https://github.com/m-labs/nmigen.git \
|
||||
&& cd nmigen \
|
||||
&& python3 setup.py develop \
|
||||
&& /root/socInstaller.py --docker --profile=Debian9 --do-alliance --do-coriolis --benchs
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
FROM debian:stretch-slim
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get -y install build-essential binutils-dev \
|
||||
git cmake bison flex gcc python-dev \
|
||||
libboost-all-dev libboost-python-dev \
|
||||
zlib1g-dev libxml2-dev rapidjson-dev libbz2-dev \
|
||||
qt4-dev-tools libqwt-dev python-qt4 \
|
||||
python3-setuptools \
|
||||
\
|
||||
autotools-dev automake \
|
||||
libxt-dev libxpm-dev libmotif-dev \
|
||||
\
|
||||
yosys \
|
||||
\
|
||||
vim \
|
||||
&& apt-get clean
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
systemImage="debian9.system"
|
||||
coriolisImage="debian9.coriolis"
|
||||
bashImage="debian9.bash"
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
|
||||
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
|
||||
buildDir=${commonRoot}/build
|
||||
installDir=${commonRoot}/install
|
||||
|
||||
export ALLIANCE_TOP=${installDir}
|
||||
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
cd ${srcDir}
|
||||
# Skip doc generation to avoid pulling TeXLive in docker images.
|
||||
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
|
||||
./autostuff clean
|
||||
./autostuff
|
||||
mkdir -p ${buildDir}
|
||||
cd ${buildDir}
|
||||
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
|
||||
make -j1 install
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
echo "Running /root/.bashrc"
|
||||
|
||||
for archDir in `ls /root/coriolis-2.x/`; do
|
||||
if [ "$archDir" = "src" ]; then continue; fi
|
||||
break
|
||||
done
|
||||
echo "Found Coriolis architecture directory \"${archDir}\"."
|
||||
|
||||
installDir="/root/coriolis-2.x/${archDir}/Release.Shared/install"
|
||||
. ${installDir}/etc/profile.d/alc_env.sh
|
||||
eval `${installDir}/etc/coriolis2/coriolisEnv.py`
|
||||
|
||||
export QT_X11_NO_MITSHM=1
|
|
@ -0,0 +1,627 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# -*- mode:Python -*-
|
||||
#
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) UPMC 2015-2018, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C o r i o l i s I n s t a l l e r |
|
||||
# | |
|
||||
# | Authors : Jean-Paul Chaput |
|
||||
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./socInstaller.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
#
|
||||
# WARNING:
|
||||
# This script has been designed only for internal use in the
|
||||
# LIP6/CIAN department. If you want to use it you will need to
|
||||
# change the hardwired configuration.
|
||||
|
||||
|
||||
showTrace = True
|
||||
|
||||
try:
|
||||
import sys
|
||||
import os.path
|
||||
import shutil
|
||||
import optparse
|
||||
import time
|
||||
import traceback
|
||||
import distutils.sysconfig
|
||||
import subprocess
|
||||
import socket
|
||||
import re
|
||||
import bz2
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
except ImportError, e:
|
||||
module = str(e).split()[-1]
|
||||
|
||||
|
||||
class ErrorMessage ( Exception ):
|
||||
|
||||
def __init__ ( self, code, *arguments ):
|
||||
self._code = code
|
||||
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
|
||||
|
||||
text = None
|
||||
if len(arguments) == 1:
|
||||
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
|
||||
else:
|
||||
self._errors = arguments[0]
|
||||
elif len(arguments) > 1:
|
||||
text = list(arguments)
|
||||
|
||||
if text:
|
||||
self._errors = []
|
||||
while len(text[0]) == 0: del text[0]
|
||||
|
||||
lstrip = 0
|
||||
if text[0].startswith('[ERROR]'): lstrip = 8
|
||||
|
||||
for line in text:
|
||||
if line[0:lstrip ] == ' '*lstrip or \
|
||||
line[0:lstrip-1] == '[ERROR]':
|
||||
self._errors += [ line[lstrip:] ]
|
||||
else:
|
||||
self._errors += [ line.lstrip() ]
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
if not isinstance(self._errors,list):
|
||||
return "[ERROR] %s" % self._errors
|
||||
|
||||
formatted = "\n"
|
||||
for i in range(len(self._errors)):
|
||||
if i == 0: formatted += "[ERROR] %s" % self._errors[i]
|
||||
else: formatted += " %s" % self._errors[i]
|
||||
if i+1 < len(self._errors): formatted += "\n"
|
||||
return formatted
|
||||
|
||||
def addMessage ( self, message ):
|
||||
if not isinstance(self._errors,list):
|
||||
self._errors = [ self._errors ]
|
||||
if isinstance(message,list):
|
||||
for line in message:
|
||||
self._errors += [ line ]
|
||||
else:
|
||||
self._errors += [ message ]
|
||||
return
|
||||
|
||||
def terminate ( self ):
|
||||
print self
|
||||
sys.exit(self._code)
|
||||
|
||||
@property
|
||||
def code ( self ): return self._code
|
||||
|
||||
|
||||
class BadBinary ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, binary ):
|
||||
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
|
||||
return
|
||||
|
||||
|
||||
class BadReturnCode ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, status ):
|
||||
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
|
||||
return
|
||||
|
||||
|
||||
class Command ( object ):
|
||||
|
||||
def __init__ ( self, arguments, fdLog=None ):
|
||||
self.arguments = arguments
|
||||
self.fdLog = fdLog
|
||||
|
||||
if self.fdLog != None and not isinstance(self.fdLog,file):
|
||||
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
|
||||
return
|
||||
|
||||
def _argumentsToStr ( self, arguments ):
|
||||
s = ''
|
||||
for argument in arguments:
|
||||
if argument.find(' ') >= 0: s += ' "' + argument + '"'
|
||||
else: s += ' ' + argument
|
||||
return s
|
||||
|
||||
def log ( self, text ):
|
||||
print text[:-1]
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
if isinstance(self.fdLog,file):
|
||||
self.fdLog.write( text )
|
||||
self.fdLog.flush()
|
||||
return
|
||||
|
||||
def execute ( self ):
|
||||
global conf
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
homeDir = os.environ['HOME']
|
||||
workDir = os.getcwd()
|
||||
if homeDir.startswith(homeDir):
|
||||
workDir = '~' + workDir[ len(homeDir) : ]
|
||||
user = 'root'
|
||||
if os.environ.has_key('USER'): user = os.environ['USER']
|
||||
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
|
||||
|
||||
try:
|
||||
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
|
||||
print self.arguments
|
||||
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
|
||||
while True:
|
||||
line = child.stdout.readline()
|
||||
if not line: break
|
||||
|
||||
self.log( line )
|
||||
except OSError, e:
|
||||
raise BadBinary( self.arguments[0] )
|
||||
|
||||
(pid,status) = os.waitpid( child.pid, 0 )
|
||||
status >>= 8
|
||||
if status != 0:
|
||||
raise BadReturnCode( status )
|
||||
|
||||
return
|
||||
|
||||
|
||||
class CommandArg ( object ):
|
||||
|
||||
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
|
||||
self.command = command
|
||||
self.host = host
|
||||
self.wd = wd
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
s = ''
|
||||
if self.wd: s = 'cd %s && ' % self.wd
|
||||
|
||||
for i in range(len(self.command)):
|
||||
if i: s += ' '
|
||||
s += self.command[i]
|
||||
return s
|
||||
|
||||
def getArgs ( self ):
|
||||
if not self.host: return self.command
|
||||
return [ 'ssh', self.host, str(self) ]
|
||||
|
||||
def execute ( self ):
|
||||
if not self.host and self.wd: os.chdir( self.wd )
|
||||
Command( self.getArgs(), self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class AllianceCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, alcBin, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ alcBin ], fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class CoriolisCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, ccbBin, rootDir, threads=1, otherArgs=[], fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ ccbBin
|
||||
, '--root='+rootDir
|
||||
, '--project=coriolis'
|
||||
, '--make=-j%d install' % threads
|
||||
] + otherArgs
|
||||
, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class BenchsCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, benchsDir, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ '../bin/go.sh' ], wd=benchsDir, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
|
||||
class GitRepository ( object ):
|
||||
|
||||
@staticmethod
|
||||
def getLocalRepository ( url ):
|
||||
localRepo = url.split( '/' )[-1]
|
||||
if localRepo.endswith('.git'):
|
||||
localRepo = localRepo[:-4]
|
||||
return localRepo
|
||||
|
||||
def __init__ ( self, url, cloneDir, fdLog=None ):
|
||||
self.url = url
|
||||
self.cloneDir = cloneDir
|
||||
self.localRepo = GitRepository.getLocalRepository( url )
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
@property
|
||||
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
|
||||
|
||||
def removeLocalRepo ( self ):
|
||||
if os.path.isdir(self.localRepoDir):
|
||||
print 'Removing Git local repository: <%s>' % self.localRepoDir
|
||||
shutil.rmtree( self.localRepoDir )
|
||||
return
|
||||
|
||||
def clone ( self ):
|
||||
print 'Clone/pull from:', self.url
|
||||
if not os.path.isdir(self.cloneDir):
|
||||
os.makedirs( self.cloneDir )
|
||||
|
||||
if not os.path.isdir(self.localRepoDir):
|
||||
os.chdir( self.cloneDir )
|
||||
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
|
||||
else:
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'pull' ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
def checkout ( self, branch ):
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class Configuration ( object ):
|
||||
|
||||
PrimaryNames = \
|
||||
[ 'sender' , 'receivers'
|
||||
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
|
||||
, 'homeDir' , 'masterHost'
|
||||
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
|
||||
, 'rmSource' , 'rmBuild'
|
||||
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
|
||||
, 'success' , 'rcode'
|
||||
]
|
||||
SecondaryNames = \
|
||||
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'alcBin', 'ccbBin', 'benchsDir'
|
||||
]
|
||||
|
||||
def __init__ ( self ):
|
||||
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
|
||||
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
|
||||
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
|
||||
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
|
||||
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
|
||||
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
|
||||
self._homeDir = os.environ['HOME']
|
||||
self._debugArg = ''
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = True
|
||||
self._doCoriolis = False
|
||||
self._doAlliance = False
|
||||
self._doBenchs = False
|
||||
self._doSendReport = False
|
||||
self._nightlyMode = False
|
||||
self._dockerMode = False
|
||||
self._chrootMode = False
|
||||
self._logs = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._fds = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._ccbBin = None
|
||||
self._benchsDir = None
|
||||
self._masterHost = self._detectMasterHost()
|
||||
self._success = False
|
||||
self._rcode = 0
|
||||
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __setattr__ ( self, attribute, value ):
|
||||
if attribute in Configuration.SecondaryNames:
|
||||
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
|
||||
return
|
||||
|
||||
if attribute == 'masterHost' or attribute == '_masterHost':
|
||||
if value == 'lepka':
|
||||
print 'Never touch the Git tree when running on <lepka>.'
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = False
|
||||
self._doSendReport = False
|
||||
|
||||
if attribute[0] == '_':
|
||||
self.__dict__[attribute] = value
|
||||
return
|
||||
|
||||
if attribute == 'homeDir': value = os.path.expanduser(value)
|
||||
|
||||
self.__dict__['_'+attribute] = value
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __getattr__ ( self, attribute ):
|
||||
if attribute[0] != '_': attribute = '_'+attribute
|
||||
if not self.__dict__.has_key(attribute):
|
||||
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
|
||||
return self.__dict__[attribute]
|
||||
|
||||
def _updateSecondaries ( self ):
|
||||
if self._nightlyMode:
|
||||
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
|
||||
else:
|
||||
self._rootDir = self._homeDir + '/coriolis-2.x'
|
||||
self._srcDir = self._rootDir + '/src'
|
||||
self._logDir = self._srcDir + '/logs'
|
||||
self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
|
||||
self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
|
||||
self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
|
||||
return
|
||||
|
||||
def _detectMasterHost ( self ):
|
||||
if self._chrootMode: return 'chrooted-host'
|
||||
|
||||
masterHost = 'unknown'
|
||||
hostname = socket.gethostname()
|
||||
hostAddr = socket.gethostbyname(hostname)
|
||||
|
||||
if hostname == 'lepka' and hostAddr == '127.0.0.1':
|
||||
masterHost = 'lepka'
|
||||
else:
|
||||
masterHost = hostname.split('.')[0]
|
||||
return masterHost
|
||||
|
||||
def openLog ( self, stem ):
|
||||
if not os.path.isdir(self._logDir):
|
||||
os.makedirs( self._logDir )
|
||||
|
||||
index = 0
|
||||
timeTag = time.strftime( "%Y.%m.%d" )
|
||||
while True:
|
||||
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
|
||||
if not os.path.isfile(logFile):
|
||||
print "Report log: <%s>" % logFile
|
||||
break
|
||||
index += 1
|
||||
fd = open( logFile, "w" )
|
||||
self._logs[stem] = logFile
|
||||
self._fds [stem] = fd
|
||||
return
|
||||
|
||||
def closeLogs ( self ):
|
||||
for fd in self._fds.values():
|
||||
if fd: fd.close()
|
||||
return
|
||||
|
||||
def compressLogs ( self ):
|
||||
for log in self._logs.values():
|
||||
if not log: continue
|
||||
|
||||
fd = open( log, 'r' )
|
||||
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
|
||||
|
||||
for line in fd.readlines(): bzfd.write( line )
|
||||
|
||||
bzfd.close()
|
||||
fd.close()
|
||||
|
||||
os.unlink( log )
|
||||
return
|
||||
|
||||
def getCommands ( self, target ):
|
||||
commands = []
|
||||
|
||||
if self.doAlliance:
|
||||
if not os.path.isfile( self.alcBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <allianceInstaller.sh>, should be here:'
|
||||
, ' <%s>' % self.alcBin
|
||||
] )
|
||||
commands.append( AllianceCommand( self.alcBin, fdLog=self.fds['alliance'] ) )
|
||||
|
||||
if self.doCoriolis:
|
||||
if not os.path.isfile( self.ccbBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
|
||||
, ' <%s>' % self.ccbBin
|
||||
] )
|
||||
|
||||
otherArgs = []
|
||||
if self.debugArg: otherArgs.append( self.debugArg )
|
||||
|
||||
if target == 'SL7_64':
|
||||
otherArgs.append( '--project=support' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'SL6_64' or target == 'SL6':
|
||||
otherArgs.append( '--project=support' )
|
||||
otherArgs.append( '--devtoolset=8' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 6, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'Ubuntu18' or target == 'Debian9':
|
||||
if target == 'Ubuntu18': otherArgs.append( '--qt5' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs, fdLog=self.fds['coriolis'] ) )
|
||||
|
||||
if self.doBenchs:
|
||||
commands.append( BenchsCommand( self.benchsDir, fdLog=self.fds['benchs'] ) )
|
||||
return commands
|
||||
|
||||
|
||||
class Report ( object ):
|
||||
|
||||
def __init__ ( self, conf ):
|
||||
self.conf = conf
|
||||
|
||||
commaspace = ', '
|
||||
date = time.strftime( "%A %d %B %Y" )
|
||||
stateText = 'FAILED'
|
||||
modeText = 'SoC installation'
|
||||
if self.conf.success: stateText = 'SUCCESS'
|
||||
if self.conf.nightlyMode: modeText = 'Nightly build'
|
||||
|
||||
self.message = MIMEMultipart()
|
||||
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
|
||||
self.message['From' ] = self.conf.sender
|
||||
self.message['To' ] = commaspace.join( self.conf.receivers )
|
||||
self.attachements = []
|
||||
|
||||
self.mainText = '\n'
|
||||
self.mainText += 'Salut le Crevard,\n'
|
||||
self.mainText += '\n'
|
||||
if self.conf.nightlyMode:
|
||||
self.mainText += 'This is the nightly build report of Coriolis.\n'
|
||||
else:
|
||||
self.mainText += 'SoC installer report of Coriolis.\n'
|
||||
self.mainText += '%s\n' % date
|
||||
self.mainText += '\n'
|
||||
if self.conf.success:
|
||||
self.mainText += 'Build was SUCCESSFUL\n'
|
||||
else:
|
||||
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
|
||||
self.mainText += '\n'
|
||||
self.mainText += 'Complete log file(s) can be found here:\n'
|
||||
return
|
||||
|
||||
def attachLog ( self, logFile ):
|
||||
if not logFile: return
|
||||
|
||||
fd = open( logFile, 'rb' )
|
||||
try:
|
||||
fd.seek( -1024*100, os.SEEK_END )
|
||||
except IOError, e:
|
||||
pass
|
||||
tailLines = ''
|
||||
for line in fd.readlines()[1:]:
|
||||
tailLines += line
|
||||
fd.close()
|
||||
self.mainText += ' <%s>\n' % logFile
|
||||
|
||||
attachement = MIMEApplication(tailLines)
|
||||
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
|
||||
|
||||
self.attachements.append( attachement )
|
||||
return
|
||||
|
||||
def send ( self ):
|
||||
self.message.attach( MIMEText(self.mainText) )
|
||||
for attachement in self.attachements:
|
||||
self.message.attach( attachement )
|
||||
|
||||
print "Sending mail report to:"
|
||||
for receiver in self.conf.receivers: print ' <%s>' % receiver
|
||||
session = smtplib.SMTP( 'localhost' )
|
||||
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
|
||||
session.quit()
|
||||
return
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# <socInstaller> Main Part.
|
||||
|
||||
|
||||
parser = optparse.OptionParser ()
|
||||
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." )
|
||||
parser.add_option ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
|
||||
parser.add_option ( "--do-alliance" , action="store_true" , dest="doAlliance" , help="Rebuild the Alliance tools." )
|
||||
parser.add_option ( "--do-coriolis" , action="store_true" , dest="doCoriolis" , help="Rebuild the Coriolis tools." )
|
||||
parser.add_option ( "--do-report" , action="store_true" , dest="doReport" , help="Send a final report." )
|
||||
parser.add_option ( "--nightly" , action="store_true" , dest="nightly" , help="Perform a nighly build." )
|
||||
parser.add_option ( "--docker" , action="store_true" , dest="docker" , help="Perform a build inside a docker container." )
|
||||
parser.add_option ( "--chroot" , action="store_true" , dest="chroot" , help="Perform a build inside a chrooted environment." )
|
||||
parser.add_option ( "--benchs" , action="store_true" , dest="benchs" , help="Run the <alliance-checker-toolkit> sanity benchs." )
|
||||
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove the build/install directories." )
|
||||
parser.add_option ( "--rm-source" , action="store_true" , dest="rmSource" , help="Remove the Git source repositories." )
|
||||
parser.add_option ( "--rm-all" , action="store_true" , dest="rmAll" , help="Remove everything (source+build+install)." )
|
||||
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" , help="The root directory (default: <~/coriolis-2.x/>)." )
|
||||
parser.add_option ( "--profile" , action="store" , type="string", dest="profile" , help="The targeted OS for the build." )
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
conf = Configuration()
|
||||
|
||||
try:
|
||||
if options.debug: conf.debugArg = '--debug'
|
||||
if options.nightly: conf.nightlyMode = True
|
||||
if options.docker: conf.dockerMode = True
|
||||
if options.chroot: conf.chrootMode = True
|
||||
if options.noGit: conf.doGit = False
|
||||
if options.doCoriolis: conf.doCoriolis = True
|
||||
if options.doAlliance: conf.doAlliance = True
|
||||
if options.benchs: conf.doBenchs = True
|
||||
if options.doReport: conf.doSendReport = True
|
||||
if options.rmSource or options.rmAll: conf.rmSource = True
|
||||
if options.rmBuild or options.rmAll: conf.rmBuild = True
|
||||
|
||||
if conf.doAlliance: conf.openLog( 'alliance' )
|
||||
if conf.doCoriolis: conf.openLog( 'coriolis' )
|
||||
if conf.doBenchs: conf.openLog( 'benchs' )
|
||||
|
||||
if conf.dockerMode: os.environ['USER'] = 'root'
|
||||
|
||||
gitSupports = []
|
||||
for supportRepo in conf.supportRepos:
|
||||
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
|
||||
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
|
||||
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
|
||||
|
||||
if conf.doAlliance:
|
||||
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
|
||||
|
||||
if conf.doGit:
|
||||
for gitSupport in gitSupports:
|
||||
if conf.rmSource: gitSupport.removeLocalRepo()
|
||||
gitSupport.clone()
|
||||
#if gitSupport.url.endswith('rapidjson'):
|
||||
# gitSupport.checkout( 'a1c4f32' )
|
||||
|
||||
if conf.doCoriolis:
|
||||
if conf.rmSource: gitCoriolis.removeLocalRepo()
|
||||
gitCoriolis.clone ()
|
||||
gitCoriolis.checkout( 'devel' )
|
||||
|
||||
if conf.doAlliance:
|
||||
if conf.rmSource: gitAlliance.removeLocalRepo()
|
||||
gitAlliance.clone ()
|
||||
#gitAlliance.checkout( 'devel' )
|
||||
|
||||
if conf.rmSource: gitBenchs.removeLocalRepo()
|
||||
gitBenchs.clone()
|
||||
|
||||
if conf.rmBuild:
|
||||
for entry in os.listdir(conf.rootDir):
|
||||
if entry.startswith('Linux.'):
|
||||
buildDir = conf.rootDir+'/'+entry
|
||||
print 'Removing OS build directory: <%s>' % buildDir
|
||||
shutil.rmtree( buildDir )
|
||||
|
||||
commands = conf.getCommands( options.profile )
|
||||
for command in commands:
|
||||
if command.host:
|
||||
print 'Executing command on remote host <%s>:' % host
|
||||
else:
|
||||
print 'Executing command on *local* host:'
|
||||
print ' %s' % str(command)
|
||||
command.execute()
|
||||
|
||||
conf.closeLogs()
|
||||
|
||||
conf.success = True
|
||||
|
||||
except ErrorMessage, e:
|
||||
print e
|
||||
conf.closeLogs()
|
||||
conf.success = False
|
||||
|
||||
if showTrace:
|
||||
print '\nPython stack trace:'
|
||||
traceback.print_tb( sys.exc_info()[2] )
|
||||
conf.rcode = e.code
|
||||
|
||||
if conf.doSendReport:
|
||||
report = Report( conf )
|
||||
report.attachLog( conf.logs['coriolis' ] )
|
||||
report.attachLog( conf.logs['benchs' ] )
|
||||
report.send()
|
||||
|
||||
conf.compressLogs()
|
||||
|
||||
sys.exit( conf.rcode )
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
FROM sl7.coriolis
|
||||
|
||||
COPY root/dot.bashrc /root/.bashrc
|
||||
|
||||
CMD [ "/bin/bash", "-i" ]
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
FROM sl7.system
|
||||
|
||||
COPY root/socInstaller.py /root/socInstaller.py
|
||||
RUN /root/socInstaller.py --docker --profile=SL7_64 --do-alliance --do-coriolis --benchs
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
FROM scientificlinux/sl:latest
|
||||
|
||||
RUN yum -y update \
|
||||
&& yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
|
||||
&& yum -y install git cmake bison flex gcc-c++ libstdc++-devel \
|
||||
make binutils-devel \
|
||||
boost-devel boost-python boost-filesystem \
|
||||
boost-regex boost-wave \
|
||||
python-devel libxml2-devel bzip2-devel \
|
||||
qt-devel PyQt4 \
|
||||
\
|
||||
autoconf automake libtool \
|
||||
libX11-devel libXt-devel libXpm-devel \
|
||||
motif motif-devel \
|
||||
\
|
||||
python36-six \
|
||||
vim-x11 \
|
||||
&& yum -y install http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/qwt-6.1.2-4.fc23.x86_64.rpm \
|
||||
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/qwt-devel-6.1.2-4.fc23.x86_64.rpm \
|
||||
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/yosys-0.9-1.el7.soc.x86_64.rpm \
|
||||
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/python3-pyvcd-0.1.7-git2302c99.1.el7.soc.x86_64.rpm \
|
||||
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/python3-nmigen-0.1-git57d95b7.1.el7.soc.x86_64.rpm \
|
||||
&& yum clean all
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
systemImage="sl7.system"
|
||||
coriolisImage="sl7.coriolis"
|
||||
bashImage="sl7.bash"
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
|
||||
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
|
||||
buildDir=${commonRoot}/build
|
||||
installDir=${commonRoot}/install
|
||||
|
||||
export ALLIANCE_TOP=${installDir}
|
||||
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
cd ${srcDir}
|
||||
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
|
||||
./autostuff clean
|
||||
./autostuff
|
||||
mkdir -p ${buildDir}
|
||||
cd ${buildDir}
|
||||
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
|
||||
make -j1 install
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
echo "Running /root/.bashrc"
|
||||
|
||||
for archDir in `ls /root/coriolis-2.x/`; do
|
||||
if [ "$archDir" = "src" ]; then continue; fi
|
||||
break
|
||||
done
|
||||
echo "Found Coriolis architecture directory \"${archDir}\"."
|
||||
|
||||
installDir="/root/coriolis-2.x/${archDir}/Release.Shared/install"
|
||||
. ${installDir}/etc/profile.d/alc_env.sh
|
||||
eval `${installDir}/etc/coriolis2/coriolisEnv.py`
|
||||
|
||||
export QT_X11_NO_MITSHM=1
|
|
@ -0,0 +1,631 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# -*- mode:Python -*-
|
||||
#
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) UPMC 2015-2018, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C o r i o l i s I n s t a l l e r |
|
||||
# | |
|
||||
# | Authors : Jean-Paul Chaput |
|
||||
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./socInstaller.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
#
|
||||
# WARNING:
|
||||
# This script has been designed only for internal use in the
|
||||
# LIP6/CIAN department. If you want to use it you will need to
|
||||
# change the hardwired configuration.
|
||||
|
||||
|
||||
showTrace = True
|
||||
|
||||
try:
|
||||
import sys
|
||||
import os.path
|
||||
import shutil
|
||||
import optparse
|
||||
import time
|
||||
import traceback
|
||||
import distutils.sysconfig
|
||||
import subprocess
|
||||
import socket
|
||||
import re
|
||||
import bz2
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
except ImportError, e:
|
||||
module = str(e).split()[-1]
|
||||
|
||||
|
||||
class ErrorMessage ( Exception ):
|
||||
|
||||
def __init__ ( self, code, *arguments ):
|
||||
self._code = code
|
||||
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
|
||||
|
||||
text = None
|
||||
if len(arguments) == 1:
|
||||
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
|
||||
else:
|
||||
self._errors = arguments[0]
|
||||
elif len(arguments) > 1:
|
||||
text = list(arguments)
|
||||
|
||||
if text:
|
||||
self._errors = []
|
||||
while len(text[0]) == 0: del text[0]
|
||||
|
||||
lstrip = 0
|
||||
if text[0].startswith('[ERROR]'): lstrip = 8
|
||||
|
||||
for line in text:
|
||||
if line[0:lstrip ] == ' '*lstrip or \
|
||||
line[0:lstrip-1] == '[ERROR]':
|
||||
self._errors += [ line[lstrip:] ]
|
||||
else:
|
||||
self._errors += [ line.lstrip() ]
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
if not isinstance(self._errors,list):
|
||||
return "[ERROR] %s" % self._errors
|
||||
|
||||
formatted = "\n"
|
||||
for i in range(len(self._errors)):
|
||||
if i == 0: formatted += "[ERROR] %s" % self._errors[i]
|
||||
else: formatted += " %s" % self._errors[i]
|
||||
if i+1 < len(self._errors): formatted += "\n"
|
||||
return formatted
|
||||
|
||||
def addMessage ( self, message ):
|
||||
if not isinstance(self._errors,list):
|
||||
self._errors = [ self._errors ]
|
||||
if isinstance(message,list):
|
||||
for line in message:
|
||||
self._errors += [ line ]
|
||||
else:
|
||||
self._errors += [ message ]
|
||||
return
|
||||
|
||||
def terminate ( self ):
|
||||
print self
|
||||
sys.exit(self._code)
|
||||
|
||||
@property
|
||||
def code ( self ): return self._code
|
||||
|
||||
|
||||
class BadBinary ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, binary ):
|
||||
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
|
||||
return
|
||||
|
||||
|
||||
class BadReturnCode ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, status ):
|
||||
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
|
||||
return
|
||||
|
||||
|
||||
class Command ( object ):
|
||||
|
||||
def __init__ ( self, arguments, fdLog=None ):
|
||||
self.arguments = arguments
|
||||
self.fdLog = fdLog
|
||||
|
||||
if self.fdLog != None and not isinstance(self.fdLog,file):
|
||||
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
|
||||
return
|
||||
|
||||
def _argumentsToStr ( self, arguments ):
|
||||
s = ''
|
||||
for argument in arguments:
|
||||
if argument.find(' ') >= 0: s += ' "' + argument + '"'
|
||||
else: s += ' ' + argument
|
||||
return s
|
||||
|
||||
def log ( self, text ):
|
||||
print text[:-1]
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
if isinstance(self.fdLog,file):
|
||||
self.fdLog.write( text )
|
||||
self.fdLog.flush()
|
||||
return
|
||||
|
||||
def execute ( self ):
|
||||
global conf
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
homeDir = os.environ['HOME']
|
||||
workDir = os.getcwd()
|
||||
if homeDir.startswith(homeDir):
|
||||
workDir = '~' + workDir[ len(homeDir) : ]
|
||||
user = 'root'
|
||||
if os.environ.has_key('USER'): user = os.environ['USER']
|
||||
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
|
||||
|
||||
try:
|
||||
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
|
||||
print self.arguments
|
||||
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
|
||||
while True:
|
||||
line = child.stdout.readline()
|
||||
if not line: break
|
||||
|
||||
self.log( line )
|
||||
except OSError, e:
|
||||
raise BadBinary( self.arguments[0] )
|
||||
|
||||
(pid,status) = os.waitpid( child.pid, 0 )
|
||||
status >>= 8
|
||||
if status != 0:
|
||||
raise BadReturnCode( status )
|
||||
|
||||
return
|
||||
|
||||
|
||||
class CommandArg ( object ):
|
||||
|
||||
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
|
||||
self.command = command
|
||||
self.host = host
|
||||
self.wd = wd
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
s = ''
|
||||
if self.wd: s = 'cd %s && ' % self.wd
|
||||
|
||||
for i in range(len(self.command)):
|
||||
if i: s += ' '
|
||||
s += self.command[i]
|
||||
return s
|
||||
|
||||
def getArgs ( self ):
|
||||
if not self.host: return self.command
|
||||
return [ 'ssh', self.host, str(self) ]
|
||||
|
||||
def execute ( self ):
|
||||
if not self.host and self.wd: os.chdir( self.wd )
|
||||
Command( self.getArgs(), self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class AllianceCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, alcBin, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ alcBin ], fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class CoriolisCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, ccbBin, rootDir, threads=1, otherArgs=[], fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ ccbBin
|
||||
, '--root='+rootDir
|
||||
, '--project=coriolis'
|
||||
, '--make=-j%d install' % threads
|
||||
] + otherArgs
|
||||
, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class BenchsCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, benchsDir, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ '../bin/go.sh' ], wd=benchsDir, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
|
||||
class GitRepository ( object ):
|
||||
|
||||
@staticmethod
|
||||
def getLocalRepository ( url ):
|
||||
localRepo = url.split( '/' )[-1]
|
||||
if localRepo.endswith('.git'):
|
||||
localRepo = localRepo[:-4]
|
||||
return localRepo
|
||||
|
||||
def __init__ ( self, url, cloneDir, fdLog=None ):
|
||||
self.url = url
|
||||
self.cloneDir = cloneDir
|
||||
self.localRepo = GitRepository.getLocalRepository( url )
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
@property
|
||||
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
|
||||
|
||||
def removeLocalRepo ( self ):
|
||||
if os.path.isdir(self.localRepoDir):
|
||||
print 'Removing Git local repository: <%s>' % self.localRepoDir
|
||||
shutil.rmtree( self.localRepoDir )
|
||||
return
|
||||
|
||||
def clone ( self ):
|
||||
print 'Clone/pull from:', self.url
|
||||
if not os.path.isdir(self.cloneDir):
|
||||
os.makedirs( self.cloneDir )
|
||||
|
||||
if not os.path.isdir(self.localRepoDir):
|
||||
os.chdir( self.cloneDir )
|
||||
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
|
||||
else:
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'pull' ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
def checkout ( self, branch ):
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class Configuration ( object ):
|
||||
|
||||
PrimaryNames = \
|
||||
[ 'sender' , 'receivers'
|
||||
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
|
||||
, 'homeDir' , 'masterHost'
|
||||
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
|
||||
, 'rmSource' , 'rmBuild'
|
||||
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
|
||||
, 'success' , 'rcode'
|
||||
]
|
||||
SecondaryNames = \
|
||||
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'alcBin', 'ccbBin', 'benchsDir'
|
||||
]
|
||||
|
||||
def __init__ ( self ):
|
||||
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
|
||||
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
|
||||
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
|
||||
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
|
||||
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
|
||||
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
|
||||
self._homeDir = os.environ['HOME']
|
||||
self._debugArg = ''
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = True
|
||||
self._doCoriolis = False
|
||||
self._doAlliance = False
|
||||
self._doBenchs = False
|
||||
self._doSendReport = False
|
||||
self._nightlyMode = False
|
||||
self._dockerMode = False
|
||||
self._chrootMode = None
|
||||
self._logs = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._fds = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._ccbBin = None
|
||||
self._benchsDir = None
|
||||
self._masterHost = self._detectMasterHost()
|
||||
self._success = False
|
||||
self._rcode = 0
|
||||
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __setattr__ ( self, attribute, value ):
|
||||
if attribute in Configuration.SecondaryNames:
|
||||
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
|
||||
return
|
||||
|
||||
if attribute == 'masterHost' or attribute == '_masterHost':
|
||||
if value == 'lepka':
|
||||
print 'Never touch the Git tree when running on <lepka>.'
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = False
|
||||
self._doSendReport = False
|
||||
|
||||
if attribute[0] == '_':
|
||||
self.__dict__[attribute] = value
|
||||
return
|
||||
|
||||
if attribute == 'homeDir': value = os.path.expanduser(value)
|
||||
|
||||
self.__dict__['_'+attribute] = value
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __getattr__ ( self, attribute ):
|
||||
if attribute[0] != '_': attribute = '_'+attribute
|
||||
if not self.__dict__.has_key(attribute):
|
||||
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
|
||||
return self.__dict__[attribute]
|
||||
|
||||
def _updateSecondaries ( self ):
|
||||
if self._nightlyMode:
|
||||
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
|
||||
else:
|
||||
self._rootDir = self._homeDir + '/coriolis-2.x'
|
||||
self._srcDir = self._rootDir + '/src'
|
||||
self._logDir = self._srcDir + '/logs'
|
||||
self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
|
||||
self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
|
||||
self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
|
||||
self._masterHost = self._detectMasterHost()
|
||||
return
|
||||
|
||||
def _detectMasterHost ( self ):
|
||||
if self._chrootMode is None: return 'unknown'
|
||||
if self._chrootMode: return 'chrooted-host'
|
||||
|
||||
masterHost = 'unknown'
|
||||
hostname = socket.gethostname()
|
||||
hostAddr = socket.gethostbyname(hostname)
|
||||
|
||||
if hostname == 'lepka' and hostAddr == '127.0.0.1':
|
||||
masterHost = 'lepka'
|
||||
else:
|
||||
masterHost = hostname.split('.')[0]
|
||||
return masterHost
|
||||
|
||||
def openLog ( self, stem ):
|
||||
if not os.path.isdir(self._logDir):
|
||||
os.makedirs( self._logDir )
|
||||
|
||||
index = 0
|
||||
timeTag = time.strftime( "%Y.%m.%d" )
|
||||
while True:
|
||||
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
|
||||
if not os.path.isfile(logFile):
|
||||
print "Report log: <%s>" % logFile
|
||||
break
|
||||
index += 1
|
||||
fd = open( logFile, "w" )
|
||||
self._logs[stem] = logFile
|
||||
self._fds [stem] = fd
|
||||
return
|
||||
|
||||
def closeLogs ( self ):
|
||||
for fd in self._fds.values():
|
||||
if fd: fd.close()
|
||||
return
|
||||
|
||||
def compressLogs ( self ):
|
||||
for log in self._logs.values():
|
||||
if not log: continue
|
||||
|
||||
fd = open( log, 'r' )
|
||||
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
|
||||
|
||||
for line in fd.readlines(): bzfd.write( line )
|
||||
|
||||
bzfd.close()
|
||||
fd.close()
|
||||
|
||||
os.unlink( log )
|
||||
return
|
||||
|
||||
def getCommands ( self, target ):
|
||||
commands = []
|
||||
|
||||
if self.doAlliance:
|
||||
if not os.path.isfile( self.alcBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <allianceInstaller.sh>, should be here:'
|
||||
, ' <%s>' % self.alcBin
|
||||
] )
|
||||
commands.append( AllianceCommand( self.alcBin, fdLog=self.fds['alliance'] ) )
|
||||
|
||||
if self.doCoriolis:
|
||||
if not os.path.isfile( self.ccbBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
|
||||
, ' <%s>' % self.ccbBin
|
||||
] )
|
||||
|
||||
otherArgs = []
|
||||
if self.debugArg: otherArgs.append( self.debugArg )
|
||||
|
||||
if target == 'SL7_64':
|
||||
otherArgs.append( '--project=support' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'SL6_64' or target == 'SL6':
|
||||
otherArgs.append( '--project=support' )
|
||||
otherArgs.append( '--devtoolset=8' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 6, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'Ubuntu18' or target == 'Debian9':
|
||||
if target == 'Ubuntu18': otherArgs.append( '--qt5' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs, fdLog=self.fds['coriolis'] ) )
|
||||
|
||||
if self.doBenchs:
|
||||
commands.append( BenchsCommand( self.benchsDir, fdLog=self.fds['benchs'] ) )
|
||||
return commands
|
||||
|
||||
|
||||
class Report ( object ):
|
||||
|
||||
def __init__ ( self, conf ):
|
||||
self.conf = conf
|
||||
|
||||
commaspace = ', '
|
||||
date = time.strftime( "%A %d %B %Y" )
|
||||
stateText = 'FAILED'
|
||||
modeText = 'SoC installation'
|
||||
if self.conf.success: stateText = 'SUCCESS'
|
||||
if self.conf.nightlyMode: modeText = 'Nightly build'
|
||||
|
||||
self.message = MIMEMultipart()
|
||||
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
|
||||
self.message['From' ] = self.conf.sender
|
||||
self.message['To' ] = commaspace.join( self.conf.receivers )
|
||||
self.attachements = []
|
||||
|
||||
self.mainText = '\n'
|
||||
self.mainText += 'Salut le Crevard,\n'
|
||||
self.mainText += '\n'
|
||||
if self.conf.nightlyMode:
|
||||
self.mainText += 'This is the nightly build report of Coriolis.\n'
|
||||
else:
|
||||
self.mainText += 'SoC installer report of Coriolis.\n'
|
||||
self.mainText += '%s\n' % date
|
||||
self.mainText += '\n'
|
||||
if self.conf.success:
|
||||
self.mainText += 'Build was SUCCESSFUL\n'
|
||||
else:
|
||||
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
|
||||
self.mainText += '\n'
|
||||
self.mainText += 'Complete log file(s) can be found here:\n'
|
||||
return
|
||||
|
||||
def attachLog ( self, logFile ):
|
||||
if not logFile: return
|
||||
|
||||
fd = open( logFile, 'rb' )
|
||||
try:
|
||||
fd.seek( -1024*100, os.SEEK_END )
|
||||
except IOError, e:
|
||||
pass
|
||||
tailLines = ''
|
||||
for line in fd.readlines()[1:]:
|
||||
tailLines += line
|
||||
fd.close()
|
||||
self.mainText += ' <%s>\n' % logFile
|
||||
|
||||
attachement = MIMEApplication(tailLines)
|
||||
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
|
||||
|
||||
self.attachements.append( attachement )
|
||||
return
|
||||
|
||||
def send ( self ):
|
||||
self.message.attach( MIMEText(self.mainText) )
|
||||
for attachement in self.attachements:
|
||||
self.message.attach( attachement )
|
||||
|
||||
print "Sending mail report to:"
|
||||
for receiver in self.conf.receivers: print ' <%s>' % receiver
|
||||
session = smtplib.SMTP( 'localhost' )
|
||||
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
|
||||
session.quit()
|
||||
return
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# <socInstaller> Main Part.
|
||||
|
||||
|
||||
parser = optparse.OptionParser ()
|
||||
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." )
|
||||
parser.add_option ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
|
||||
parser.add_option ( "--do-alliance" , action="store_true" , dest="doAlliance" , help="Rebuild the Alliance tools." )
|
||||
parser.add_option ( "--do-coriolis" , action="store_true" , dest="doCoriolis" , help="Rebuild the Coriolis tools." )
|
||||
parser.add_option ( "--do-report" , action="store_true" , dest="doReport" , help="Send a final report." )
|
||||
parser.add_option ( "--nightly" , action="store_true" , dest="nightly" , help="Perform a nighly build." )
|
||||
parser.add_option ( "--docker" , action="store_true" , dest="docker" , help="Perform a build inside a docker container." )
|
||||
parser.add_option ( "--chroot" , action="store_true" , dest="chroot" , help="Perform a build inside a chrooted environment." )
|
||||
parser.add_option ( "--benchs" , action="store_true" , dest="benchs" , help="Run the <alliance-checker-toolkit> sanity benchs." )
|
||||
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove the build/install directories." )
|
||||
parser.add_option ( "--rm-source" , action="store_true" , dest="rmSource" , help="Remove the Git source repositories." )
|
||||
parser.add_option ( "--rm-all" , action="store_true" , dest="rmAll" , help="Remove everything (source+build+install)." )
|
||||
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" , help="The root directory (default: <~/coriolis-2.x/>)." )
|
||||
parser.add_option ( "--profile" , action="store" , type="string", dest="profile" , help="The targeted OS for the build." )
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
|
||||
conf = Configuration()
|
||||
|
||||
try:
|
||||
if options.debug: conf.debugArg = '--debug'
|
||||
if options.nightly: conf.nightlyMode = True
|
||||
if options.docker: conf.dockerMode = True
|
||||
if options.chroot: conf.chrootMode = True
|
||||
if options.noGit: conf.doGit = False
|
||||
if options.doCoriolis: conf.doCoriolis = True
|
||||
if options.doAlliance: conf.doAlliance = True
|
||||
if options.benchs: conf.doBenchs = True
|
||||
if options.doReport: conf.doSendReport = True
|
||||
if options.rmSource or options.rmAll: conf.rmSource = True
|
||||
if options.rmBuild or options.rmAll: conf.rmBuild = True
|
||||
|
||||
|
||||
if conf.doAlliance: conf.openLog( 'alliance' )
|
||||
if conf.doCoriolis: conf.openLog( 'coriolis' )
|
||||
if conf.doBenchs: conf.openLog( 'benchs' )
|
||||
|
||||
if conf.dockerMode: os.environ['USER'] = 'root'
|
||||
|
||||
gitSupports = []
|
||||
for supportRepo in conf.supportRepos:
|
||||
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
|
||||
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
|
||||
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
|
||||
|
||||
if conf.doAlliance:
|
||||
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
|
||||
|
||||
if conf.doGit:
|
||||
for gitSupport in gitSupports:
|
||||
if conf.rmSource: gitSupport.removeLocalRepo()
|
||||
gitSupport.clone()
|
||||
#if gitSupport.url.endswith('rapidjson'):
|
||||
# gitSupport.checkout( 'a1c4f32' )
|
||||
|
||||
if conf.doCoriolis:
|
||||
if conf.rmSource: gitCoriolis.removeLocalRepo()
|
||||
gitCoriolis.clone ()
|
||||
gitCoriolis.checkout( 'devel' )
|
||||
|
||||
if conf.doAlliance:
|
||||
if conf.rmSource: gitAlliance.removeLocalRepo()
|
||||
gitAlliance.clone ()
|
||||
#gitAlliance.checkout( 'devel' )
|
||||
|
||||
if conf.rmSource: gitBenchs.removeLocalRepo()
|
||||
gitBenchs.clone()
|
||||
|
||||
if conf.rmBuild:
|
||||
for entry in os.listdir(conf.rootDir):
|
||||
if entry.startswith('Linux.'):
|
||||
buildDir = conf.rootDir+'/'+entry
|
||||
print 'Removing OS build directory: <%s>' % buildDir
|
||||
shutil.rmtree( buildDir )
|
||||
|
||||
commands = conf.getCommands( options.profile )
|
||||
for command in commands:
|
||||
if command.host:
|
||||
print 'Executing command on remote host <%s>:' % host
|
||||
else:
|
||||
print 'Executing command on *local* host:'
|
||||
print ' %s' % str(command)
|
||||
command.execute()
|
||||
|
||||
conf.closeLogs()
|
||||
|
||||
conf.success = True
|
||||
|
||||
except ErrorMessage, e:
|
||||
print e
|
||||
conf.closeLogs()
|
||||
conf.success = False
|
||||
|
||||
if showTrace:
|
||||
print '\nPython stack trace:'
|
||||
traceback.print_tb( sys.exc_info()[2] )
|
||||
conf.rcode = e.code
|
||||
|
||||
if conf.doSendReport:
|
||||
report = Report( conf )
|
||||
report.attachLog( conf.logs['coriolis' ] )
|
||||
report.attachLog( conf.logs['benchs' ] )
|
||||
report.send()
|
||||
|
||||
conf.compressLogs()
|
||||
|
||||
sys.exit( conf.rcode )
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
FROM ununtu18.coriolis
|
||||
|
||||
COPY root/dot.bashrc /root/.bashrc
|
||||
|
||||
CMD [ "/bin/bash", "-i" ]
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
FROM ubuntu18.system
|
||||
|
||||
COPY root/socInstaller.py /root/socInstaller.py
|
||||
RUN mkdir -p coriolis-2.x/src \
|
||||
&& git clone https://github.com/m-labs/nmigen.git \
|
||||
&& cd nmigen \
|
||||
&& python3 setup.py develop \
|
||||
&& /root/socInstaller.py --docker --profile=Ubuntu18 --do-alliance --do-coriolis --benchs
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
FROM ubuntu:bionic
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get -y install build-essential binutils-dev \
|
||||
git cmake bison flex gcc python-dev \
|
||||
libboost-all-dev libboost-python-dev \
|
||||
zlib1g-dev libxml2-dev rapidjson-dev libbz2-dev \
|
||||
qtbase5-dev libqt5svg5-dev libqwt-qt5-dev \
|
||||
python-pyqt5 \
|
||||
\
|
||||
autotools-dev automake \
|
||||
libxt-dev libxpm-dev libmotif-dev \
|
||||
\
|
||||
yosys \
|
||||
python3-setuptools python3-pip python3-six \
|
||||
python3-wheel \
|
||||
\
|
||||
vim \
|
||||
&& apt-get clean \
|
||||
&& pip3 install git+https://github.com/m-labs/nmigen.git
|
||||
|
||||
# For building with Qt 4 instead of Qt 5.
|
||||
# qt4-dev-tools libqwt-dev python-qt4 \
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
systemImage="ubuntu18.system"
|
||||
coriolisImage="ubuntu18.coriolis"
|
||||
bashImage="ubuntu18.bash"
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
|
||||
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
|
||||
buildDir=${commonRoot}/build
|
||||
installDir=${commonRoot}/install
|
||||
|
||||
export ALLIANCE_TOP=${installDir}
|
||||
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
cd ${srcDir}
|
||||
# Skip doc generation to avoid pulling TeXLive in docker images.
|
||||
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
|
||||
./autostuff clean
|
||||
./autostuff
|
||||
mkdir -p ${buildDir}
|
||||
cd ${buildDir}
|
||||
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
|
||||
make -j1 install
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
echo "Running /root/.bashrc"
|
||||
|
||||
for archDir in `ls /root/coriolis-2.x/`; do
|
||||
if [ "$archDir" = "src" ]; then continue; fi
|
||||
break
|
||||
done
|
||||
echo "Found Coriolis architecture directory \"${archDir}\"."
|
||||
|
||||
installDir="/root/coriolis-2.x/${archDir}/Release.Shared/install"
|
||||
. ${installDir}/etc/profile.d/alc_env.sh
|
||||
eval `${installDir}/etc/coriolis2/coriolisEnv.py`
|
||||
|
||||
export QT_X11_NO_MITSHM=1
|
|
@ -0,0 +1,631 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# -*- mode:Python -*-
|
||||
#
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) UPMC 2015-2018, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C o r i o l i s I n s t a l l e r |
|
||||
# | |
|
||||
# | Authors : Jean-Paul Chaput |
|
||||
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./socInstaller.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
#
|
||||
# WARNING:
|
||||
# This script has been designed only for internal use in the
|
||||
# LIP6/CIAN department. If you want to use it you will need to
|
||||
# change the hardwired configuration.
|
||||
|
||||
|
||||
showTrace = True
|
||||
|
||||
try:
|
||||
import sys
|
||||
import os.path
|
||||
import shutil
|
||||
import optparse
|
||||
import time
|
||||
import traceback
|
||||
import distutils.sysconfig
|
||||
import subprocess
|
||||
import socket
|
||||
import re
|
||||
import bz2
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
except ImportError, e:
|
||||
module = str(e).split()[-1]
|
||||
|
||||
|
||||
class ErrorMessage ( Exception ):
|
||||
|
||||
def __init__ ( self, code, *arguments ):
|
||||
self._code = code
|
||||
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
|
||||
|
||||
text = None
|
||||
if len(arguments) == 1:
|
||||
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
|
||||
else:
|
||||
self._errors = arguments[0]
|
||||
elif len(arguments) > 1:
|
||||
text = list(arguments)
|
||||
|
||||
if text:
|
||||
self._errors = []
|
||||
while len(text[0]) == 0: del text[0]
|
||||
|
||||
lstrip = 0
|
||||
if text[0].startswith('[ERROR]'): lstrip = 8
|
||||
|
||||
for line in text:
|
||||
if line[0:lstrip ] == ' '*lstrip or \
|
||||
line[0:lstrip-1] == '[ERROR]':
|
||||
self._errors += [ line[lstrip:] ]
|
||||
else:
|
||||
self._errors += [ line.lstrip() ]
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
if not isinstance(self._errors,list):
|
||||
return "[ERROR] %s" % self._errors
|
||||
|
||||
formatted = "\n"
|
||||
for i in range(len(self._errors)):
|
||||
if i == 0: formatted += "[ERROR] %s" % self._errors[i]
|
||||
else: formatted += " %s" % self._errors[i]
|
||||
if i+1 < len(self._errors): formatted += "\n"
|
||||
return formatted
|
||||
|
||||
def addMessage ( self, message ):
|
||||
if not isinstance(self._errors,list):
|
||||
self._errors = [ self._errors ]
|
||||
if isinstance(message,list):
|
||||
for line in message:
|
||||
self._errors += [ line ]
|
||||
else:
|
||||
self._errors += [ message ]
|
||||
return
|
||||
|
||||
def terminate ( self ):
|
||||
print self
|
||||
sys.exit(self._code)
|
||||
|
||||
@property
|
||||
def code ( self ): return self._code
|
||||
|
||||
|
||||
class BadBinary ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, binary ):
|
||||
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
|
||||
return
|
||||
|
||||
|
||||
class BadReturnCode ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, status ):
|
||||
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
|
||||
return
|
||||
|
||||
|
||||
class Command ( object ):
|
||||
|
||||
def __init__ ( self, arguments, fdLog=None ):
|
||||
self.arguments = arguments
|
||||
self.fdLog = fdLog
|
||||
|
||||
if self.fdLog != None and not isinstance(self.fdLog,file):
|
||||
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
|
||||
return
|
||||
|
||||
def _argumentsToStr ( self, arguments ):
|
||||
s = ''
|
||||
for argument in arguments:
|
||||
if argument.find(' ') >= 0: s += ' "' + argument + '"'
|
||||
else: s += ' ' + argument
|
||||
return s
|
||||
|
||||
def log ( self, text ):
|
||||
print text[:-1]
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
if isinstance(self.fdLog,file):
|
||||
self.fdLog.write( text )
|
||||
self.fdLog.flush()
|
||||
return
|
||||
|
||||
def execute ( self ):
|
||||
global conf
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
homeDir = os.environ['HOME']
|
||||
workDir = os.getcwd()
|
||||
if homeDir.startswith(homeDir):
|
||||
workDir = '~' + workDir[ len(homeDir) : ]
|
||||
user = 'root'
|
||||
if os.environ.has_key('USER'): user = os.environ['USER']
|
||||
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
|
||||
|
||||
try:
|
||||
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
|
||||
print self.arguments
|
||||
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
|
||||
while True:
|
||||
line = child.stdout.readline()
|
||||
if not line: break
|
||||
|
||||
self.log( line )
|
||||
except OSError, e:
|
||||
raise BadBinary( self.arguments[0] )
|
||||
|
||||
(pid,status) = os.waitpid( child.pid, 0 )
|
||||
status >>= 8
|
||||
if status != 0:
|
||||
raise BadReturnCode( status )
|
||||
|
||||
return
|
||||
|
||||
|
||||
class CommandArg ( object ):
|
||||
|
||||
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
|
||||
self.command = command
|
||||
self.host = host
|
||||
self.wd = wd
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
s = ''
|
||||
if self.wd: s = 'cd %s && ' % self.wd
|
||||
|
||||
for i in range(len(self.command)):
|
||||
if i: s += ' '
|
||||
s += self.command[i]
|
||||
return s
|
||||
|
||||
def getArgs ( self ):
|
||||
if not self.host: return self.command
|
||||
return [ 'ssh', self.host, str(self) ]
|
||||
|
||||
def execute ( self ):
|
||||
if not self.host and self.wd: os.chdir( self.wd )
|
||||
Command( self.getArgs(), self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class AllianceCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, alcBin, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ alcBin ], fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class CoriolisCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, ccbBin, rootDir, threads=1, otherArgs=[], fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ ccbBin
|
||||
, '--root='+rootDir
|
||||
, '--project=coriolis'
|
||||
, '--make=-j%d install' % threads
|
||||
] + otherArgs
|
||||
, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class BenchsCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, benchsDir, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ '../bin/go.sh' ], wd=benchsDir, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
|
||||
class GitRepository ( object ):
|
||||
|
||||
@staticmethod
|
||||
def getLocalRepository ( url ):
|
||||
localRepo = url.split( '/' )[-1]
|
||||
if localRepo.endswith('.git'):
|
||||
localRepo = localRepo[:-4]
|
||||
return localRepo
|
||||
|
||||
def __init__ ( self, url, cloneDir, fdLog=None ):
|
||||
self.url = url
|
||||
self.cloneDir = cloneDir
|
||||
self.localRepo = GitRepository.getLocalRepository( url )
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
@property
|
||||
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
|
||||
|
||||
def removeLocalRepo ( self ):
|
||||
if os.path.isdir(self.localRepoDir):
|
||||
print 'Removing Git local repository: <%s>' % self.localRepoDir
|
||||
shutil.rmtree( self.localRepoDir )
|
||||
return
|
||||
|
||||
def clone ( self ):
|
||||
print 'Clone/pull from:', self.url
|
||||
if not os.path.isdir(self.cloneDir):
|
||||
os.makedirs( self.cloneDir )
|
||||
|
||||
if not os.path.isdir(self.localRepoDir):
|
||||
os.chdir( self.cloneDir )
|
||||
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
|
||||
else:
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'pull' ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
def checkout ( self, branch ):
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class Configuration ( object ):
|
||||
|
||||
PrimaryNames = \
|
||||
[ 'sender' , 'receivers'
|
||||
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
|
||||
, 'homeDir' , 'masterHost'
|
||||
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
|
||||
, 'rmSource' , 'rmBuild'
|
||||
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
|
||||
, 'success' , 'rcode'
|
||||
]
|
||||
SecondaryNames = \
|
||||
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'alcBin', 'ccbBin', 'benchsDir'
|
||||
]
|
||||
|
||||
def __init__ ( self ):
|
||||
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
|
||||
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
|
||||
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
|
||||
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
|
||||
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
|
||||
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
|
||||
self._homeDir = os.environ['HOME']
|
||||
self._debugArg = ''
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = True
|
||||
self._doCoriolis = False
|
||||
self._doAlliance = False
|
||||
self._doBenchs = False
|
||||
self._doSendReport = False
|
||||
self._nightlyMode = False
|
||||
self._dockerMode = False
|
||||
self._chrootMode = None
|
||||
self._logs = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._fds = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._ccbBin = None
|
||||
self._benchsDir = None
|
||||
self._masterHost = self._detectMasterHost()
|
||||
self._success = False
|
||||
self._rcode = 0
|
||||
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __setattr__ ( self, attribute, value ):
|
||||
if attribute in Configuration.SecondaryNames:
|
||||
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
|
||||
return
|
||||
|
||||
if attribute == 'masterHost' or attribute == '_masterHost':
|
||||
if value == 'lepka':
|
||||
print 'Never touch the Git tree when running on <lepka>.'
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = False
|
||||
self._doSendReport = False
|
||||
|
||||
if attribute[0] == '_':
|
||||
self.__dict__[attribute] = value
|
||||
return
|
||||
|
||||
if attribute == 'homeDir': value = os.path.expanduser(value)
|
||||
|
||||
self.__dict__['_'+attribute] = value
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __getattr__ ( self, attribute ):
|
||||
if attribute[0] != '_': attribute = '_'+attribute
|
||||
if not self.__dict__.has_key(attribute):
|
||||
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
|
||||
return self.__dict__[attribute]
|
||||
|
||||
def _updateSecondaries ( self ):
|
||||
if self._nightlyMode:
|
||||
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
|
||||
else:
|
||||
self._rootDir = self._homeDir + '/coriolis-2.x'
|
||||
self._srcDir = self._rootDir + '/src'
|
||||
self._logDir = self._srcDir + '/logs'
|
||||
self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
|
||||
self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
|
||||
self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
|
||||
self._masterHost = self._detectMasterHost()
|
||||
return
|
||||
|
||||
def _detectMasterHost ( self ):
|
||||
if self._chrootMode is None: return 'unknown'
|
||||
if self._chrootMode: return 'chrooted-host'
|
||||
|
||||
masterHost = 'unknown'
|
||||
hostname = socket.gethostname()
|
||||
hostAddr = socket.gethostbyname(hostname)
|
||||
|
||||
if hostname == 'lepka' and hostAddr == '127.0.0.1':
|
||||
masterHost = 'lepka'
|
||||
else:
|
||||
masterHost = hostname.split('.')[0]
|
||||
return masterHost
|
||||
|
||||
def openLog ( self, stem ):
|
||||
if not os.path.isdir(self._logDir):
|
||||
os.makedirs( self._logDir )
|
||||
|
||||
index = 0
|
||||
timeTag = time.strftime( "%Y.%m.%d" )
|
||||
while True:
|
||||
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
|
||||
if not os.path.isfile(logFile):
|
||||
print "Report log: <%s>" % logFile
|
||||
break
|
||||
index += 1
|
||||
fd = open( logFile, "w" )
|
||||
self._logs[stem] = logFile
|
||||
self._fds [stem] = fd
|
||||
return
|
||||
|
||||
def closeLogs ( self ):
|
||||
for fd in self._fds.values():
|
||||
if fd: fd.close()
|
||||
return
|
||||
|
||||
def compressLogs ( self ):
|
||||
for log in self._logs.values():
|
||||
if not log: continue
|
||||
|
||||
fd = open( log, 'r' )
|
||||
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
|
||||
|
||||
for line in fd.readlines(): bzfd.write( line )
|
||||
|
||||
bzfd.close()
|
||||
fd.close()
|
||||
|
||||
os.unlink( log )
|
||||
return
|
||||
|
||||
def getCommands ( self, target ):
|
||||
commands = []
|
||||
|
||||
if self.doAlliance:
|
||||
if not os.path.isfile( self.alcBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <allianceInstaller.sh>, should be here:'
|
||||
, ' <%s>' % self.alcBin
|
||||
] )
|
||||
commands.append( AllianceCommand( self.alcBin, fdLog=self.fds['alliance'] ) )
|
||||
|
||||
if self.doCoriolis:
|
||||
if not os.path.isfile( self.ccbBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
|
||||
, ' <%s>' % self.ccbBin
|
||||
] )
|
||||
|
||||
otherArgs = []
|
||||
if self.debugArg: otherArgs.append( self.debugArg )
|
||||
|
||||
if target == 'SL7_64':
|
||||
otherArgs.append( '--project=support' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'SL6_64' or target == 'SL6':
|
||||
otherArgs.append( '--project=support' )
|
||||
otherArgs.append( '--devtoolset=8' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 6, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'Ubuntu18' or target == 'Debian9':
|
||||
if target == 'Ubuntu18': otherArgs.append( '--qt5' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs, fdLog=self.fds['coriolis'] ) )
|
||||
|
||||
if self.doBenchs:
|
||||
commands.append( BenchsCommand( self.benchsDir, fdLog=self.fds['benchs'] ) )
|
||||
return commands
|
||||
|
||||
|
||||
class Report ( object ):
|
||||
|
||||
def __init__ ( self, conf ):
|
||||
self.conf = conf
|
||||
|
||||
commaspace = ', '
|
||||
date = time.strftime( "%A %d %B %Y" )
|
||||
stateText = 'FAILED'
|
||||
modeText = 'SoC installation'
|
||||
if self.conf.success: stateText = 'SUCCESS'
|
||||
if self.conf.nightlyMode: modeText = 'Nightly build'
|
||||
|
||||
self.message = MIMEMultipart()
|
||||
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
|
||||
self.message['From' ] = self.conf.sender
|
||||
self.message['To' ] = commaspace.join( self.conf.receivers )
|
||||
self.attachements = []
|
||||
|
||||
self.mainText = '\n'
|
||||
self.mainText += 'Salut le Crevard,\n'
|
||||
self.mainText += '\n'
|
||||
if self.conf.nightlyMode:
|
||||
self.mainText += 'This is the nightly build report of Coriolis.\n'
|
||||
else:
|
||||
self.mainText += 'SoC installer report of Coriolis.\n'
|
||||
self.mainText += '%s\n' % date
|
||||
self.mainText += '\n'
|
||||
if self.conf.success:
|
||||
self.mainText += 'Build was SUCCESSFUL\n'
|
||||
else:
|
||||
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
|
||||
self.mainText += '\n'
|
||||
self.mainText += 'Complete log file(s) can be found here:\n'
|
||||
return
|
||||
|
||||
def attachLog ( self, logFile ):
|
||||
if not logFile: return
|
||||
|
||||
fd = open( logFile, 'rb' )
|
||||
try:
|
||||
fd.seek( -1024*100, os.SEEK_END )
|
||||
except IOError, e:
|
||||
pass
|
||||
tailLines = ''
|
||||
for line in fd.readlines()[1:]:
|
||||
tailLines += line
|
||||
fd.close()
|
||||
self.mainText += ' <%s>\n' % logFile
|
||||
|
||||
attachement = MIMEApplication(tailLines)
|
||||
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
|
||||
|
||||
self.attachements.append( attachement )
|
||||
return
|
||||
|
||||
def send ( self ):
|
||||
self.message.attach( MIMEText(self.mainText) )
|
||||
for attachement in self.attachements:
|
||||
self.message.attach( attachement )
|
||||
|
||||
print "Sending mail report to:"
|
||||
for receiver in self.conf.receivers: print ' <%s>' % receiver
|
||||
session = smtplib.SMTP( 'localhost' )
|
||||
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
|
||||
session.quit()
|
||||
return
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# <socInstaller> Main Part.
|
||||
|
||||
|
||||
parser = optparse.OptionParser ()
|
||||
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." )
|
||||
parser.add_option ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
|
||||
parser.add_option ( "--do-alliance" , action="store_true" , dest="doAlliance" , help="Rebuild the Alliance tools." )
|
||||
parser.add_option ( "--do-coriolis" , action="store_true" , dest="doCoriolis" , help="Rebuild the Coriolis tools." )
|
||||
parser.add_option ( "--do-report" , action="store_true" , dest="doReport" , help="Send a final report." )
|
||||
parser.add_option ( "--nightly" , action="store_true" , dest="nightly" , help="Perform a nighly build." )
|
||||
parser.add_option ( "--docker" , action="store_true" , dest="docker" , help="Perform a build inside a docker container." )
|
||||
parser.add_option ( "--chroot" , action="store_true" , dest="chroot" , help="Perform a build inside a chrooted environment." )
|
||||
parser.add_option ( "--benchs" , action="store_true" , dest="benchs" , help="Run the <alliance-checker-toolkit> sanity benchs." )
|
||||
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove the build/install directories." )
|
||||
parser.add_option ( "--rm-source" , action="store_true" , dest="rmSource" , help="Remove the Git source repositories." )
|
||||
parser.add_option ( "--rm-all" , action="store_true" , dest="rmAll" , help="Remove everything (source+build+install)." )
|
||||
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" , help="The root directory (default: <~/coriolis-2.x/>)." )
|
||||
parser.add_option ( "--profile" , action="store" , type="string", dest="profile" , help="The targeted OS for the build." )
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
|
||||
conf = Configuration()
|
||||
|
||||
try:
|
||||
if options.debug: conf.debugArg = '--debug'
|
||||
if options.nightly: conf.nightlyMode = True
|
||||
if options.docker: conf.dockerMode = True
|
||||
if options.chroot: conf.chrootMode = True
|
||||
if options.noGit: conf.doGit = False
|
||||
if options.doCoriolis: conf.doCoriolis = True
|
||||
if options.doAlliance: conf.doAlliance = True
|
||||
if options.benchs: conf.doBenchs = True
|
||||
if options.doReport: conf.doSendReport = True
|
||||
if options.rmSource or options.rmAll: conf.rmSource = True
|
||||
if options.rmBuild or options.rmAll: conf.rmBuild = True
|
||||
|
||||
|
||||
if conf.doAlliance: conf.openLog( 'alliance' )
|
||||
if conf.doCoriolis: conf.openLog( 'coriolis' )
|
||||
if conf.doBenchs: conf.openLog( 'benchs' )
|
||||
|
||||
if conf.dockerMode: os.environ['USER'] = 'root'
|
||||
|
||||
gitSupports = []
|
||||
for supportRepo in conf.supportRepos:
|
||||
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
|
||||
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
|
||||
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
|
||||
|
||||
if conf.doAlliance:
|
||||
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
|
||||
|
||||
if conf.doGit:
|
||||
for gitSupport in gitSupports:
|
||||
if conf.rmSource: gitSupport.removeLocalRepo()
|
||||
gitSupport.clone()
|
||||
#if gitSupport.url.endswith('rapidjson'):
|
||||
# gitSupport.checkout( 'a1c4f32' )
|
||||
|
||||
if conf.doCoriolis:
|
||||
if conf.rmSource: gitCoriolis.removeLocalRepo()
|
||||
gitCoriolis.clone ()
|
||||
gitCoriolis.checkout( 'devel' )
|
||||
|
||||
if conf.doAlliance:
|
||||
if conf.rmSource: gitAlliance.removeLocalRepo()
|
||||
gitAlliance.clone ()
|
||||
#gitAlliance.checkout( 'devel' )
|
||||
|
||||
if conf.rmSource: gitBenchs.removeLocalRepo()
|
||||
gitBenchs.clone()
|
||||
|
||||
if conf.rmBuild:
|
||||
for entry in os.listdir(conf.rootDir):
|
||||
if entry.startswith('Linux.'):
|
||||
buildDir = conf.rootDir+'/'+entry
|
||||
print 'Removing OS build directory: <%s>' % buildDir
|
||||
shutil.rmtree( buildDir )
|
||||
|
||||
commands = conf.getCommands( options.profile )
|
||||
for command in commands:
|
||||
if command.host:
|
||||
print 'Executing command on remote host <%s>:' % host
|
||||
else:
|
||||
print 'Executing command on *local* host:'
|
||||
print ' %s' % str(command)
|
||||
command.execute()
|
||||
|
||||
conf.closeLogs()
|
||||
|
||||
conf.success = True
|
||||
|
||||
except ErrorMessage, e:
|
||||
print e
|
||||
conf.closeLogs()
|
||||
conf.success = False
|
||||
|
||||
if showTrace:
|
||||
print '\nPython stack trace:'
|
||||
traceback.print_tb( sys.exc_info()[2] )
|
||||
conf.rcode = e.code
|
||||
|
||||
if conf.doSendReport:
|
||||
report = Report( conf )
|
||||
report.attachLog( conf.logs['coriolis' ] )
|
||||
report.attachLog( conf.logs['benchs' ] )
|
||||
report.send()
|
||||
|
||||
conf.compressLogs()
|
||||
|
||||
sys.exit( conf.rcode )
|
|
@ -0,0 +1,133 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
showHelp=0
|
||||
showError=0
|
||||
doBuildSystem=0
|
||||
doBuildCoriolis=0
|
||||
doBuildBash=0
|
||||
doBuild=0
|
||||
doRun=0
|
||||
doRemove=0
|
||||
|
||||
|
||||
if [ ! -f "./docker-conf.sh" ]; then
|
||||
echo "[ERROR] Missing \"./docker-conf.sh\"."
|
||||
echo " (wd:\"`pwd`\")"
|
||||
exit 1
|
||||
fi
|
||||
. "./docker-conf.sh"
|
||||
dockerImages="${systemImage},${coriolisImage},${bashImage}"
|
||||
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--help) showHelp=1;;
|
||||
--build-system) doBuildSystem=1;;
|
||||
--build-coriolis) doBuildCoriolis=1;;
|
||||
--build-bash) doBuildBash=1;;
|
||||
--run) doRun=1;;
|
||||
--remove) doRemove=1;;
|
||||
-*) NB=2; CH=`echo $1 | cut -c$NB`
|
||||
while [ "$CH" != "" ]; do
|
||||
case $CH in
|
||||
h) showHelp=1;;
|
||||
s) doBuildSystem=1;;
|
||||
c) doBuildCoriolis=1;;
|
||||
b) doBuildBash=1;;
|
||||
r) doRun=1;;
|
||||
*) showError=1; badOption="$1";;
|
||||
esac
|
||||
NB=`expr $NB + 1`
|
||||
CH=`echo $1 | cut -c$NB`
|
||||
done;;
|
||||
*) showError=1; badOption="$1";;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ ${showError} -ne 0 ]; then
|
||||
echo "[ERROR] Unknown argument \"${badOption}\"."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ${showHelp} -ne 0 ]; then
|
||||
echo "Usage: ./manager.sh [options]"
|
||||
echo "Options:"
|
||||
echo " * [-h|--help]: Print this help."
|
||||
echo " * [-s|--build-system]: Rebuild the whole OS image."
|
||||
echo " * [-c|--build-coriolis]: Rebuild the Coriolis image. It will remove the previous"
|
||||
echo " images (${dockerImages})."
|
||||
echo " * [-b|--build-bash]: Rebuild the Bash (shell) image. It will remove the previous"
|
||||
echo " image (${bashImage})."
|
||||
echo " * [-r|--run]: Recompile Alliance, Coriolis & perform benchs."
|
||||
echo " * [--remove]: Remove container(s) & image(s)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [ ${doBuildSystem} -ne 0 ]; then
|
||||
doBuildBash=1
|
||||
doBuildCoriolis=1
|
||||
doBuild=1
|
||||
doRemove=1
|
||||
fi
|
||||
|
||||
if [ ${doBuildCoriolis} -ne 0 ]; then
|
||||
doBuildBash=1
|
||||
doBuild=1
|
||||
doRemove=1
|
||||
fi
|
||||
|
||||
if [ ${doBuildBash} -ne 0 ]; then
|
||||
doBuild=1
|
||||
doRemove=1
|
||||
fi
|
||||
|
||||
|
||||
if [ ${doRemove} -ne 0 ]; then
|
||||
if [ ${doBuildBash} -ne 0 ]; then
|
||||
echo "Removing \"${bashImage}\" docker container."
|
||||
docker rm ${bashImage}
|
||||
docker rmi ${bashImage}
|
||||
fi
|
||||
|
||||
if [ ${doBuildCoriolis} -ne 0 ]; then
|
||||
echo "Removing \"${coriolisImage}\" docker image."
|
||||
docker rm ${coriolisImage}
|
||||
docker rmi ${coriolisImage}
|
||||
fi
|
||||
|
||||
if [ ${doBuildSystem} -ne 0 ]; then
|
||||
echo "Removing \"${systemImage}\" docker image."
|
||||
docker rm ${systemImage}
|
||||
docker rmi ${systemImage}
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ ${doBuild} -ne 0 ]; then
|
||||
echo "Synching Alliance & Coriolis builder scripts."
|
||||
cp ../../socInstaller.py ./root
|
||||
cp ../../dot.bashrc ./root
|
||||
|
||||
if [ ${doBuildSystem} -ne 0 ]; then
|
||||
echo "Build \"${systemImage}\" docker image."
|
||||
docker build -f Dockerfile.system -t ${systemImage} .
|
||||
fi
|
||||
|
||||
if [ ${doBuildCoriolis} -ne 0 ]; then
|
||||
echo "Build \"${coriolisImage}\" docker image."
|
||||
docker build -f Dockerfile.coriolis -t ${coriolisImage} .
|
||||
fi
|
||||
|
||||
if [ ${doBuildCoriolis} -ne 0 ]; then
|
||||
echo "Build \"${bashImage}\" docker image."
|
||||
docker build -f Dockerfile.bash -t ${bashImage} .
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ ${doRun} -ne 0 ]; then
|
||||
docker run --rm --net=host -e DISPLAY=:0 -ti --name ${bashImage} ${bashImage}
|
||||
fi
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
echo "Running /root/.bashrc"
|
||||
|
||||
for archDir in `ls /root/coriolis-2.x/`; do
|
||||
if [ "$archDir" = "src" ]; then continue; fi
|
||||
break
|
||||
done
|
||||
echo "Found Coriolis architecture directory \"${archDir}\"."
|
||||
|
||||
installDir="/root/coriolis-2.x/${archDir}/Release.Shared/install"
|
||||
. ${installDir}/etc/profile.d/alc_env.sh
|
||||
eval `${installDir}/etc/coriolis2/coriolisEnv.py`
|
||||
|
||||
export QT_X11_NO_MITSHM=1
|
|
@ -46,31 +46,31 @@ except ImportError, e:
|
|||
class ErrorMessage ( Exception ):
|
||||
|
||||
def __init__ ( self, code, *arguments ):
|
||||
self._code = code
|
||||
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
|
||||
|
||||
text = None
|
||||
if len(arguments) == 1:
|
||||
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
|
||||
else:
|
||||
self._errors = arguments[0]
|
||||
elif len(arguments) > 1:
|
||||
text = list(arguments)
|
||||
|
||||
if text:
|
||||
self._errors = []
|
||||
while len(text[0]) == 0: del text[0]
|
||||
|
||||
lstrip = 0
|
||||
if text[0].startswith('[ERROR]'): lstrip = 8
|
||||
|
||||
for line in text:
|
||||
if line[0:lstrip ] == ' '*lstrip or \
|
||||
line[0:lstrip-1] == '[ERROR]':
|
||||
self._errors += [ line[lstrip:] ]
|
||||
self._code = code
|
||||
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
|
||||
|
||||
text = None
|
||||
if len(arguments) == 1:
|
||||
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
|
||||
else:
|
||||
self._errors += [ line.lstrip() ]
|
||||
return
|
||||
self._errors = arguments[0]
|
||||
elif len(arguments) > 1:
|
||||
text = list(arguments)
|
||||
|
||||
if text:
|
||||
self._errors = []
|
||||
while len(text[0]) == 0: del text[0]
|
||||
|
||||
lstrip = 0
|
||||
if text[0].startswith('[ERROR]'): lstrip = 8
|
||||
|
||||
for line in text:
|
||||
if line[0:lstrip ] == ' '*lstrip or \
|
||||
line[0:lstrip-1] == '[ERROR]':
|
||||
self._errors += [ line[lstrip:] ]
|
||||
else:
|
||||
self._errors += [ line.lstrip() ]
|
||||
return
|
||||
|
||||
def __str__ ( self ):
|
||||
if not isinstance(self._errors,list):
|
||||
|
@ -104,321 +104,417 @@ class ErrorMessage ( Exception ):
|
|||
class BadBinary ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, binary ):
|
||||
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
|
||||
return
|
||||
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
|
||||
return
|
||||
|
||||
|
||||
class BadReturnCode ( ErrorMessage ):
|
||||
|
||||
def __init__ ( self, status ):
|
||||
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
|
||||
return
|
||||
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
|
||||
return
|
||||
|
||||
|
||||
class Command ( object ):
|
||||
|
||||
def __init__ ( self, arguments, fdLog=None ):
|
||||
self.arguments = arguments
|
||||
self.fdLog = fdLog
|
||||
|
||||
if self.fdLog != None and not isinstance(self.fdLog,file):
|
||||
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
|
||||
return
|
||||
self.arguments = arguments
|
||||
self.fdLog = fdLog
|
||||
|
||||
if self.fdLog != None and not isinstance(self.fdLog,file):
|
||||
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
|
||||
return
|
||||
|
||||
def _argumentsToStr ( self, arguments ):
|
||||
s = ''
|
||||
for argument in arguments:
|
||||
if argument.find(' ') >= 0: s += ' "' + argument + '"'
|
||||
else: s += ' ' + argument
|
||||
return s
|
||||
s = ''
|
||||
for argument in arguments:
|
||||
if argument.find(' ') >= 0: s += ' "' + argument + '"'
|
||||
else: s += ' ' + argument
|
||||
return s
|
||||
|
||||
def log ( self, text ):
|
||||
print text[:-1]
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
if isinstance(self.fdLog,file):
|
||||
self.fdLog.write( text )
|
||||
self.fdLog.flush()
|
||||
return
|
||||
print text[:-1]
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
if isinstance(self.fdLog,file):
|
||||
self.fdLog.write( text )
|
||||
self.fdLog.flush()
|
||||
return
|
||||
|
||||
def execute ( self ):
|
||||
global conf
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
global conf
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
homeDir = os.environ['HOME']
|
||||
workDir = os.getcwd()
|
||||
if homeDir.startswith(homeDir):
|
||||
workDir = '~' + workDir[ len(homeDir) : ]
|
||||
user = 'root'
|
||||
if os.environ.has_key('USER'): user = os.environ['USER']
|
||||
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
|
||||
|
||||
try:
|
||||
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
|
||||
print self.arguments
|
||||
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
|
||||
while True:
|
||||
line = child.stdout.readline()
|
||||
if not line: break
|
||||
|
||||
self.log( line )
|
||||
except OSError, e:
|
||||
raise BadBinary( self.arguments[0] )
|
||||
|
||||
(pid,status) = os.waitpid( child.pid, 0 )
|
||||
status >>= 8
|
||||
if status != 0:
|
||||
raise BadReturnCode( status )
|
||||
|
||||
return
|
||||
|
||||
homeDir = os.environ['HOME']
|
||||
workDir = os.getcwd()
|
||||
if homeDir.startswith(homeDir):
|
||||
workDir = '~' + workDir[ len(homeDir) : ]
|
||||
prompt = '%s@%s:%s$' % (os.environ['USER'],conf.masterHost,workDir)
|
||||
|
||||
try:
|
||||
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
|
||||
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
class CommandArg ( object ):
|
||||
|
||||
while True:
|
||||
line = child.stdout.readline()
|
||||
if not line: break
|
||||
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
|
||||
self.command = command
|
||||
self.host = host
|
||||
self.wd = wd
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
self.log( line )
|
||||
except OSError, e:
|
||||
raise BadBinary( self.arguments[0] )
|
||||
def __str__ ( self ):
|
||||
s = ''
|
||||
if self.wd: s = 'cd %s && ' % self.wd
|
||||
|
||||
(pid,status) = os.waitpid( child.pid, 0 )
|
||||
status >>= 8
|
||||
if status != 0:
|
||||
raise BadReturnCode( status )
|
||||
for i in range(len(self.command)):
|
||||
if i: s += ' '
|
||||
s += self.command[i]
|
||||
return s
|
||||
|
||||
return
|
||||
def getArgs ( self ):
|
||||
if not self.host: return self.command
|
||||
return [ 'ssh', self.host, str(self) ]
|
||||
|
||||
def execute ( self ):
|
||||
if not self.host and self.wd: os.chdir( self.wd )
|
||||
Command( self.getArgs(), self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class AllianceCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, alcBin, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ alcBin ], fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class CoriolisCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, ccbBin, rootDir, threads=1, otherArgs=[], fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ ccbBin
|
||||
, '--root='+rootDir
|
||||
, '--project=coriolis'
|
||||
, '--make=-j%d install' % threads
|
||||
] + otherArgs
|
||||
, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
class BenchsCommand ( CommandArg ):
|
||||
|
||||
def __init__ ( self, benchsDir, fdLog=None ):
|
||||
CommandArg.__init__ ( self, [ '../bin/go.sh' ], wd=benchsDir, fdLog=fdLog )
|
||||
return
|
||||
|
||||
|
||||
|
||||
class GitRepository ( object ):
|
||||
|
||||
@staticmethod
|
||||
def getLocalRepository ( url ):
|
||||
localRepo = url.split( '/' )[-1]
|
||||
if localRepo.endswith('.git'):
|
||||
localRepo = localRepo[:-4]
|
||||
return localRepo
|
||||
localRepo = url.split( '/' )[-1]
|
||||
if localRepo.endswith('.git'):
|
||||
localRepo = localRepo[:-4]
|
||||
return localRepo
|
||||
|
||||
def __init__ ( self, url, cloneDir, fdLog=None ):
|
||||
self.url = url
|
||||
self.cloneDir = cloneDir
|
||||
self.localRepo = GitRepository.getLocalRepository( url )
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
self.url = url
|
||||
self.cloneDir = cloneDir
|
||||
self.localRepo = GitRepository.getLocalRepository( url )
|
||||
self.fdLog = fdLog
|
||||
return
|
||||
|
||||
@property
|
||||
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
|
||||
|
||||
def removeLocalRepo ( self ):
|
||||
if os.path.isdir(self.localRepoDir):
|
||||
print 'Removing Git local repository: <%s>' % self.localRepoDir
|
||||
shutil.rmtree( self.localRepoDir )
|
||||
return
|
||||
if os.path.isdir(self.localRepoDir):
|
||||
print 'Removing Git local repository: <%s>' % self.localRepoDir
|
||||
shutil.rmtree( self.localRepoDir )
|
||||
return
|
||||
|
||||
def clone ( self ):
|
||||
print 'Clone/pull from:', self.url
|
||||
if not os.path.isdir(self.cloneDir):
|
||||
os.makedirs( self.cloneDir )
|
||||
|
||||
if not os.path.isdir(self.localRepoDir):
|
||||
os.chdir( self.cloneDir )
|
||||
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
|
||||
else:
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'pull' ], self.fdLog ).execute()
|
||||
return
|
||||
print 'Clone/pull from:', self.url
|
||||
if not os.path.isdir(self.cloneDir):
|
||||
os.makedirs( self.cloneDir )
|
||||
|
||||
if not os.path.isdir(self.localRepoDir):
|
||||
os.chdir( self.cloneDir )
|
||||
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
|
||||
else:
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'pull' ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
def checkout ( self, branch ):
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
|
||||
return
|
||||
os.chdir( self.localRepoDir )
|
||||
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
|
||||
return
|
||||
|
||||
|
||||
class Configuration ( object ):
|
||||
|
||||
PrimaryNames = \
|
||||
[ 'sender' , 'receivers'
|
||||
, 'coriolisRepo', 'benchsRepo', 'supportRepos'
|
||||
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
|
||||
, 'homeDir' , 'masterHost'
|
||||
, 'debugArg' , 'nightlyMode'
|
||||
, 'rmSource' , 'rmBuild', 'doGit', 'doBuild', 'doBenchs', 'doSendReport'
|
||||
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
|
||||
, 'rmSource' , 'rmBuild'
|
||||
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
|
||||
, 'success' , 'rcode'
|
||||
]
|
||||
SecondaryNames = \
|
||||
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds'
|
||||
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'alcBin', 'ccbBin', 'benchsDir'
|
||||
]
|
||||
|
||||
def __init__ ( self ):
|
||||
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
|
||||
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
|
||||
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
|
||||
self._coriolisRepo = 'https://www-soc.lip6.fr/git/coriolis.git'
|
||||
self._benchsRepo = 'https://www-soc.lip6.fr/git/alliance-check-toolkit.git'
|
||||
self._homeDir = os.environ['HOME']
|
||||
self._debugArg = ''
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = True
|
||||
self._doBuild = True
|
||||
self._doBenchs = False
|
||||
self._doSendReport = True
|
||||
self._nightlyMode = False
|
||||
self._logs = { 'build':None, 'benchs':None }
|
||||
self._fds = { 'build':None, 'benchs':None }
|
||||
self._masterHost = self._detectMasterHost()
|
||||
self._success = False
|
||||
self._rcode = 0
|
||||
|
||||
self._updateSecondaries()
|
||||
return
|
||||
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
|
||||
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
|
||||
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
|
||||
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
|
||||
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
|
||||
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
|
||||
self._homeDir = os.environ['HOME']
|
||||
self._debugArg = ''
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = True
|
||||
self._doCoriolis = False
|
||||
self._doAlliance = False
|
||||
self._doBenchs = False
|
||||
self._doSendReport = False
|
||||
self._nightlyMode = False
|
||||
self._dockerMode = False
|
||||
self._chrootMode = None
|
||||
self._logs = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._fds = { 'alliance':None, 'coriolis':None, 'benchs':None }
|
||||
self._ccbBin = None
|
||||
self._benchsDir = None
|
||||
self._masterHost = self._detectMasterHost()
|
||||
self._success = False
|
||||
self._rcode = 0
|
||||
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __setattr__ ( self, attribute, value ):
|
||||
if attribute in Configuration.SecondaryNames:
|
||||
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
|
||||
if attribute in Configuration.SecondaryNames:
|
||||
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
|
||||
return
|
||||
|
||||
if attribute == 'masterHost' or attribute == '_masterHost':
|
||||
if value == 'lepka':
|
||||
print 'Never touch the Git tree when running on <lepka>.'
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = False
|
||||
self._doSendReport = False
|
||||
|
||||
if attribute[0] == '_':
|
||||
self.__dict__[attribute] = value
|
||||
return
|
||||
|
||||
if attribute == 'homeDir': value = os.path.expanduser(value)
|
||||
|
||||
self.__dict__['_'+attribute] = value
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
if attribute == 'masterHost' or attribute == '_masterHost':
|
||||
if value == 'lepka':
|
||||
print 'Never touch the Git tree when running on <lepka>.'
|
||||
self._rmSource = False
|
||||
self._rmBuild = False
|
||||
self._doGit = False
|
||||
self._doSendReport = False
|
||||
self._targets = { 'SL6' :None
|
||||
, 'SL6_64':None
|
||||
, 'SL7_64':'lepka'
|
||||
}
|
||||
else:
|
||||
self._targets = { 'SL6' :None
|
||||
, 'SL6_64':None
|
||||
, 'SL7_64':'bop'
|
||||
}
|
||||
|
||||
if attribute[0] == '_':
|
||||
self.__dict__[attribute] = value
|
||||
return
|
||||
|
||||
if attribute == 'homeDir': value = os.path.expanduser(value)
|
||||
|
||||
self.__dict__['_'+attribute] = value
|
||||
self._updateSecondaries()
|
||||
return
|
||||
|
||||
def __getattr__ ( self, attribute ):
|
||||
if attribute[0] != '_': attribute = '_'+attribute
|
||||
if not self.__dict__.has_key(attribute):
|
||||
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
|
||||
return self.__dict__[attribute]
|
||||
if attribute[0] != '_': attribute = '_'+attribute
|
||||
if not self.__dict__.has_key(attribute):
|
||||
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
|
||||
return self.__dict__[attribute]
|
||||
|
||||
def _updateSecondaries ( self ):
|
||||
if self._nightlyMode:
|
||||
self._targets['SL6'] = None
|
||||
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
|
||||
else:
|
||||
if self._masterHost != 'lepka':
|
||||
self._targets['SL6'] = None
|
||||
self._rootDir = self._homeDir + '/coriolis-2.x'
|
||||
self._srcDir = self._rootDir + '/src'
|
||||
self._logDir = self._srcDir + '/logs'
|
||||
return
|
||||
if self._nightlyMode:
|
||||
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
|
||||
else:
|
||||
self._rootDir = self._homeDir + '/coriolis-2.x'
|
||||
self._srcDir = self._rootDir + '/src'
|
||||
self._logDir = self._srcDir + '/logs'
|
||||
self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
|
||||
self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
|
||||
self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
|
||||
self._masterHost = self._detectMasterHost()
|
||||
return
|
||||
|
||||
def _detectMasterHost ( self ):
|
||||
masterHost = 'unknown'
|
||||
hostname = socket.gethostname()
|
||||
hostAddr = socket.gethostbyname(hostname)
|
||||
|
||||
if hostname == 'lepka' and hostAddr == '127.0.0.1':
|
||||
masterHost = 'lepka'
|
||||
else:
|
||||
masterHost = hostname.split('.')[0]
|
||||
return masterHost
|
||||
if self._chrootMode is None: return 'unknown'
|
||||
if self._chrootMode: return 'chrooted-host'
|
||||
|
||||
masterHost = 'unknown'
|
||||
hostname = socket.gethostname()
|
||||
hostAddr = socket.gethostbyname(hostname)
|
||||
|
||||
if hostname == 'lepka' and hostAddr == '127.0.0.1':
|
||||
masterHost = 'lepka'
|
||||
else:
|
||||
masterHost = hostname.split('.')[0]
|
||||
return masterHost
|
||||
|
||||
def openLog ( self, stem ):
|
||||
if not os.path.isdir(self._logDir):
|
||||
os.makedirs( self._logDir )
|
||||
|
||||
index = 0
|
||||
timeTag = time.strftime( "%Y.%m.%d" )
|
||||
while True:
|
||||
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
|
||||
if not os.path.isfile(logFile):
|
||||
print "Report log: <%s>" % logFile
|
||||
break
|
||||
index += 1
|
||||
fd = open( logFile, "w" )
|
||||
self._logs[stem] = logFile
|
||||
self._fds [stem] = fd
|
||||
return
|
||||
if not os.path.isdir(self._logDir):
|
||||
os.makedirs( self._logDir )
|
||||
|
||||
index = 0
|
||||
timeTag = time.strftime( "%Y.%m.%d" )
|
||||
while True:
|
||||
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
|
||||
if not os.path.isfile(logFile):
|
||||
print "Report log: <%s>" % logFile
|
||||
break
|
||||
index += 1
|
||||
fd = open( logFile, "w" )
|
||||
self._logs[stem] = logFile
|
||||
self._fds [stem] = fd
|
||||
return
|
||||
|
||||
def closeLogs ( self ):
|
||||
for fd in self._fds.values():
|
||||
if fd: fd.close()
|
||||
return
|
||||
for fd in self._fds.values():
|
||||
if fd: fd.close()
|
||||
return
|
||||
|
||||
def compressLogs ( self ):
|
||||
for log in self._logs.values():
|
||||
if not log: continue
|
||||
for log in self._logs.values():
|
||||
if not log: continue
|
||||
|
||||
fd = open( log, 'r' )
|
||||
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
|
||||
|
||||
for line in fd.readlines(): bzfd.write( line )
|
||||
|
||||
bzfd.close()
|
||||
fd.close()
|
||||
|
||||
os.unlink( log )
|
||||
return
|
||||
|
||||
fd = open( log, 'r' )
|
||||
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
|
||||
def getCommands ( self, target ):
|
||||
commands = []
|
||||
|
||||
for line in fd.readlines(): bzfd.write( line )
|
||||
if self.doAlliance:
|
||||
if not os.path.isfile( self.alcBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <allianceInstaller.sh>, should be here:'
|
||||
, ' <%s>' % self.alcBin
|
||||
] )
|
||||
commands.append( AllianceCommand( self.alcBin, fdLog=self.fds['alliance'] ) )
|
||||
|
||||
bzfd.close()
|
||||
fd.close()
|
||||
if self.doCoriolis:
|
||||
if not os.path.isfile( self.ccbBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
|
||||
, ' <%s>' % self.ccbBin
|
||||
] )
|
||||
|
||||
os.unlink( log )
|
||||
return
|
||||
otherArgs = []
|
||||
if self.debugArg: otherArgs.append( self.debugArg )
|
||||
|
||||
if target == 'SL7_64':
|
||||
otherArgs.append( '--project=support' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'SL6_64' or target == 'SL6':
|
||||
otherArgs.append( '--project=support' )
|
||||
otherArgs.append( '--devtoolset=8' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 6, otherArgs , fdLog=self.fds['coriolis'] ) )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
|
||||
elif target == 'Ubuntu18' or target == 'Debian9':
|
||||
if target == 'Ubuntu18': otherArgs.append( '--qt5' )
|
||||
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs, fdLog=self.fds['coriolis'] ) )
|
||||
|
||||
if self.doBenchs:
|
||||
commands.append( BenchsCommand( self.benchsDir, fdLog=self.fds['benchs'] ) )
|
||||
return commands
|
||||
|
||||
|
||||
class Report ( object ):
|
||||
|
||||
def __init__ ( self, conf ):
|
||||
self.conf = conf
|
||||
|
||||
commaspace = ', '
|
||||
date = time.strftime( "%A %d %B %Y" )
|
||||
stateText = 'FAILED'
|
||||
modeText = 'SoC installation'
|
||||
if self.conf.success: stateText = 'SUCCESS'
|
||||
if self.conf.nightlyMode: modeText = 'Nightly build'
|
||||
|
||||
self.message = MIMEMultipart()
|
||||
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
|
||||
self.message['From' ] = self.conf.sender
|
||||
self.message['To' ] = commaspace.join( self.conf.receivers )
|
||||
self.attachements = []
|
||||
|
||||
self.mainText = '\n'
|
||||
self.mainText += 'Salut le Crevard,\n'
|
||||
self.mainText += '\n'
|
||||
if self.conf.nightlyMode:
|
||||
self.mainText += 'This is the nightly build report of Coriolis.\n'
|
||||
else:
|
||||
self.mainText += 'SoC installer report of Coriolis.\n'
|
||||
self.mainText += '%s\n' % date
|
||||
self.mainText += '\n'
|
||||
if self.conf.success:
|
||||
self.mainText += 'Build was SUCCESSFUL\n'
|
||||
else:
|
||||
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
|
||||
self.mainText += '\n'
|
||||
self.mainText += 'Complete log file(s) can be found here:\n'
|
||||
return
|
||||
self.conf = conf
|
||||
|
||||
commaspace = ', '
|
||||
date = time.strftime( "%A %d %B %Y" )
|
||||
stateText = 'FAILED'
|
||||
modeText = 'SoC installation'
|
||||
if self.conf.success: stateText = 'SUCCESS'
|
||||
if self.conf.nightlyMode: modeText = 'Nightly build'
|
||||
|
||||
self.message = MIMEMultipart()
|
||||
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
|
||||
self.message['From' ] = self.conf.sender
|
||||
self.message['To' ] = commaspace.join( self.conf.receivers )
|
||||
self.attachements = []
|
||||
|
||||
self.mainText = '\n'
|
||||
self.mainText += 'Salut le Crevard,\n'
|
||||
self.mainText += '\n'
|
||||
if self.conf.nightlyMode:
|
||||
self.mainText += 'This is the nightly build report of Coriolis.\n'
|
||||
else:
|
||||
self.mainText += 'SoC installer report of Coriolis.\n'
|
||||
self.mainText += '%s\n' % date
|
||||
self.mainText += '\n'
|
||||
if self.conf.success:
|
||||
self.mainText += 'Build was SUCCESSFUL\n'
|
||||
else:
|
||||
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
|
||||
self.mainText += '\n'
|
||||
self.mainText += 'Complete log file(s) can be found here:\n'
|
||||
return
|
||||
|
||||
def attachLog ( self, logFile ):
|
||||
if not logFile: return
|
||||
|
||||
fd = open( logFile, 'rb' )
|
||||
try:
|
||||
fd.seek( -1024*100, os.SEEK_END )
|
||||
except IOError, e:
|
||||
pass
|
||||
tailLines = ''
|
||||
for line in fd.readlines()[1:]:
|
||||
tailLines += line
|
||||
fd.close()
|
||||
self.mainText += ' <%s>\n' % logFile
|
||||
|
||||
attachement = MIMEApplication(tailLines)
|
||||
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
|
||||
|
||||
self.attachements.append( attachement )
|
||||
return
|
||||
if not logFile: return
|
||||
|
||||
fd = open( logFile, 'rb' )
|
||||
try:
|
||||
fd.seek( -1024*100, os.SEEK_END )
|
||||
except IOError, e:
|
||||
pass
|
||||
tailLines = ''
|
||||
for line in fd.readlines()[1:]:
|
||||
tailLines += line
|
||||
fd.close()
|
||||
self.mainText += ' <%s>\n' % logFile
|
||||
|
||||
attachement = MIMEApplication(tailLines)
|
||||
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
|
||||
|
||||
self.attachements.append( attachement )
|
||||
return
|
||||
|
||||
def send ( self ):
|
||||
self.message.attach( MIMEText(self.mainText) )
|
||||
for attachement in self.attachements:
|
||||
self.message.attach( attachement )
|
||||
|
||||
print "Sending mail report to:"
|
||||
for receiver in self.conf.receivers: print ' <%s>' % receiver
|
||||
session = smtplib.SMTP( 'localhost' )
|
||||
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
|
||||
session.quit()
|
||||
return
|
||||
self.message.attach( MIMEText(self.mainText) )
|
||||
for attachement in self.attachements:
|
||||
self.message.attach( attachement )
|
||||
|
||||
print "Sending mail report to:"
|
||||
for receiver in self.conf.receivers: print ' <%s>' % receiver
|
||||
session = smtplib.SMTP( 'localhost' )
|
||||
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
|
||||
session.quit()
|
||||
return
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
@ -428,36 +524,51 @@ class Report ( object ):
|
|||
parser = optparse.OptionParser ()
|
||||
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." )
|
||||
parser.add_option ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
|
||||
parser.add_option ( "--no-build" , action="store_true" , dest="noBuild" , help="Do not rebuild the tools, must have already be done." )
|
||||
parser.add_option ( "--no-report" , action="store_true" , dest="noReport" , help="Do not send a final report." )
|
||||
parser.add_option ( "--do-alliance" , action="store_true" , dest="doAlliance" , help="Rebuild the Alliance tools." )
|
||||
parser.add_option ( "--do-coriolis" , action="store_true" , dest="doCoriolis" , help="Rebuild the Coriolis tools." )
|
||||
parser.add_option ( "--do-report" , action="store_true" , dest="doReport" , help="Send a final report." )
|
||||
parser.add_option ( "--nightly" , action="store_true" , dest="nightly" , help="Perform a nighly build." )
|
||||
parser.add_option ( "--docker" , action="store_true" , dest="docker" , help="Perform a build inside a docker container." )
|
||||
parser.add_option ( "--chroot" , action="store_true" , dest="chroot" , help="Perform a build inside a chrooted environment." )
|
||||
parser.add_option ( "--benchs" , action="store_true" , dest="benchs" , help="Run the <alliance-checker-toolkit> sanity benchs." )
|
||||
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove the build/install directories." )
|
||||
parser.add_option ( "--rm-source" , action="store_true" , dest="rmSource" , help="Remove the Git source repositories." )
|
||||
parser.add_option ( "--rm-all" , action="store_true" , dest="rmAll" , help="Remove everything (source+build+install)." )
|
||||
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" , help="The root directory (default: <~/coriolis-2.x/>)." )
|
||||
parser.add_option ( "--profile" , action="store" , type="string", dest="profile" , help="The targeted OS for the build." )
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
|
||||
conf = Configuration()
|
||||
|
||||
try:
|
||||
if options.debug: conf.debugArg = '--debug'
|
||||
if options.nightly: conf.nightlyMode = True
|
||||
if options.docker: conf.dockerMode = True
|
||||
if options.chroot: conf.chrootMode = True
|
||||
if options.noGit: conf.doGit = False
|
||||
if options.noBuild: conf.doBuild = False
|
||||
if options.doCoriolis: conf.doCoriolis = True
|
||||
if options.doAlliance: conf.doAlliance = True
|
||||
if options.benchs: conf.doBenchs = True
|
||||
if options.noReport: conf.doSendReport = False
|
||||
if options.doReport: conf.doSendReport = True
|
||||
if options.rmSource or options.rmAll: conf.rmSource = True
|
||||
if options.rmBuild or options.rmAll: conf.rmBuild = True
|
||||
|
||||
if conf.doBuild: conf.openLog( 'build' )
|
||||
if conf.doBenchs: conf.openLog( 'benchs' )
|
||||
|
||||
if conf.doAlliance: conf.openLog( 'alliance' )
|
||||
if conf.doCoriolis: conf.openLog( 'coriolis' )
|
||||
if conf.doBenchs: conf.openLog( 'benchs' )
|
||||
|
||||
if conf.dockerMode: os.environ['USER'] = 'root'
|
||||
|
||||
gitSupports = []
|
||||
for supportRepo in conf.supportRepos:
|
||||
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
|
||||
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['build'] )
|
||||
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['build'] )
|
||||
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
|
||||
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
|
||||
|
||||
if conf.doAlliance:
|
||||
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
|
||||
|
||||
if conf.doGit:
|
||||
for gitSupport in gitSupports:
|
||||
|
@ -466,9 +577,15 @@ try:
|
|||
#if gitSupport.url.endswith('rapidjson'):
|
||||
# gitSupport.checkout( 'a1c4f32' )
|
||||
|
||||
if conf.rmSource: gitCoriolis.removeLocalRepo()
|
||||
gitCoriolis.clone ()
|
||||
gitCoriolis.checkout( 'devel_anabatic' )
|
||||
if conf.doCoriolis:
|
||||
if conf.rmSource: gitCoriolis.removeLocalRepo()
|
||||
gitCoriolis.clone ()
|
||||
gitCoriolis.checkout( 'devel' )
|
||||
|
||||
if conf.doAlliance:
|
||||
if conf.rmSource: gitAlliance.removeLocalRepo()
|
||||
gitAlliance.clone ()
|
||||
#gitAlliance.checkout( 'devel' )
|
||||
|
||||
if conf.rmSource: gitBenchs.removeLocalRepo()
|
||||
gitBenchs.clone()
|
||||
|
@ -480,33 +597,14 @@ try:
|
|||
print 'Removing OS build directory: <%s>' % buildDir
|
||||
shutil.rmtree( buildDir )
|
||||
|
||||
ccbBin = gitCoriolis.localRepoDir+'/bootstrap/ccb.py'
|
||||
if not os.path.isfile( ccbBin ):
|
||||
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
|
||||
, ' <%s>' % ccbBin
|
||||
] )
|
||||
|
||||
buildCommand = '%s --root=%s --project=support --project=coriolis --make="-j%%d install" %%s' \
|
||||
% (ccbBin,conf.rootDir)
|
||||
benchsCommand = 'cd %s/benchs && ../bin/go.sh' % (gitBenchs.localRepoDir)
|
||||
|
||||
commands = \
|
||||
[ ( conf.targets['SL7_64'], buildCommand % (3,conf.debugArg) , conf.fds['build' ] )
|
||||
, ( conf.targets['SL7_64'], buildCommand % (1,conf.debugArg+' --doc') , conf.fds['build' ] )
|
||||
, ( conf.targets['SL7_64'], benchsCommand , conf.fds['benchs'] )
|
||||
#, ( conf.targets['SL6_64'], buildCommand % (6,conf.debugArg+' --devtoolset-8') , conf.fds['build' ] )
|
||||
#, ( conf.targets['SL6_64'], buildCommand % (1,conf.debugArg+' --devtoolset-8 --doc'), conf.fds['build' ] )
|
||||
#, ( conf.targets['SL6_64'], benchsCommand , conf.fds['benchs'] )
|
||||
#, ( conf.targets['SL6'] , buildCommand % (2,conf.debugArg+' --devtoolset-8') , conf.fds['build' ] )
|
||||
#, ( conf.targets['SL6'] , buildCommand % (1,conf.debugArg+' --devtoolset-8 --doc'), conf.fds['build' ] )
|
||||
#, ( conf.targets['SL6'] , benchsCommand , conf.fds['benchs'] )
|
||||
]
|
||||
|
||||
for host,command,fd in commands:
|
||||
if host and fd:
|
||||
print 'Executing command on <%s>:' % host
|
||||
print ' %s' % command
|
||||
Command( [ 'ssh', host, command ], fd ).execute()
|
||||
commands = conf.getCommands( options.profile )
|
||||
for command in commands:
|
||||
if command.host:
|
||||
print 'Executing command on remote host <%s>:' % host
|
||||
else:
|
||||
print 'Executing command on *local* host:'
|
||||
print ' %s' % str(command)
|
||||
command.execute()
|
||||
|
||||
conf.closeLogs()
|
||||
|
||||
|
@ -524,8 +622,8 @@ except ErrorMessage, e:
|
|||
|
||||
if conf.doSendReport:
|
||||
report = Report( conf )
|
||||
report.attachLog( conf.logs['build' ] )
|
||||
report.attachLog( conf.logs['benchs'] )
|
||||
report.attachLog( conf.logs['coriolis' ] )
|
||||
report.attachLog( conf.logs['benchs' ] )
|
||||
report.send()
|
||||
|
||||
conf.compressLogs()
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
${PYTHON_LIBRARIES} -lutil
|
||||
)
|
||||
|
||||
add_library( bora ${cpps} ${mocCpps} )
|
||||
add_library( bora ${cpps} ${mocCpps} ${pyCpps} )
|
||||
set_target_properties( bora PROPERTIES VERSION 1.0 SOVERSION 1 )
|
||||
target_link_libraries( bora ${depLibs} )
|
||||
|
||||
|
|
|
@ -189,7 +189,10 @@ namespace Bora {
|
|||
{
|
||||
cdebug_log(535,1) << "HSlicingNode::updateGlobalsize() - " << this << endl;
|
||||
|
||||
for ( SlicingNode* child : _children ) child->updateGlobalSize();
|
||||
for ( SlicingNode* child : _children ) {
|
||||
cdebug_log(535,0) << "child: " << child << endl;
|
||||
child->updateGlobalSize();
|
||||
}
|
||||
|
||||
if (not getMaster()) {
|
||||
if (getNbChild() == 1) {
|
||||
|
|
|
@ -70,7 +70,8 @@ namespace Bora {
|
|||
TransistorFamily* device = dynamic_cast<TransistorFamily *>( cell );
|
||||
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
|
||||
if (device) {
|
||||
//cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl;
|
||||
cdebug_log(535,0) << "NodeSets:create(): for a Transistor Analog Device" << endl;
|
||||
|
||||
if (not stepRange) {
|
||||
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
|
||||
, getString(device->getName()).c_str()
|
||||
|
@ -94,30 +95,36 @@ namespace Bora {
|
|||
MatrixParameterRange* matrixRange = dynamic_cast<MatrixParameterRange*>( nodeset->getRange() );
|
||||
|
||||
if (mcapacitor) {
|
||||
cdebug_log(535,0) << "NodeSets::create(): for a Capacitor Analog Device" << endl;
|
||||
|
||||
if (not matrixRange) {
|
||||
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a MatrixParameterRange argument instead of %s."
|
||||
, getString(mcapacitor->getName()).c_str()
|
||||
, getString(stepRange).c_str()
|
||||
);
|
||||
|
||||
matrixRange->reset();
|
||||
do {
|
||||
MatrixParameter* mp = NULL;
|
||||
if ( (mp = dynamic_cast<MatrixParameter*>(mcapacitor->getParameter("matrix"))) != NULL )
|
||||
mp->setMatrix( &matrixRange->getValue() );
|
||||
|
||||
layoutGenerator->setDevice( mcapacitor );
|
||||
layoutGenerator->drawLayout();
|
||||
|
||||
nodeset->push_back( DBoxSet::create( mcapacitor, matrixRange->getIndex(), rg ) );
|
||||
|
||||
matrixRange->progress();
|
||||
} while ( matrixRange->isValid() );
|
||||
}
|
||||
|
||||
matrixRange->reset();
|
||||
do {
|
||||
MatrixParameter* mp = NULL;
|
||||
if ( (mp = dynamic_cast<MatrixParameter*>(mcapacitor->getParameter("matrix"))) != NULL )
|
||||
mp->setMatrix( &matrixRange->getValue() );
|
||||
|
||||
layoutGenerator->setDevice( mcapacitor );
|
||||
layoutGenerator->drawLayout();
|
||||
|
||||
//cerr << " Create BoxSet for Capacitor " << matrixRange->getValue() << endl;
|
||||
cerr << " Create BoxSet for Capacitor " << endl;
|
||||
nodeset->push_back( DBoxSet::create( mcapacitor, matrixRange->getIndex(), rg ) );
|
||||
|
||||
matrixRange->progress();
|
||||
} while ( matrixRange->isValid() );
|
||||
} else {
|
||||
ResistorFamily* device = dynamic_cast<ResistorFamily *>( cell );
|
||||
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
|
||||
if (device) {
|
||||
cdebug_log(535,0) << "NodeSets::create(): for a Resistor Analog Device" << endl;
|
||||
|
||||
if (not stepRange) {
|
||||
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
|
||||
, getString(device->getName()).c_str()
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "crlcore/PyRoutingGauge.h"
|
||||
#include "bora/PyDSlicingNode.h"
|
||||
#include "bora/PyStepParameterRange.h"
|
||||
#include "bora/PyMatrixParameterRange.h"
|
||||
|
||||
|
||||
namespace Bora {
|
||||
|
@ -73,8 +74,9 @@ extern "C" {
|
|||
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Second argument *must* be of type Cell." );
|
||||
return NULL;
|
||||
}
|
||||
if (not IsPyStepParameterRange(pyParameterRange)) {
|
||||
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Third argument *must* be of type StepParameterRange." );
|
||||
if ( not IsPyStepParameterRange(pyParameterRange)
|
||||
and not IsPyMatrixParameterRange(pyParameterRange)) {
|
||||
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Third argument *must* be of type StepParameterRange or MatrixParameterRange." );
|
||||
return NULL;
|
||||
}
|
||||
if (pyRoutingGauge and not IsPyRoutingGauge(pyRoutingGauge)) {
|
||||
|
@ -82,10 +84,18 @@ extern "C" {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Cell* cell = PYCELL_O( pyCell );
|
||||
Instance* instance = cell->getInstance( PyString_AsString(pyInstance) );
|
||||
ParameterRange* range = ParameterRangeCast( pyParameterRange );
|
||||
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL;
|
||||
Cell* cell = PYCELL_O( pyCell );
|
||||
Instance* instance = cell->getInstance( PyString_AsString(pyInstance) );
|
||||
if (not instance) {
|
||||
ostringstream message;
|
||||
message << "DSlicingNode.create(): Cell \"" << cell->getName()
|
||||
<< "\" has no instance named \"" << PyString_AsString(pyInstance) << "\".";
|
||||
PyErr_SetString( ConstructorError, message.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ParameterRange* range = ParameterRangeCast( pyParameterRange );
|
||||
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL;
|
||||
|
||||
node = DSlicingNode::create( NodeSets::create( instance->getMasterCell(), range, rg )
|
||||
, UnknownAlignment
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "bora/PyParameterRange.h"
|
||||
#include "bora/PyStepParameterRange.h"
|
||||
#include "bora/PyMatrixParameterRange.h"
|
||||
|
||||
|
||||
namespace Bora {
|
||||
|
@ -112,7 +113,8 @@ extern "C" {
|
|||
# if !defined(__PYTHON_MODULE__)
|
||||
|
||||
ParameterRange* ParameterRangeCast ( PyObject* derivedObject ) {
|
||||
if (IsPyStepParameterRange(derivedObject)) return PYSTEPPARAMETERRANGE_O(derivedObject);
|
||||
if (IsPyStepParameterRange (derivedObject)) return PYSTEPPARAMETERRANGE_O (derivedObject);
|
||||
if (IsPyMatrixParameterRange(derivedObject)) return PYMATRIXPARAMETERRANGE_O(derivedObject);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -396,12 +396,16 @@ namespace Bora {
|
|||
for( Instance* iInstance : instances ) {
|
||||
Cell* model = iInstance->getMasterCell();
|
||||
Device* device = dynamic_cast<Device*>(model);
|
||||
cerr << "device:" << device << endl;
|
||||
|
||||
if (device) {
|
||||
TransistorFamily* tf = dynamic_cast<TransistorFamily*>( device );
|
||||
if (tf) _gridLabel[i+5]->setDynamicText ( QString("%1" ).arg( tf->getNfing() ) );
|
||||
cerr << "tf:" << tf << endl;
|
||||
if (tf) {
|
||||
_gridLabel[i+5]->setDynamicText ( QString("%1" ).arg( tf->getNfing() ) );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: CMAKE; explicit-buffer-name: # "CMakeLists.txt<crlcore/doc/crlcore>" -*-
|
||||
|
||||
set ( htmlInstallDir share/doc/coriolis2/en/html/crlcore )
|
||||
set ( htmlInstallDir share/doc/coriolis2/en/html/doc/crlcore )
|
||||
set ( latexInstallDir share/doc/coriolis2/en/latex/crlcore )
|
||||
set ( doxExtras closed.png
|
||||
open.png
|
||||
|
|
|
@ -54,7 +54,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -92,7 +92,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -59,7 +59,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -66,7 +66,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -123,7 +123,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -98,7 +98,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -60,7 +60,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -80,7 +80,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -93,7 +93,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -68,7 +68,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -64,7 +64,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -53,7 +53,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -118,7 +118,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -87,7 +87,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -923,7 +923,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -56,7 +56,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -175,7 +175,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -67,7 +67,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -495,7 +495,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -60,7 +60,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -292,7 +292,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -71,7 +71,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -763,7 +763,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -86,7 +86,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -846,7 +846,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -96,7 +96,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -1136,7 +1136,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -54,7 +54,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -127,7 +127,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -68,7 +68,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -451,7 +451,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -70,7 +70,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -682,7 +682,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -64,7 +64,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -452,7 +452,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -56,7 +56,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -190,7 +190,7 @@ Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -64,7 +64,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -198,7 +198,7 @@ Static Public Member Functions</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -73,7 +73,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -53,7 +53,7 @@ Directories</h2></td></tr>
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -49,7 +49,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -49,7 +49,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -61,7 +61,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -72,7 +72,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -54,7 +54,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -48,7 +48,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -68,7 +68,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -62,7 +62,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -57,7 +57,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -55,7 +55,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -91,7 +91,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -54,7 +54,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -588,7 +588,7 @@ $(function() {
|
|||
<hr>
|
||||
<table class="footer1">
|
||||
<tr>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
|
||||
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Feb 3 2020</small></td>
|
||||
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue