Improve the management of the I/O pad near the chip corner.
* Bug: In cumulus/plugins/PadsCorona.py, when a pad is at the beginning or at the end of the side, the pad corona terminal may be outside the corona range (not directly facing it). In that case, create a bend to reach it. Worse, in some case more than one (but likely no more), could be in that case, so not only do we create a bend but also make a shift in the bended segment so two consecutive ones are not on the same axis, causing shorts. If both end pads of a corner are in that case, we cannot prevent a short, so at least, issue a warning. * Bug: In CRL::Vhdl, the Entity::VstUseConcat was not passed correctly along, so we did get a strange mix of conat and direct assignment. * New: In Unicorn/cgt.py : added --vst-use-concat options to control the VST driver behavior.
This commit is contained in:
parent
f92b48174b
commit
91f973c00f
|
@ -195,6 +195,34 @@ namespace CRL {
|
|||
}
|
||||
|
||||
|
||||
DbU::Unit RoutingGauge::getPitch ( const Layer* layer ) const
|
||||
{
|
||||
size_t depth = getLayerDepth( layer );
|
||||
return (depth != nlayerdepth) ? _layerGauges[depth]->getPitch() : 0;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit RoutingGauge::getOffset ( const Layer* layer ) const
|
||||
{
|
||||
size_t depth = getLayerDepth( layer );
|
||||
return (depth != nlayerdepth) ? _layerGauges[depth]->getOffset() : 0;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit RoutingGauge::getWireWidth ( const Layer* layer ) const
|
||||
{
|
||||
size_t depth = getLayerDepth( layer );
|
||||
return (depth != nlayerdepth) ? _layerGauges[depth]->getWireWidth() : 0;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit RoutingGauge::getViaWidth ( const Layer* layer ) const
|
||||
{
|
||||
size_t depth = getLayerDepth( layer );
|
||||
return (depth != nlayerdepth) ? _layerGauges[depth]->getViaWidth() : 0;
|
||||
}
|
||||
|
||||
|
||||
RoutingLayerGauge* RoutingGauge::getLayerGauge ( size_t depth ) const
|
||||
{
|
||||
if ( depth >= _layerGauges.size() ) return NULL;
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace Vhdl {
|
|||
_offset = (ptrdiff_t)this - (ptrdiff_t)property;
|
||||
}
|
||||
|
||||
if (_flags == NoFlags) _flags = EntityMode;
|
||||
if ((_flags & ~ModeMask) == NoFlags) _flags |= EntityMode;
|
||||
|
||||
for ( Net* net : cell->getNets() ) {
|
||||
if (net->isDeepNet()) continue;
|
||||
|
@ -353,7 +353,8 @@ namespace Vhdl {
|
|||
}
|
||||
|
||||
for ( auto icell : masterCells ) {
|
||||
Vhdl::Entity* component = Vhdl::EntityExtension::create( icell, Vhdl::Entity::ComponentMode );
|
||||
Vhdl::Entity* component = Vhdl::EntityExtension::create
|
||||
( icell, Vhdl::Entity::ComponentMode | (_flags & ModeMask));
|
||||
component->toComponent( out );
|
||||
out << "\n";
|
||||
}
|
||||
|
@ -393,7 +394,8 @@ namespace Vhdl {
|
|||
|
||||
Entity* masterEntity = EntityExtension::get( instance->getMasterCell() );
|
||||
if (not masterEntity) {
|
||||
masterEntity = EntityExtension::create( instance->getMasterCell(), ComponentMode );
|
||||
masterEntity = EntityExtension::create
|
||||
( instance->getMasterCell(), ComponentMode | (_flags & ModeMask));
|
||||
}
|
||||
|
||||
size_t width = 0;
|
||||
|
|
|
@ -243,6 +243,9 @@ namespace Vhdl {
|
|||
first = false;
|
||||
}
|
||||
} else {
|
||||
cerr << "VhdlPortMap is in bit mode for \"" << _signal->getName() << "\""
|
||||
<< " _flags:" << _flags << " mappedNames:" << _mapping.size() << endl;
|
||||
|
||||
auto imapping = _mapping.rbegin();
|
||||
bool first = true;
|
||||
for ( ; imapping!=_mapping.rend() ; ++imapping ) {
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace CRL {
|
|||
void vstDriver ( const string cellPath, Cell *cell, unsigned int& saveState )
|
||||
{
|
||||
unsigned int entityFlags = Vhdl::Entity::EntityMode /* | Vhdl::Entity::IeeeMode */;
|
||||
if (saveState & Catalog::State::VstUseConcat) entityFlags |= Vhdl::Entity::VstUseConcat;
|
||||
/*if (saveState & Catalog::State::VstUseConcat)*/ entityFlags |= Vhdl::Entity::VstUseConcat;
|
||||
|
||||
//NamingScheme::toVhdl( cell, NamingScheme::FromVerilog );
|
||||
Vhdl::Entity* vhdlEntity = Vhdl::EntityExtension::create( cell, entityFlags );
|
||||
|
|
|
@ -72,6 +72,10 @@ namespace CRL {
|
|||
size_t getLayerDepth ( const Layer* ) const;
|
||||
unsigned int getLayerType ( const Layer* ) const;
|
||||
unsigned int getLayerDirection ( const Layer* ) const;
|
||||
DbU::Unit getPitch ( const Layer* ) const;
|
||||
DbU::Unit getOffset ( const Layer* ) const;
|
||||
DbU::Unit getWireWidth ( const Layer* ) const;
|
||||
DbU::Unit getViaWidth ( const Layer* ) const;
|
||||
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
|
||||
inline unsigned int getLayerDirection ( size_t depth ) const;
|
||||
inline unsigned int getLayerType ( size_t depth ) const;
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace Vhdl {
|
|||
, AsInnerSignal = 0x0010
|
||||
, VstUseConcat = 0x0020
|
||||
};
|
||||
const unsigned int ModeMask = VstUseConcat;
|
||||
public:
|
||||
static std::vector<Entity*>&
|
||||
getAllEntities ();
|
||||
|
|
|
@ -179,6 +179,102 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getPitch ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyRoutingGauge_getPitch()" << endl;
|
||||
|
||||
DbU::Unit pitch = 0;
|
||||
HTRY
|
||||
METHOD_HEAD("RoutingGauge.getPitch()")
|
||||
PyObject* pyLayer = NULL;
|
||||
|
||||
if (PyArg_ParseTuple( args, "O:RoutingGauge.getPitch", &pyLayer)) {
|
||||
if ( not PyObject_IsInstance(pyLayer,(PyObject*)&PyTypeLayer) ) {
|
||||
PyErr_SetString ( ConstructorError, "Bad type for layer argument of RoutingGauge.getLayerPitch()." );
|
||||
return NULL;
|
||||
}
|
||||
pitch = rg->getPitch( PYLAYER_O(pyLayer) );
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingGauge.getPitch()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
return Py_BuildValue("I",pitch);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getOffset ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyRoutingGauge_getOffset()" << endl;
|
||||
|
||||
DbU::Unit offset = 0;
|
||||
HTRY
|
||||
METHOD_HEAD("RoutingGauge.getOffset()")
|
||||
PyObject* pyLayer = NULL;
|
||||
|
||||
if (PyArg_ParseTuple( args, "O:RoutingGauge.getOffset", &pyLayer)) {
|
||||
if ( not PyObject_IsInstance(pyLayer,(PyObject*)&PyTypeLayer) ) {
|
||||
PyErr_SetString ( ConstructorError, "Bad type for layer argument of RoutingGauge.getOffset()." );
|
||||
return NULL;
|
||||
}
|
||||
offset = rg->getOffset( PYLAYER_O(pyLayer) );
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingGauge.getOffset()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
return Py_BuildValue("I",offset);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getWireWidth ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyRoutingGauge_getWireWidth()" << endl;
|
||||
|
||||
DbU::Unit wireWidth = 0;
|
||||
HTRY
|
||||
METHOD_HEAD("RoutingGauge.getWireWidth()")
|
||||
PyObject* pyLayer = NULL;
|
||||
|
||||
if (PyArg_ParseTuple( args, "O:RoutingGauge.getWireWidth", &pyLayer)) {
|
||||
if ( not PyObject_IsInstance(pyLayer,(PyObject*)&PyTypeLayer) ) {
|
||||
PyErr_SetString ( ConstructorError, "Bad type for layer argument of RoutingGauge.getWireWidth()." );
|
||||
return NULL;
|
||||
}
|
||||
wireWidth = rg->getWireWidth( PYLAYER_O(pyLayer) );
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingGauge.getWireWidth()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
return Py_BuildValue("I",wireWidth);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getViaWidth ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyRoutingGauge_getViaWidth()" << endl;
|
||||
|
||||
DbU::Unit pitch = 0;
|
||||
HTRY
|
||||
METHOD_HEAD("RoutingGauge.getViaWidth()")
|
||||
PyObject* pyLayer = NULL;
|
||||
|
||||
if (PyArg_ParseTuple( args, "O:RoutingGauge.getViaWidth", &pyLayer)) {
|
||||
if ( not PyObject_IsInstance(pyLayer,(PyObject*)&PyTypeLayer) ) {
|
||||
PyErr_SetString ( ConstructorError, "Bad type for layer argument of RoutingGauge.getViaWidth()." );
|
||||
return NULL;
|
||||
}
|
||||
pitch = rg->getViaWidth( PYLAYER_O(pyLayer) );
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingGauge.getViaWidth()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
return Py_BuildValue("I",pitch);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getLayerGauge ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyRoutingGauge_getLayerGauge()" << endl;
|
||||
|
@ -394,6 +490,14 @@ extern "C" {
|
|||
, "Return the vertical pitch of the metal closest to the substrate." }
|
||||
, { "getLayerDepth" , (PyCFunction)PyRoutingGauge_getLayerDepth , METH_VARARGS
|
||||
, "Return the depth of the given layer." }
|
||||
, { "getPitch" , (PyCFunction)PyRoutingGauge_getPitch , METH_VARARGS
|
||||
, "Return the routing pitch of the given layer." }
|
||||
, { "getOffset" , (PyCFunction)PyRoutingGauge_getOffset , METH_VARARGS
|
||||
, "Return the offset of the first track of the given layer." }
|
||||
, { "getWireWidth" , (PyCFunction)PyRoutingGauge_getWireWidth , METH_VARARGS
|
||||
, "Return the default wire width of the given layer." }
|
||||
, { "getViaWidth" , (PyCFunction)PyRoutingGauge_getViaWidth , METH_VARARGS
|
||||
, "Return the default via width of the given layer." }
|
||||
, { "getLayerGauge" , (PyCFunction)PyRoutingGauge_getLayerGauge , METH_VARARGS
|
||||
, "Return the RoutingLayerGauge of the given layer/depth." }
|
||||
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection , METH_VARARGS
|
||||
|
|
|
@ -216,6 +216,7 @@ class GaugeConf ( object ):
|
|||
def getIoPadGauge ( self ): return self.ioPadGauge
|
||||
def getHRoutingGauge ( self ): return self.routingGauge.getLayerGauge( self.horizontalDepth )
|
||||
def getVRoutingGauge ( self ): return self.routingGauge.getLayerGauge( self.verticalDepth )
|
||||
def getPitch ( self, layer ): return self.routingGauge.getPitch( layer )
|
||||
|
||||
def _loadRoutingGauge ( self ):
|
||||
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
|
||||
|
@ -734,6 +735,45 @@ class ChipConf ( object ):
|
|||
return axis, width
|
||||
|
||||
|
||||
def toCoronaPitchInChip ( self, uCore, layer ):
|
||||
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: %sl %s\n' % (DbU.toLambda(uCore), DbU.getValueString(uCore)) )
|
||||
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
lg = None
|
||||
mask = layer.getMask()
|
||||
for layerGauge in self.gaugeConf.routingGauge.getLayerGauges():
|
||||
if layerGauge.getLayer().getMask() == mask:
|
||||
lg = layerGauge
|
||||
break
|
||||
|
||||
if not lg:
|
||||
trace( 550, '-' )
|
||||
return 0
|
||||
|
||||
trace( 550, '\t%s\n' % str(lg) )
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
uCorona = uCore - coronaAb.getYMin()
|
||||
else:
|
||||
uCorona = uCore - coronaAb.getXMin()
|
||||
|
||||
uCorona, width = self.toRoutingGauge( uCorona, uCorona, layer )
|
||||
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: %sl %s\n' % (DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
uCore = uCorona + coronaAb.getYMin()
|
||||
else:
|
||||
uCore = uCorona + coronaAb.getXMin()
|
||||
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: %sl %s\n' % (DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCore: %sl %s\n' % (DbU.toLambda(uCore ), DbU.getValueString(uCore )) )
|
||||
trace( 550, '-' )
|
||||
return uCore
|
||||
|
||||
|
||||
|
||||
def coronaHorizontal ( self, chipNet, layer, chipY, width, chipXMin, chipXMax ):
|
||||
trace( 550, ',+', '\tChipConf.coronaHorizontal\n' )
|
||||
|
||||
|
@ -958,7 +998,7 @@ class ChipConf ( object ):
|
|||
if padList[i][1] == padInstance.getName():
|
||||
if (padInstance.getMasterCell().getAbutmentBox().getHeight() != self.gaugeConf.getIoPadHeight()):
|
||||
raise ErrorMessage( 1, 'The pad [%d] %s (%s) on %s side is not an instance of a pad cell.'
|
||||
% (i,padInstance.getName(),padInstance.getModel().getName(),side) )
|
||||
% (i,padInstance.getName(),padInstance.getMasterCell().getName(),side) )
|
||||
padList[i][1] = padInstance
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -169,6 +169,7 @@ class Side ( object ):
|
|||
self.u = self.conf.getIoPadHeight()
|
||||
self.spacerCount = 0
|
||||
self.gap = 0
|
||||
self.coreWires = []
|
||||
|
||||
if self.type == chip.North:
|
||||
self.pads = self.conf.northPads
|
||||
|
@ -221,6 +222,16 @@ class Side ( object ):
|
|||
return False
|
||||
|
||||
|
||||
def addCoreWire ( self, coreWire ):
|
||||
self.coreWires.append( coreWire )
|
||||
return
|
||||
|
||||
|
||||
def updateGap ( self, gapWidth ):
|
||||
self.gap = max( self.gap, gapWidth )
|
||||
return
|
||||
|
||||
|
||||
def _check ( self, checkSize, checkName ):
|
||||
sideName = 'unknown'
|
||||
chipSize = 0
|
||||
|
@ -552,20 +563,75 @@ class Side ( object ):
|
|||
return
|
||||
|
||||
|
||||
def drawCoreWires ( self ):
|
||||
trace( 550, ',+', '\tSide.drawCoreWire()\n' )
|
||||
|
||||
if self.type == chip.West or self.type == chip.East:
|
||||
trace( 550, 'Sort East/West' )
|
||||
self.coreWires.sort( key=lambda wire: wire.bbSegment.getCenter().getY() )
|
||||
if self.type == chip.North or self.type == chip.South:
|
||||
trace( 550, 'Sort North/South' )
|
||||
self.coreWires.sort( key=lambda wire: wire.bbSegment.getCenter().getX() )
|
||||
|
||||
for wire in self.coreWires:
|
||||
wire.updateInCorona()
|
||||
|
||||
size = len(self.coreWires)
|
||||
offset = 0
|
||||
for i in range(size):
|
||||
if self.coreWires[i].inCoronaRange: break
|
||||
offset += 1
|
||||
for i in range(offset):
|
||||
self.coreWires[i].setOffset( i+1, CoreWire.AtBegin )
|
||||
|
||||
offset = 0
|
||||
for i in range(1,size+1):
|
||||
if self.coreWires[-i].inCoronaRange: break
|
||||
offset += 1
|
||||
for i in range(offset):
|
||||
self.coreWires[ -(offset+1) ].setOffset( i+1, CoreWire.AtEnd )
|
||||
|
||||
for wire in self.coreWires:
|
||||
if self.type == chip.West or self.type == chip.East:
|
||||
trace( 550, '\t| %s %s %d %s inRange:%s\n' % ( wire.chipNet.getName()
|
||||
, DbU.getValueString(wire.bbSegment.getCenter().getY())
|
||||
, wire.count
|
||||
, wire.padSegment.getLayer()
|
||||
, wire.inCoronaRange ) )
|
||||
|
||||
if self.type == chip.North or self.type == chip.South:
|
||||
trace( 550, '\t| %s %s %d %s inRange:%s\n' % ( wire.chipNet.getName()
|
||||
, DbU.getValueString(wire.bbSegment.getCenter().getX())
|
||||
, wire.count
|
||||
, wire.padSegment.getLayer()
|
||||
, wire.inCoronaRange ) )
|
||||
wire.drawWire()
|
||||
trace( 550, '-' )
|
||||
return
|
||||
|
||||
|
||||
class CoreWire ( object ):
|
||||
|
||||
# Should be read from the symbolic technology rules.
|
||||
viaPitch = DbU.fromLambda( 4.0 )
|
||||
|
||||
NoOffset = 0x0000
|
||||
AtBegin = 0x0001
|
||||
AtEnd = 0x0002
|
||||
|
||||
def __init__ ( self, corona, chipNet, padSegment, bbSegment, side, preferredDir, count ):
|
||||
self.corona = corona
|
||||
self.chipNet = chipNet
|
||||
self.padSegment = padSegment
|
||||
self.bbSegment = bbSegment
|
||||
self.side = side
|
||||
self.preferredDir = preferredDir
|
||||
self.arraySize = None
|
||||
self.count = count
|
||||
self.corona = corona
|
||||
self.chipNet = chipNet
|
||||
self.padSegment = padSegment
|
||||
self.bbSegment = bbSegment
|
||||
self.offset = 0
|
||||
self.offsetType = CoreWire.NoOffset
|
||||
self.side = side
|
||||
self.preferredDir = preferredDir
|
||||
self.inCoronaRange = True
|
||||
self.arraySize = None
|
||||
self.count = count
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
@ -573,6 +639,27 @@ class CoreWire ( object ):
|
|||
def conf ( self ): return self.corona.conf
|
||||
|
||||
|
||||
def updateInCorona ( self ):
|
||||
coronaAb = self.conf.getInstanceAb( self.conf.icorona )
|
||||
|
||||
if self.side == chip.South or self.side == chip.North:
|
||||
xCoronaPin = self.bbSegment.getCenter().getX()
|
||||
if xCoronaPin <= coronaAb.getXMin(): self.inCoronaRange = False
|
||||
elif xCoronaPin >= coronaAb.getXMax(): self.inCoronaRange = False
|
||||
|
||||
if self.side == chip.East or self.side == chip.West:
|
||||
yCoronaPin = self.bbSegment.getCenter().getY()
|
||||
if yCoronaPin <= coronaAb.getYMin(): self.inCoronaRange = False
|
||||
elif yCoronaPin >= coronaAb.getYMax(): self.inCoronaRange = False
|
||||
|
||||
return
|
||||
|
||||
|
||||
def setOffset ( self, offset, offsetType ):
|
||||
self.offset = offset
|
||||
self.offsetType = offsetType
|
||||
|
||||
|
||||
def _computeCoreLayers ( self ):
|
||||
rg = self.conf.gaugeConf.routingGauge
|
||||
mask = self.padSegment.getLayer().getMask()
|
||||
|
@ -627,7 +714,7 @@ class CoreWire ( object ):
|
|||
def drawWire ( self ):
|
||||
trace( 550, ',+', '\tCoreWire.drawWire(): chip:"%s"\n' %(self.chipNet.getName()) )
|
||||
|
||||
coreAb = self.conf.getInstanceAb( self.conf.icorona )
|
||||
coronaAb = self.conf.getInstanceAb( self.conf.icorona )
|
||||
|
||||
self._computeCoreLayers()
|
||||
|
||||
|
@ -637,21 +724,30 @@ class CoreWire ( object ):
|
|||
|
||||
if self.side == chip.West or self.side == chip.East:
|
||||
flags = chip.OnHorizontalPitch
|
||||
hPitch = self.conf.gaugeConf.getPitch( self.symSegmentLayer )
|
||||
vPitch = self.conf.gaugeConf.getPitch( self.padSegment.getLayer() )
|
||||
|
||||
yCore = self.conf.toCoronaPitchInChip( self.bbSegment.getCenter().getY(), self.symSegmentLayer )
|
||||
if self.offset:
|
||||
if self.offsetType == CoreWire.AtBegin:
|
||||
yCore += 2*hPitch*self.offset
|
||||
else:
|
||||
yCore -= 2*hPitch*self.offset
|
||||
|
||||
if self.side == chip.West:
|
||||
accessDirection = Pin.Direction.WEST
|
||||
xPadMin = self.bbSegment.getXMin()
|
||||
xContact = self.corona.coreSymBb.getXMin()
|
||||
xContact = self.corona.coreSymBb.getXMin() - self.offset * 2*vPitch
|
||||
xPadMax = xContact
|
||||
xCore = coreAb.getXMin()
|
||||
xCore = coronaAb.getXMin()
|
||||
if not self.preferredDir:
|
||||
xPadMax += self.bbSegment.getHeight()/2
|
||||
else:
|
||||
accessDirection = Pin.Direction.EAST
|
||||
xPadMax = self.bbSegment.getXMax()
|
||||
xContact = self.corona.coreSymBb.getXMax()
|
||||
xContact = self.corona.coreSymBb.getXMax() + self.offset * 2*vPitch
|
||||
xPadMin = xContact
|
||||
xCore = coreAb.getXMax()
|
||||
xCore = coronaAb.getXMax()
|
||||
if not self.preferredDir:
|
||||
xPadMin -= self.bbSegment.getHeight()/2
|
||||
|
||||
|
@ -665,24 +761,24 @@ class CoreWire ( object ):
|
|||
trace( 550, '\tself.arraySize: %s\n' % str(self.arraySize) )
|
||||
if self.arraySize:
|
||||
contacts = self.conf.coronaContactArray( self.chipNet
|
||||
, self.symContactLayer
|
||||
, xContact
|
||||
, self.bbSegment.getCenter().getY()
|
||||
, self.arraySize
|
||||
, flags
|
||||
)
|
||||
, self.symContactLayer
|
||||
, xContact
|
||||
, yCore
|
||||
, self.arraySize
|
||||
, flags
|
||||
)
|
||||
vStrapBb = Box()
|
||||
for contact in contacts:
|
||||
vStrapBb.merge( contact.getBoundingBox() )
|
||||
else:
|
||||
contact = self.conf.coronaContact( self.chipNet
|
||||
, self.symContactLayer
|
||||
, xContact
|
||||
, self.bbSegment.getCenter().getY()
|
||||
, self.symContactSize[0]
|
||||
, self.symContactSize[1]
|
||||
, flags
|
||||
)
|
||||
, self.symContactLayer
|
||||
, xContact
|
||||
, yCore
|
||||
, self.symContactSize[0]
|
||||
, self.symContactSize[1]
|
||||
, flags
|
||||
)
|
||||
vStrapBb = contact.getBoundingBox( padLayer )
|
||||
|
||||
hRealBb = hReal.getBoundingBox( padLayer )
|
||||
|
@ -707,7 +803,7 @@ class CoreWire ( object ):
|
|||
|
||||
self.conf.coronaHorizontal( self.chipNet
|
||||
, self.symSegmentLayer
|
||||
, self.bbSegment.getCenter().getY()
|
||||
, yCore
|
||||
, self.bbSegment.getHeight()
|
||||
, xContact
|
||||
, xCore
|
||||
|
@ -718,27 +814,38 @@ class CoreWire ( object ):
|
|||
, accessDirection
|
||||
, self.symSegmentLayer
|
||||
, xCore
|
||||
, self.bbSegment.getCenter().getY()
|
||||
, yCore
|
||||
, DbU.fromLambda( 1.0 )
|
||||
, self.bbSegment.getHeight()
|
||||
)
|
||||
else:
|
||||
flags = chip.OnVerticalPitch
|
||||
flags = chip.OnVerticalPitch
|
||||
hPitch = self.conf.gaugeConf.getPitch( self.padSegment.getLayer() )
|
||||
vPitch = self.conf.gaugeConf.getPitch( self.symSegmentLayer )
|
||||
|
||||
trace( 550, '\t%s translated of %s\n' % (self.symSegmentLayer, DbU.getValueString( 2*vPitch*self.offset )) )
|
||||
|
||||
xCore = self.conf.toCoronaPitchInChip( self.bbSegment.getCenter().getX(), self.symSegmentLayer )
|
||||
if self.offset:
|
||||
if self.offsetType == CoreWire.AtBegin:
|
||||
xCore += 2*vPitch*self.offset
|
||||
else:
|
||||
xCore -= 2*vPitch*self.offset
|
||||
|
||||
if self.side == chip.South:
|
||||
accessDirection = Pin.Direction.SOUTH
|
||||
yPadMin = self.bbSegment.getYMin()
|
||||
yPadMax = self.corona.coreSymBb.getYMin()
|
||||
yPadMax = self.corona.coreSymBb.getYMin() - self.offset * 2*hPitch
|
||||
yContact = yPadMax
|
||||
yCore = coreAb.getYMin()
|
||||
yCore = coronaAb.getYMin()
|
||||
if not self.preferredDir:
|
||||
yPadMax += self.bbSegment.getWidth()/2
|
||||
else:
|
||||
accessDirection = Pin.Direction.NORTH
|
||||
yPadMax = self.bbSegment.getYMax()
|
||||
yPadMin = self.corona.coreSymBb.getYMax()
|
||||
yPadMin = self.corona.coreSymBb.getYMax() + self.offset * 2*hPitch
|
||||
yContact = yPadMin
|
||||
yCore = coreAb.getYMax()
|
||||
yCore = coronaAb.getYMax()
|
||||
if not self.preferredDir:
|
||||
yPadMin -= self.bbSegment.getWidth()/2
|
||||
|
||||
|
@ -753,7 +860,7 @@ class CoreWire ( object ):
|
|||
if self.arraySize:
|
||||
contacts = self.conf.coronaContactArray( self.chipNet
|
||||
, self.symContactLayer
|
||||
, self.bbSegment.getCenter().getX()
|
||||
, xCore
|
||||
, yContact
|
||||
, self.arraySize
|
||||
, flags
|
||||
|
@ -792,9 +899,10 @@ class CoreWire ( object ):
|
|||
if self.side == chip.South: yContact = min( yContact, hStrapBb.getYMin() )
|
||||
else: yContact = max( yContact, hStrapBb.getYMax() )
|
||||
|
||||
trace( 550, '\txCore: %sl %s\n' % (DbU.toLambda(xCore), DbU.getValueString(xCore)) )
|
||||
self.conf.coronaVertical( self.chipNet
|
||||
, self.symSegmentLayer
|
||||
, self.bbSegment.getCenter().getX()
|
||||
, xCore
|
||||
, self.bbSegment.getWidth()
|
||||
, yContact
|
||||
, yCore
|
||||
|
@ -803,7 +911,7 @@ class CoreWire ( object ):
|
|||
, self.count
|
||||
, accessDirection
|
||||
, self.symSegmentLayer
|
||||
, self.bbSegment.getCenter().getX()
|
||||
, xCore
|
||||
, yCore
|
||||
, self.bbSegment.getWidth()
|
||||
, DbU.fromLambda( 1.0 )
|
||||
|
@ -967,12 +1075,12 @@ class Corona ( object ):
|
|||
|
||||
|
||||
def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ):
|
||||
padSide = None
|
||||
if self.hasSouthPad(padInstance): padSide = chip.South
|
||||
elif self.hasNorthPad(padInstance): padSide = chip.North
|
||||
elif self.hasEastPad (padInstance): padSide = chip.East
|
||||
elif self.hasWestPad (padInstance): padSide = chip.West
|
||||
if not padSide: return None
|
||||
side = None
|
||||
if self.hasSouthPad(padInstance): side = self.southSide
|
||||
elif self.hasNorthPad(padInstance): side = self.northSide
|
||||
elif self.hasEastPad (padInstance): side = self.eastSide
|
||||
elif self.hasWestPad (padInstance): side = self.westSide
|
||||
if not side: return count
|
||||
|
||||
innerBb = self.conf.cell.getAbutmentBox().inflate( -self.conf.getIoPadHeight() )
|
||||
rg = self.conf.gaugeConf.routingGauge
|
||||
|
@ -1005,7 +1113,7 @@ class Corona ( object ):
|
|||
gapWidth = 0
|
||||
segments = None
|
||||
inPreferredDir = False
|
||||
if padSide == chip.North or padSide == chip.South:
|
||||
if side.type == chip.North or side.type == chip.South:
|
||||
if len(vsegments):
|
||||
inPreferredDir = True
|
||||
segments = vsegments[ min(vsegments.keys()) ]
|
||||
|
@ -1025,14 +1133,10 @@ class Corona ( object ):
|
|||
coreWires = []
|
||||
if segments:
|
||||
for segment, bb in segments:
|
||||
if padSide == chip.South: self.southSide.gap = max( self.southSide.gap, gapWidth )
|
||||
elif padSide == chip.North: self.northSide.gap = max( self.northSide.gap, gapWidth )
|
||||
elif padSide == chip.East : self.eastSide.gap = max( self.eastSide.gap , gapWidth )
|
||||
elif padSide == chip.West : self.westSide.gap = max( self.westSide.gap , gapWidth )
|
||||
|
||||
coreWires.append( CoreWire( self, chipIntNet, segment, bb, padSide, inPreferredDir, count ) )
|
||||
side.updateGap ( gapWidth )
|
||||
side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) )
|
||||
count += 1
|
||||
return coreWires
|
||||
return count
|
||||
|
||||
|
||||
def _placeInnerCorona ( self ):
|
||||
|
@ -1045,8 +1149,6 @@ class Corona ( object ):
|
|||
self.eastSide.gap = self.southSide.gap
|
||||
self.westSide.gap = self.southSide.gap
|
||||
|
||||
coreWires = []
|
||||
|
||||
for coronaPlug in self.conf.icorona.getPlugs():
|
||||
chipIntNet = coronaPlug.getNet()
|
||||
if not chipIntNet:
|
||||
|
@ -1058,11 +1160,8 @@ class Corona ( object ):
|
|||
doneInstances = []
|
||||
for chipPlug in chipIntNet.getPlugs():
|
||||
doneInstances.append( chipPlug.getInstance() )
|
||||
padNet = chipPlug.getMasterNet()
|
||||
padWires = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected )
|
||||
if padWires:
|
||||
coreWires += padWires
|
||||
padConnected += len(padWires)
|
||||
padNet = chipPlug.getMasterNet()
|
||||
padConnected = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected )
|
||||
|
||||
if chipIntNet.isGlobal():
|
||||
for instance in self.conf.cell.getInstances():
|
||||
|
@ -1072,10 +1171,7 @@ class Corona ( object ):
|
|||
padNet = instance.getMasterCell().getNet( chipIntNet.getName() )
|
||||
if not padNet: continue
|
||||
|
||||
padWires = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected )
|
||||
if padWires:
|
||||
coreWires += padWires
|
||||
padConnected += len(padWires)
|
||||
padConnected = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected )
|
||||
|
||||
if padConnected == 0:
|
||||
raise ErrorMessage( 1, 'PadsCorona._placeInnerCorona(): Chip net "%s" is not connected to a pad.' \
|
||||
|
@ -1089,10 +1185,46 @@ class Corona ( object ):
|
|||
, self.conf.toSymbolic( self.eastSide.gap /2, chip.Inferior )
|
||||
, self.conf.toSymbolic( self.northSide.gap/2, chip.Inferior ) )
|
||||
|
||||
for wire in coreWires:
|
||||
trace( 550, '\t| %s %d %s\n' % (wire.chipNet.getName(),wire.count,wire.padSegment.getLayer()))
|
||||
self.southSide.drawCoreWires()
|
||||
self.northSide.drawCoreWires()
|
||||
self.eastSide .drawCoreWires()
|
||||
self.westSide .drawCoreWires()
|
||||
|
||||
for wire in coreWires: wire.drawWire()
|
||||
if len(self.southSide.coreWires) \
|
||||
and len(self.westSide .coreWires) \
|
||||
and not self.southSide.coreWires[0].inCoronaRange \
|
||||
and not self.westSide .coreWires[0].inCoronaRange:
|
||||
print ErrorMessage( 1, [ 'Corona._placeInnerCorona(): Both pads on south-east corner are outside corona range.'
|
||||
, 'This will generate a short-circuit between S:"%s" and W:"%s".' % \
|
||||
( self.southSide.coreWires[0].chipNet.getName()
|
||||
, self.westSide .coreWires[0].chipNet.getName()) ] )
|
||||
|
||||
if len(self.southSide.coreWires) \
|
||||
and len(self.eastSide .coreWires) \
|
||||
and not self.southSide.coreWires[-1].inCoronaRange \
|
||||
and not self.eastSide .coreWires[ 0].inCoronaRange:
|
||||
print ErrorMessage( 1, [ 'Corona._placeInnerCorona(): Both pads on south-west corner are outside corona range.'
|
||||
, 'This will generate a short-circuit between S:"%s" and E:"%s.' % \
|
||||
( self.southSide.coreWires[-1].chipNet.getName()
|
||||
, self.eastSide .coreWires[ 0].chipNet.getName()) ] )
|
||||
|
||||
if len(self.northSide.coreWires) \
|
||||
and len(self.westSide .coreWires) \
|
||||
and not self.northSide.coreWires[ 0].inCoronaRange \
|
||||
and not self.westSide .coreWires[-1].inCoronaRange:
|
||||
print ErrorMessage( 1, [ 'Corona._placeInnerCorona(): Both pads on north-east corner are outside corona range.'
|
||||
, 'This will generate a short-circuit between N:"%s" and W:"%s".' % \
|
||||
( self.northSide.coreWires[ 0].chipNet.getName()
|
||||
, self.westSide .coreWires[-1].chipNet.getName()) ] )
|
||||
|
||||
if len(self.northSide.coreWires) \
|
||||
and len(self.eastSide .coreWires) \
|
||||
and not self.northSide.coreWires[-1].inCoronaRange \
|
||||
and not self.eastSide .coreWires[-1].inCoronaRange:
|
||||
print ErrorMessage( 1, [ 'Corona._placeInnerCorona(): Both pads on north-west corner are outside corona range.'
|
||||
, 'This will generate a short-circuit between N:"%s" and E:"%s.' % \
|
||||
( self.northSide.coreWires[-1].chipNet.getName()
|
||||
, self.eastSide .coreWires[-1].chipNet.getName()) ] )
|
||||
|
||||
return
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@ if __name__ == '__main__':
|
|||
parser.add_option( '-M', '--dump-measures' , action='store_true', dest='dumpMeasures' , help='Dump some statistical measurements on the disk.')
|
||||
parser.add_option( '-s', '--save-design' , type='string' , dest='saveDesign' , help='Save the routed design.')
|
||||
parser.add_option( '--top-routing-layer', type='string' , dest='topRoutingLayer', help='Sets the top (upper) routing layer.')
|
||||
parser.add_option( '--vst-use-concat' , action='store_true', dest='vstUseConcat' , help='The VST driver will use "&" (concat) in PORT MAP.')
|
||||
(options, args) = parser.parse_args()
|
||||
args.insert(0, 'cgt')
|
||||
|
||||
|
@ -260,6 +261,7 @@ if __name__ == '__main__':
|
|||
|
||||
if options.saveDesign:
|
||||
views = CRL.Catalog.State.Physical
|
||||
if options.vstUseConcat: views |= CRL.Catalog.State.VstUseConcat
|
||||
if options.saveDesign != cell.getName():
|
||||
cell.setName(options.saveDesign)
|
||||
views |= CRL.Catalog.State.Logical
|
||||
|
|
Loading…
Reference in New Issue