Add a new RoutingLayerGauge type "PowerSupply".
* New: In CRL::RoutingLayerGauge, add a new kind of gauge "PowerSupply" to flag a layer which is dedicated to routing power supplies. * New: In AllianceFramework, add management of PowerSupply gauge kind. Exported in the Python interface.
This commit is contained in:
parent
a6492f6edc
commit
63a03bf11b
|
@ -126,6 +126,19 @@ namespace CRL {
|
||||||
{ return (getLayerGauge(layer) != NULL) or (getViaDepth(layer) != nlayerdepth); }
|
{ return (getLayerGauge(layer) != NULL) or (getViaDepth(layer) != nlayerdepth); }
|
||||||
|
|
||||||
|
|
||||||
|
RoutingLayerGauge* RoutingGauge::getPowerSupplyGauge () const
|
||||||
|
{
|
||||||
|
size_t i = _layerGauges.size();
|
||||||
|
if (i == 0) return NULL;
|
||||||
|
do {
|
||||||
|
--i;
|
||||||
|
if (_layerGauges[i]->getType() == Constant::PowerSupply)
|
||||||
|
return _layerGauges[i];
|
||||||
|
} while ( i > 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RoutingLayerGauge* RoutingGauge::getHorizontalGauge () const
|
RoutingLayerGauge* RoutingGauge::getHorizontalGauge () const
|
||||||
{
|
{
|
||||||
RoutingLayerGauge* pinOnly = NULL;
|
RoutingLayerGauge* pinOnly = NULL;
|
||||||
|
|
|
@ -51,54 +51,56 @@ namespace CRL {
|
||||||
// Constants.
|
// Constants.
|
||||||
static const size_t nlayerdepth;
|
static const size_t nlayerdepth;
|
||||||
// Constructors & Destructors.
|
// Constructors & Destructors.
|
||||||
static RoutingGauge* create ( const char* name );
|
static RoutingGauge* create ( const char* name );
|
||||||
virtual void destroy ();
|
virtual void destroy ();
|
||||||
// Predicates.
|
// Predicates.
|
||||||
inline bool isSymbolic () const;
|
inline bool isSymbolic () const;
|
||||||
inline bool isTwoMetals () const;
|
inline bool isTwoMetals () const;
|
||||||
inline bool isHV () const;
|
inline bool isHV () const;
|
||||||
inline bool isVH () const;
|
inline bool isVH () const;
|
||||||
bool hasLayer ( const Layer* ) const;
|
inline bool hasPowerSupply () const;
|
||||||
// Accessors.
|
bool hasLayer ( const Layer* ) const;
|
||||||
RoutingGauge* getClone () const;
|
// Accessors.
|
||||||
inline const Name getName () const;
|
RoutingGauge* getClone () const;
|
||||||
inline Technology* getTechnology () const;
|
inline const Name getName () const;
|
||||||
inline size_t getDepth () const;
|
inline Technology* getTechnology () const;
|
||||||
inline DbU::Unit getHorizontalPitch () const;
|
inline size_t getDepth () const;
|
||||||
inline DbU::Unit getVerticalPitch () const;
|
inline DbU::Unit getHorizontalPitch () const;
|
||||||
RoutingLayerGauge* getHorizontalGauge () const;
|
inline DbU::Unit getVerticalPitch () const;
|
||||||
RoutingLayerGauge* getVerticalGauge () const;
|
RoutingLayerGauge* getHorizontalGauge () const;
|
||||||
RoutingLayerGauge* getLayerGauge ( const Layer* ) const;
|
RoutingLayerGauge* getVerticalGauge () const;
|
||||||
size_t getViaDepth ( const Layer* ) const;
|
RoutingLayerGauge* getPowerSupplyGauge () const;
|
||||||
size_t getLayerDepth ( const Layer* ) const;
|
RoutingLayerGauge* getLayerGauge ( const Layer* ) const;
|
||||||
unsigned int getLayerType ( const Layer* ) const;
|
size_t getViaDepth ( const Layer* ) const;
|
||||||
unsigned int getLayerDirection ( const Layer* ) const;
|
size_t getLayerDepth ( const Layer* ) const;
|
||||||
DbU::Unit getPitch ( const Layer* ) const;
|
unsigned int getLayerType ( const Layer* ) const;
|
||||||
DbU::Unit getOffset ( const Layer* ) const;
|
unsigned int getLayerDirection ( const Layer* ) const;
|
||||||
DbU::Unit getWireWidth ( const Layer* ) const;
|
DbU::Unit getPitch ( const Layer* ) const;
|
||||||
DbU::Unit getPWireWidth ( const Layer* ) const;
|
DbU::Unit getOffset ( const Layer* ) const;
|
||||||
DbU::Unit getViaWidth ( const Layer* ) const;
|
DbU::Unit getWireWidth ( const Layer* ) const;
|
||||||
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
|
DbU::Unit getPWireWidth ( const Layer* ) const;
|
||||||
inline unsigned int getLayerDirection ( size_t depth ) const;
|
DbU::Unit getViaWidth ( const Layer* ) const;
|
||||||
inline unsigned int getLayerType ( size_t depth ) const;
|
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
|
||||||
inline DbU::Unit getLayerPitch ( size_t depth ) const;
|
inline unsigned int getLayerDirection ( size_t depth ) const;
|
||||||
inline DbU::Unit getLayerOffset ( size_t depth ) const;
|
inline unsigned int getLayerType ( size_t depth ) const;
|
||||||
inline DbU::Unit getLayerWireWidth ( size_t depth ) const;
|
inline DbU::Unit getLayerPitch ( size_t depth ) const;
|
||||||
inline DbU::Unit getLayerPWireWidth ( size_t depth ) const;
|
inline DbU::Unit getLayerOffset ( size_t depth ) const;
|
||||||
inline DbU::Unit getViaWidth ( size_t depth ) const;
|
inline DbU::Unit getLayerWireWidth ( size_t depth ) const;
|
||||||
const Layer* getRoutingLayer ( size_t depth ) const;
|
inline DbU::Unit getLayerPWireWidth ( size_t depth ) const;
|
||||||
Layer* getContactLayer ( size_t depth ) const;
|
inline DbU::Unit getViaWidth ( size_t depth ) const;
|
||||||
const vector<RoutingLayerGauge*>&
|
const Layer* getRoutingLayer ( size_t depth ) const;
|
||||||
getLayerGauges () const;
|
Layer* getContactLayer ( size_t depth ) const;
|
||||||
// Methods.
|
const vector<RoutingLayerGauge*>&
|
||||||
void addLayerGauge ( RoutingLayerGauge* layerGauge );
|
getLayerGauges () const;
|
||||||
void checkConnexity () const;
|
// Methods.
|
||||||
inline void setSymbolic ( bool );
|
void addLayerGauge ( RoutingLayerGauge* layerGauge );
|
||||||
// Hurricane Managment.
|
void checkConnexity () const;
|
||||||
void toJson ( JsonWriter* ) const;
|
inline void setSymbolic ( bool );
|
||||||
virtual Record* _getRecord ( Record* record=NULL ) const;
|
// Hurricane Managment.
|
||||||
virtual string _getString () const;
|
void toJson ( JsonWriter* ) const;
|
||||||
virtual string _getTypeName () const;
|
virtual Record* _getRecord ( Record* record=NULL ) const;
|
||||||
|
virtual string _getString () const;
|
||||||
|
virtual string _getTypeName () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Internal - Attributes.
|
// Internal - Attributes.
|
||||||
|
@ -121,6 +123,7 @@ namespace CRL {
|
||||||
inline bool RoutingGauge::isTwoMetals () const { return (getDepth() < 3); }
|
inline bool RoutingGauge::isTwoMetals () const { return (getDepth() < 3); }
|
||||||
inline bool RoutingGauge::isHV () const { return not isTwoMetals() and (getLayerGauge(1)->isHorizontal()); }
|
inline bool RoutingGauge::isHV () const { return not isTwoMetals() and (getLayerGauge(1)->isHorizontal()); }
|
||||||
inline bool RoutingGauge::isVH () const { return not isTwoMetals() and (getLayerGauge(1)->isVertical()); }
|
inline bool RoutingGauge::isVH () const { return not isTwoMetals() and (getLayerGauge(1)->isVertical()); }
|
||||||
|
inline bool RoutingGauge::hasPowerSupply () const { return (getPowerSupplyGauge() != NULL); }
|
||||||
inline const Name RoutingGauge::getName () const { return _name; }
|
inline const Name RoutingGauge::getName () const { return _name; }
|
||||||
inline size_t RoutingGauge::getDepth () const { return _layerGauges.size(); }
|
inline size_t RoutingGauge::getDepth () const { return _layerGauges.size(); }
|
||||||
inline Technology* RoutingGauge::getTechnology () const { return _technology; }
|
inline Technology* RoutingGauge::getTechnology () const { return _technology; }
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
#ifndef CRL_ROUTING_LAYER_GAUGE_H
|
#pragma once
|
||||||
#define CRL_ROUTING_LAYER_GAUGE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "hurricane/Commons.h"
|
#include "hurricane/Commons.h"
|
||||||
#include "hurricane/Error.h"
|
#include "hurricane/Error.h"
|
||||||
|
@ -39,6 +36,7 @@ namespace Constant {
|
||||||
|
|
||||||
enum LayerGaugeType { Default = (1<<0)
|
enum LayerGaugeType { Default = (1<<0)
|
||||||
, PinOnly = (1<<1)
|
, PinOnly = (1<<1)
|
||||||
|
, PowerSupply = (1<<2)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Round { Superior = (1<<2)
|
enum Round { Superior = (1<<2)
|
||||||
|
@ -277,8 +275,9 @@ inline std::string getString<const Constant::LayerGaugeType*>
|
||||||
( const Constant::LayerGaugeType* layerGaugeType )
|
( const Constant::LayerGaugeType* layerGaugeType )
|
||||||
{
|
{
|
||||||
switch ( *layerGaugeType ) {
|
switch ( *layerGaugeType ) {
|
||||||
case Constant::Default: return "Default";
|
case Constant::Default: return "Default";
|
||||||
case Constant::PinOnly: return "PinOnly";
|
case Constant::PinOnly: return "PinOnly";
|
||||||
|
case Constant::PowerSupply: return "PowerSupply";
|
||||||
}
|
}
|
||||||
return "Unknown Constant::LayerGaugeType";
|
return "Unknown Constant::LayerGaugeType";
|
||||||
}
|
}
|
||||||
|
@ -295,8 +294,9 @@ inline std::string getString<const Constant::LayerGaugeType>
|
||||||
( const Constant::LayerGaugeType layerGaugeType )
|
( const Constant::LayerGaugeType layerGaugeType )
|
||||||
{
|
{
|
||||||
switch ( layerGaugeType ) {
|
switch ( layerGaugeType ) {
|
||||||
case Constant::Default: return "Default";
|
case Constant::Default: return "Default";
|
||||||
case Constant::PinOnly: return "PinOnly";
|
case Constant::PinOnly: return "PinOnly";
|
||||||
|
case Constant::PowerSupply: return "PowerSupply";
|
||||||
}
|
}
|
||||||
return "Unknown Constant::LayerGaugeType";
|
return "Unknown Constant::LayerGaugeType";
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,3 @@ inline std::string getString<Constant::LayerGaugeType>
|
||||||
|
|
||||||
|
|
||||||
IOSTREAM_POINTER_SUPPORT(Constant::LayerGaugeType);
|
IOSTREAM_POINTER_SUPPORT(Constant::LayerGaugeType);
|
||||||
|
|
||||||
|
|
||||||
#endif // CRL_ROUTING_LAYER_GAUGE_H
|
|
||||||
|
|
|
@ -212,6 +212,7 @@ extern "C" {
|
||||||
|
|
||||||
PyCatalog_postModuleInit ();
|
PyCatalog_postModuleInit ();
|
||||||
PyEnvironment_postModuleInit ();
|
PyEnvironment_postModuleInit ();
|
||||||
|
PyRoutingGauge_postModuleInit ();
|
||||||
PyRoutingLayerGauge_postModuleInit ();
|
PyRoutingLayerGauge_postModuleInit ();
|
||||||
PyAllianceFramework_postModuleInit ();
|
PyAllianceFramework_postModuleInit ();
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,19 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyRoutingGauge_getPowerSupplyGauge ( PyRoutingGauge* self )
|
||||||
|
{
|
||||||
|
cdebug_log(30,0) << "PyRoutingGauge_getPowerSupplyGauge()" << endl;
|
||||||
|
RoutingLayerGauge* rlg = NULL;
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD("RoutingGauge.getPowerSupplyGauge()")
|
||||||
|
rlg = rg->getPowerSupplyGauge();
|
||||||
|
if (not rlg) Py_RETURN_NONE;
|
||||||
|
HCATCH
|
||||||
|
return PyRoutingLayerGauge_Link( rlg );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject* PyRoutingGauge_getRoutingLayer ( PyRoutingGauge* self, PyObject* args )
|
static PyObject* PyRoutingGauge_getRoutingLayer ( PyRoutingGauge* self, PyObject* args )
|
||||||
{
|
{
|
||||||
cdebug_log(30,0) << "PyRoutingGauge_getRoutingLayer()" << endl;
|
cdebug_log(30,0) << "PyRoutingGauge_getRoutingLayer()" << endl;
|
||||||
|
@ -490,10 +503,11 @@ extern "C" {
|
||||||
// Standard Attributes.
|
// Standard Attributes.
|
||||||
GetNameMethod(RoutingGauge,rg)
|
GetNameMethod(RoutingGauge,rg)
|
||||||
accessorVectorFromVoid(getLayerGauges,PyRoutingGauge,RoutingGauge,RoutingLayerGauge)
|
accessorVectorFromVoid(getLayerGauges,PyRoutingGauge,RoutingGauge,RoutingLayerGauge)
|
||||||
DirectGetBoolAttribute(PyRoutingGauge_isSymbolic ,isSymbolic ,PyRoutingGauge,RoutingGauge)
|
DirectGetBoolAttribute(PyRoutingGauge_isSymbolic ,isSymbolic ,PyRoutingGauge,RoutingGauge)
|
||||||
DirectSetBoolAttribute(PyRoutingGauge_setSymbolic,setSymbolic,PyRoutingGauge,RoutingGauge)
|
DirectSetBoolAttribute(PyRoutingGauge_setSymbolic ,setSymbolic ,PyRoutingGauge,RoutingGauge)
|
||||||
DirectGetBoolAttribute(PyRoutingGauge_isHV ,isHV ,PyRoutingGauge,RoutingGauge)
|
DirectGetBoolAttribute(PyRoutingGauge_isHV ,isHV ,PyRoutingGauge,RoutingGauge)
|
||||||
DirectGetBoolAttribute(PyRoutingGauge_isVH ,isVH ,PyRoutingGauge,RoutingGauge)
|
DirectGetBoolAttribute(PyRoutingGauge_isVH ,isVH ,PyRoutingGauge,RoutingGauge)
|
||||||
|
DirectGetBoolAttribute(PyRoutingGauge_hasPowerSupply,hasPowerSupply,PyRoutingGauge,RoutingGauge)
|
||||||
|
|
||||||
|
|
||||||
// Standart Destroy (Attribute).
|
// Standart Destroy (Attribute).
|
||||||
|
@ -508,6 +522,8 @@ extern "C" {
|
||||||
, "The first routing layer (metal2) is horizontal." }
|
, "The first routing layer (metal2) is horizontal." }
|
||||||
, { "isVH" , (PyCFunction)PyRoutingGauge_isVH , METH_NOARGS
|
, { "isVH" , (PyCFunction)PyRoutingGauge_isVH , METH_NOARGS
|
||||||
, "The first routing layer (metal2) is vertical." }
|
, "The first routing layer (metal2) is vertical." }
|
||||||
|
, { "hasPowerSupply" , (PyCFunction)PyRoutingGauge_hasPowerSupply , METH_NOARGS
|
||||||
|
, "Is there a dedicated layer for power supplies." }
|
||||||
, { "getName" , (PyCFunction)PyRoutingGauge_getName , METH_NOARGS
|
, { "getName" , (PyCFunction)PyRoutingGauge_getName , METH_NOARGS
|
||||||
, "Return the maximum depth of the RoutingGauge." }
|
, "Return the maximum depth of the RoutingGauge." }
|
||||||
, { "getTechnology" , (PyCFunction)PyRoutingGauge_getTechnology , METH_NOARGS
|
, { "getTechnology" , (PyCFunction)PyRoutingGauge_getTechnology , METH_NOARGS
|
||||||
|
@ -522,12 +538,14 @@ extern "C" {
|
||||||
, "Return the depth of the given layer." }
|
, "Return the depth of the given layer." }
|
||||||
, { "getPitch" , (PyCFunction)PyRoutingGauge_getPitch , METH_VARARGS
|
, { "getPitch" , (PyCFunction)PyRoutingGauge_getPitch , METH_VARARGS
|
||||||
, "Return the routing pitch of the given layer." }
|
, "Return the routing pitch of the given layer." }
|
||||||
, { "getOffset" , (PyCFunction)PyRoutingGauge_getOffset , METH_VARARGS
|
, { "getOffset" , (PyCFunction)PyRoutingGauge_getOffset , METH_VARARGS
|
||||||
, "Return the offset of the first track of the given layer." }
|
, "Return the offset of the first track of the given layer." }
|
||||||
, { "getWireWidth" , (PyCFunction)PyRoutingGauge_getWireWidth , METH_VARARGS
|
, { "getWireWidth" , (PyCFunction)PyRoutingGauge_getWireWidth , METH_VARARGS
|
||||||
, "Return the default wire width of the given layer." }
|
, "Return the default wire width of the given layer." }
|
||||||
, { "getViaWidth" , (PyCFunction)PyRoutingGauge_getViaWidth , METH_VARARGS
|
, { "getViaWidth" , (PyCFunction)PyRoutingGauge_getViaWidth , METH_VARARGS
|
||||||
, "Return the default via width of the given layer." }
|
, "Return the default via width of the given layer." }
|
||||||
|
, { "getPowerSupplyGauge" , (PyCFunction)PyRoutingGauge_getPowerSupplyGauge, METH_NOARGS
|
||||||
|
, "Return the power supply gauge (None if there isn't)." }
|
||||||
, { "getLayerGauge" , (PyCFunction)PyRoutingGauge_getLayerGauge , METH_VARARGS
|
, { "getLayerGauge" , (PyCFunction)PyRoutingGauge_getLayerGauge , METH_VARARGS
|
||||||
, "Return the RoutingLayerGauge of the given layer/depth." }
|
, "Return the RoutingLayerGauge of the given layer/depth." }
|
||||||
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection , METH_VARARGS
|
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection , METH_VARARGS
|
||||||
|
@ -558,6 +576,14 @@ extern "C" {
|
||||||
VectorMethods (RoutingLayerGauge)
|
VectorMethods (RoutingLayerGauge)
|
||||||
|
|
||||||
|
|
||||||
|
extern void PyRoutingGauge_postModuleInit ()
|
||||||
|
{
|
||||||
|
PyObject* constant;
|
||||||
|
|
||||||
|
LoadObjectConstant(PyTypeRoutingGauge.tp_dict,RoutingGauge::nlayerdepth,"nlayerdepth");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#else // End of Python Module Code Part.
|
#else // End of Python Module Code Part.
|
||||||
|
|
||||||
// +=================================================================+
|
// +=================================================================+
|
||||||
|
|
|
@ -108,7 +108,8 @@ extern "C" {
|
||||||
}
|
}
|
||||||
switch( type ) {
|
switch( type ) {
|
||||||
case Constant::Default:
|
case Constant::Default:
|
||||||
case Constant::PinOnly: break;
|
case Constant::PinOnly:
|
||||||
|
case Constant::PowerSupply: break;
|
||||||
default:
|
default:
|
||||||
PyErr_SetString ( ConstructorError, "Bad value for type argument of RoutingLayerGauge.create()." );
|
PyErr_SetString ( ConstructorError, "Bad value for type argument of RoutingLayerGauge.create()." );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -347,14 +348,15 @@ extern "C" {
|
||||||
{
|
{
|
||||||
PyObject* constant;
|
PyObject* constant;
|
||||||
|
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Horizontal ,"Horizontal");
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Horizontal ,"Horizontal" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Vertical ,"Vertical" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Vertical ,"Vertical" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Default ,"Default" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Default ,"Default" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::PinOnly ,"PinOnly" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::PinOnly ,"PinOnly" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Superior ,"Superior" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::PowerSupply,"PowerSupply" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Inferior ,"Inferior" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Superior ,"Superior" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Nearest ,"Nearest" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Inferior ,"Inferior" );
|
||||||
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Exact ,"Exact" );
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Nearest ,"Nearest" );
|
||||||
|
LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Exact ,"Exact" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CRL_PY_ROUTINGGAUGE__
|
#pragma once
|
||||||
#define __CRL_PY_ROUTINGGAUGE__
|
|
||||||
|
|
||||||
#include "hurricane/isobar/PyHurricane.h"
|
#include "hurricane/isobar/PyHurricane.h"
|
||||||
#include "crlcore/RoutingGauge.h"
|
#include "crlcore/RoutingGauge.h"
|
||||||
|
|
||||||
|
@ -63,6 +61,3 @@ declareVectorObject(RoutingLayerGauge);
|
||||||
|
|
||||||
|
|
||||||
} // Hurricane namespace.
|
} // Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
#endif // __CRL_PY_ROUTINGGAUGE__
|
|
||||||
|
|
Loading…
Reference in New Issue