Added management for "phlib" I/O pad external connectors (for cougar/lvx).
* New: In CRL::ApDriver::DumpSegments(), drive as top-level segments the RoutingPads using a Pin, and not only using a segment. They are not exported as top level Pin but only as Segment as they do belong to a deeper level. * New: In Cumulus/plugins/PadsCorona.Side._placePads(), now manage both "pxlib" and "phlib*". Pad library management is still hardcoded, this should be made a configuration option someday.
This commit is contained in:
parent
02b30b6681
commit
5914e16f26
|
@ -186,6 +186,7 @@ void DumpReference(ofstream& ccell, Cell *cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DumpContacts(ofstream& ccell, Cell *cell)
|
void DumpContacts(ofstream& ccell, Cell *cell)
|
||||||
{
|
{
|
||||||
const char* mbkLayer;
|
const char* mbkLayer;
|
||||||
|
@ -232,11 +233,11 @@ void DumpContacts(ofstream& ccell, Cell *cell)
|
||||||
|
|
||||||
void DumpSegments ( ofstream& ccell, Cell* cell )
|
void DumpSegments ( ofstream& ccell, Cell* cell )
|
||||||
{
|
{
|
||||||
const char* mbkLayer;
|
const char* mbkLayer = NULL;
|
||||||
DbU::Unit x1, x2, y1, y2, width;
|
DbU::Unit x1, x2, y1, y2, width;
|
||||||
Segment* segment;
|
Segment* segment = NULL;
|
||||||
RoutingPad* rp;
|
RoutingPad* rp = NULL;
|
||||||
bool external;
|
bool external = false;
|
||||||
|
|
||||||
for ( Net* net : cell->getNets() ) {
|
for ( Net* net : cell->getNets() ) {
|
||||||
string netName = toMBKName( net->getName() );
|
string netName = toMBKName( net->getName() );
|
||||||
|
@ -244,18 +245,38 @@ void DumpContacts(ofstream& ccell, Cell *cell)
|
||||||
|
|
||||||
for ( Component* component : net->getComponents() ) {
|
for ( Component* component : net->getComponents() ) {
|
||||||
if ( (rp = dynamic_cast<RoutingPad*>(component)) ) {
|
if ( (rp = dynamic_cast<RoutingPad*>(component)) ) {
|
||||||
if ( not net->isExternal() ) continue;
|
if (not net->isExternal()) continue;
|
||||||
if ( not cell->isRouted() ) continue;
|
if (not cell->isRouted()) continue;
|
||||||
|
|
||||||
external = true;
|
external = true;
|
||||||
segment = dynamic_cast<Segment*>(rp->getOccurrence().getEntity());
|
segment = dynamic_cast<Segment*>(rp->getOccurrence().getEntity());
|
||||||
if ( !segment ) continue;
|
if (segment) {
|
||||||
|
x1 = rp->getSourceX();
|
||||||
x1 = rp->getSourceX();
|
x2 = rp->getTargetX();
|
||||||
x2 = rp->getTargetX();
|
y1 = rp->getSourceY();
|
||||||
y1 = rp->getSourceY();
|
y2 = rp->getTargetY();
|
||||||
y2 = rp->getTargetY();
|
width = segment->getWidth();
|
||||||
width = segment->getWidth();
|
} else {
|
||||||
|
Pin* pin = dynamic_cast<Pin*>(rp->getOccurrence().getEntity());
|
||||||
|
if (pin) {
|
||||||
|
Box bb ( pin->getBoundingBox() );
|
||||||
|
rp->getOccurrence().getPath().getTransformation().applyOn( bb );
|
||||||
|
if (bb.getWidth() > bb.getHeight()) {
|
||||||
|
x1 = bb.getCenter().getX();
|
||||||
|
x2 = x1;
|
||||||
|
y1 = bb.getYMin();
|
||||||
|
y2 = bb.getYMax();
|
||||||
|
width = bb.getWidth();
|
||||||
|
} else {
|
||||||
|
x1 = bb.getXMin();
|
||||||
|
x2 = bb.getXMax();
|
||||||
|
y1 = bb.getCenter().getY();
|
||||||
|
y2 = y1;
|
||||||
|
width = bb.getHeight();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} else if ( (segment = dynamic_cast<Segment*>(component)) ) {
|
} else if ( (segment = dynamic_cast<Segment*>(component)) ) {
|
||||||
external = NetExternalComponents::isExternal(component);
|
external = NetExternalComponents::isExternal(component);
|
||||||
x1 = segment->getSourceX();
|
x1 = segment->getSourceX();
|
||||||
|
@ -303,93 +324,68 @@ unsigned getPinIndex(Name& pinname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DumpPins(ofstream &ccell, Cell* cell)
|
void DumpPins(ofstream &ccell, Cell* cell)
|
||||||
{
|
{
|
||||||
const char* mbkLayer;
|
const char* mbkLayer = NULL;
|
||||||
|
|
||||||
for_each_net(net, cell->getExternalNets())
|
for ( Net* net : cell->getExternalNets() ) {
|
||||||
{
|
vector<Pin*> pins;
|
||||||
typedef vector<Pin*> PinVector;
|
for ( Pin* pin : net->getPins() ) {
|
||||||
PinVector pinVector;
|
pins.push_back(pin);
|
||||||
for_each_pin(pin, net->getPins())
|
|
||||||
{
|
|
||||||
pinVector.push_back(pin);
|
|
||||||
end_for;
|
|
||||||
}
|
|
||||||
sort (pinVector.begin(), pinVector.end(), PinSort());
|
|
||||||
set<unsigned> indexesSet;
|
|
||||||
for (PinVector::const_iterator pvit = pinVector.begin();
|
|
||||||
pvit != pinVector.end();
|
|
||||||
pvit++)
|
|
||||||
{
|
|
||||||
if ( !toMBKLayer(mbkLayer,(*pvit)->getLayer()->getName(),false) ) continue;
|
|
||||||
|
|
||||||
Pin* pin = *pvit;
|
|
||||||
Name pinName(pin->getName());
|
|
||||||
unsigned index = getPinIndex(pinName);
|
|
||||||
if (pinName != net->getName())
|
|
||||||
{
|
|
||||||
throw Error("Pin name (" + getString(pinName)
|
|
||||||
+ ") must look like "
|
|
||||||
+ getString(net->getName())
|
|
||||||
+ "[.index] to be driven in AP format");
|
|
||||||
}
|
|
||||||
if (indexesSet.find(index) != indexesSet.end())
|
|
||||||
{
|
|
||||||
throw Error("Two pins on same net with same index for net : "
|
|
||||||
+ getString(net->getName()));
|
|
||||||
}
|
|
||||||
indexesSet.insert(index);
|
|
||||||
// if (pin->getWidth() != pin->getHeight())
|
|
||||||
// cerr << Warning( "CRL::ApDriver(): Pin \"" + getString(pin->getName()) + "\" of \""
|
|
||||||
// + getString(net->getName())
|
|
||||||
// + "\", AP format support only square shapes.")
|
|
||||||
// << endl;;
|
|
||||||
|
|
||||||
DbU::Unit width = 0;
|
|
||||||
switch ( pin->getAccessDirection() ) {
|
|
||||||
case Pin::AccessDirection::NORTH:
|
|
||||||
case Pin::AccessDirection::SOUTH: width = pin->getWidth(); break;
|
|
||||||
case Pin::AccessDirection::EAST:
|
|
||||||
case Pin::AccessDirection::WEST: width = pin->getHeight(); break;
|
|
||||||
default:
|
|
||||||
cerr << Warning( "CRL::ApDriver(): Pin \"" + getString(pin->getName()) + "\" of \""
|
|
||||||
+ getString(net->getName())
|
|
||||||
+ "\", has undefined access direction.")
|
|
||||||
<< endl;;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ccell << "C " << toMBKlambda(pin->getX())
|
|
||||||
<< "," << toMBKlambda(pin->getY())
|
|
||||||
<< "," << toMBKlambda(width)
|
|
||||||
<< "," << toMBKName(pinName)
|
|
||||||
<< "," << index
|
|
||||||
<< ",";
|
|
||||||
switch (pin->getAccessDirection())
|
|
||||||
{
|
|
||||||
case Pin::AccessDirection::NORTH:
|
|
||||||
ccell << "NORTH";
|
|
||||||
break;
|
|
||||||
case Pin::AccessDirection::SOUTH:
|
|
||||||
ccell << "SOUTH";
|
|
||||||
break;
|
|
||||||
case Pin::AccessDirection::EAST:
|
|
||||||
ccell << "EAST";
|
|
||||||
break;
|
|
||||||
case Pin::AccessDirection::WEST:
|
|
||||||
ccell << "WEST";
|
|
||||||
break;
|
|
||||||
case Pin::AccessDirection::UNDEFINED:
|
|
||||||
default:
|
|
||||||
throw Error("Pins must a have direction to generate a .ap");
|
|
||||||
}
|
|
||||||
ccell << "," << mbkLayer << endl;
|
|
||||||
}
|
|
||||||
end_for;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort( pins.begin(), pins.end(), PinSort() );
|
||||||
|
set<unsigned> indexesSet;
|
||||||
|
for ( Pin* pin : pins ) {
|
||||||
|
if (not toMBKLayer(mbkLayer,pin->getLayer()->getName(),false)) continue;
|
||||||
|
|
||||||
|
Name pinName (pin->getName());
|
||||||
|
unsigned index = getPinIndex(pinName);
|
||||||
|
if (pinName != net->getName()) {
|
||||||
|
throw Error( "CRL::ApDriver(): Pin \"%s\" and Net \"%s[.index]\" must have the same name to driven in AP format."
|
||||||
|
, getString(pinName).c_str()
|
||||||
|
, getString(net->getName()).c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexesSet.find(index) != indexesSet.end())
|
||||||
|
throw Error( "CRL::ApDriver(): Net \"%s\" has more than one Pin indexed %u."
|
||||||
|
, getString(net->getName()).c_str(), index );
|
||||||
|
|
||||||
|
indexesSet.insert(index);
|
||||||
|
|
||||||
|
DbU::Unit width = 0;
|
||||||
|
switch ( pin->getAccessDirection() ) {
|
||||||
|
case Pin::AccessDirection::NORTH:
|
||||||
|
case Pin::AccessDirection::SOUTH: width = pin->getWidth(); break;
|
||||||
|
case Pin::AccessDirection::EAST:
|
||||||
|
case Pin::AccessDirection::WEST: width = pin->getHeight(); break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ccell << "C " << toMBKlambda(pin->getX())
|
||||||
|
<< "," << toMBKlambda(pin->getY())
|
||||||
|
<< "," << toMBKlambda(width)
|
||||||
|
<< "," << toMBKName(pinName)
|
||||||
|
<< "," << index
|
||||||
|
<< ",";
|
||||||
|
switch ( pin->getAccessDirection() ) {
|
||||||
|
case Pin::AccessDirection::NORTH: ccell << "NORTH"; break;
|
||||||
|
case Pin::AccessDirection::SOUTH: ccell << "SOUTH"; break;
|
||||||
|
case Pin::AccessDirection::EAST: ccell << "EAST" ; break;
|
||||||
|
case Pin::AccessDirection::WEST: ccell << "WEST" ; break;
|
||||||
|
case Pin::AccessDirection::UNDEFINED:
|
||||||
|
default:
|
||||||
|
throw Error( "CRL::ApDriver(): Pin \" has undefined access direction."
|
||||||
|
, getString(pin->getName()).c_str() );
|
||||||
|
}
|
||||||
|
ccell << "," << mbkLayer << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DumpDate(ofstream &ccell)
|
void DumpDate(ofstream &ccell)
|
||||||
{
|
{
|
||||||
time_t tim;
|
time_t tim;
|
||||||
|
@ -400,6 +396,7 @@ void DumpDate(ofstream &ccell)
|
||||||
<< "/" << rest->tm_year+1900;
|
<< "/" << rest->tm_year+1900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DumpInstances(ofstream &ccell, Cell* cell)
|
void DumpInstances(ofstream &ccell, Cell* cell)
|
||||||
{
|
{
|
||||||
for_each_instance(instance, cell->getNotUnplacedInstances())
|
for_each_instance(instance, cell->getNotUnplacedInstances())
|
||||||
|
@ -444,6 +441,7 @@ void DumpInstances(ofstream &ccell, Cell* cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CRL {
|
namespace CRL {
|
||||||
|
|
|
@ -438,14 +438,21 @@ class Side ( object ):
|
||||||
|
|
||||||
self.u += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
self.u += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
||||||
|
|
||||||
|
p = None
|
||||||
if self.conf.getIoPadGauge().getName() == 'pxlib':
|
if self.conf.getIoPadGauge().getName() == 'pxlib':
|
||||||
p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' )
|
p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' )
|
||||||
|
|
||||||
|
if self.conf.getIoPadGauge().getName().startswith('phlib'):
|
||||||
|
p = re.compile( r'p(?P<power>v[sd]{2})ck2_sp' )
|
||||||
|
|
||||||
|
if p:
|
||||||
m = p.match( padInstance.getMasterCell().getName() )
|
m = p.match( padInstance.getMasterCell().getName() )
|
||||||
|
|
||||||
padName = 'pad'
|
padName = 'pad'
|
||||||
if m: padName = m.group( 'power' )
|
if m: padName = m.group( 'power' )
|
||||||
|
|
||||||
padNet = padInstance.getMasterCell().getNet( padName )
|
padNet = padInstance.getMasterCell().getNet( padName )
|
||||||
|
print 'padName:', padName, 'padNet:', padNet
|
||||||
if padNet:
|
if padNet:
|
||||||
plug = padInstance.getPlug( padNet )
|
plug = padInstance.getPlug( padNet )
|
||||||
chipNet = plug.getNet()
|
chipNet = plug.getNet()
|
||||||
|
|
Loading…
Reference in New Issue