move device to devicebackup
This commit is contained in:
parent
af659752dc
commit
686b97f1ec
|
@ -98,7 +98,7 @@ Transistor::Transistor(Library* library, const Name& name,
|
||||||
_source20(NULL), _source22(NULL),
|
_source20(NULL), _source22(NULL),
|
||||||
_drain40(NULL), _drain42(NULL),
|
_drain40(NULL), _drain42(NULL),
|
||||||
_grid00(NULL), _grid01(NULL), _grid30(NULL), _grid31(NULL),
|
_grid00(NULL), _grid01(NULL), _grid30(NULL), _grid31(NULL),
|
||||||
_anonymous10(NULL), _anonymous11(NULL), _anonymous12(NULL)
|
_anonymous10(NULL), _anonymous11(NULL), _anonymous12(NULL), _anonymous50(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,6 +145,24 @@ void Transistor::_postCreate() {
|
||||||
setTerminal(false);
|
setTerminal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Transistor::setPolarity(const Polarity& polarity) {
|
||||||
|
UpdateSession::open();
|
||||||
|
if (polarity != _polarity) {
|
||||||
|
_polarity = polarity;
|
||||||
|
DataBase* db = DataBase::getDB();
|
||||||
|
Technology* technology = db->getTechnology();
|
||||||
|
if (_polarity == Polarity::N) {
|
||||||
|
_anonymous11->setLayer(getLayer(technology, "nImplant"));
|
||||||
|
_anonymous12->setLayer(getLayer(technology, "nImplant"));
|
||||||
|
} else {
|
||||||
|
_anonymous11->setLayer(getLayer(technology, "pImplant"));
|
||||||
|
_anonymous12->setLayer(getLayer(technology, "pImplant"));
|
||||||
|
}
|
||||||
|
createLayout();
|
||||||
|
}
|
||||||
|
UpdateSession::close();
|
||||||
|
}
|
||||||
|
|
||||||
void Transistor::createLayout() {
|
void Transistor::createLayout() {
|
||||||
DataBase* db = DataBase::getDB();
|
DataBase* db = DataBase::getDB();
|
||||||
if (!db) {
|
if (!db) {
|
||||||
|
@ -168,10 +186,12 @@ void Transistor::createLayout() {
|
||||||
getLayer(techno, "cut0"), getLayer(techno, "active"))->getValue();
|
getLayer(techno, "cut0"), getLayer(techno, "active"))->getValue();
|
||||||
DbU::Unit spacingActivePoly = atechno->getPhysicalRule("minSpacing",
|
DbU::Unit spacingActivePoly = atechno->getPhysicalRule("minSpacing",
|
||||||
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
|
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
|
||||||
DbU::Unit sourceDrainWidth = atechno->getPhysicalRule("minSourceDrainWidth",
|
DbU::Unit sourceDrainWidth = atechno->getPhysicalRule("minExtension",
|
||||||
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
|
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
|
||||||
DbU::Unit extActiveCut0 = atechno->getPhysicalRule("minExtension",
|
DbU::Unit extActiveCut0 = atechno->getPhysicalRule("minExtension",
|
||||||
getLayer(techno, "active"), getLayer(techno, "cut0"))->getValue();
|
getLayer(techno, "active"), getLayer(techno, "cut0"))->getValue();
|
||||||
|
DbU::Unit enclosurePPlusActive = atechno->getPhysicalRule("minEnclosure",
|
||||||
|
getLayer(techno, "nWell"), getLayer(techno, "active"))->getValue();
|
||||||
DbU::Unit enclosureImplantPoly = 0;
|
DbU::Unit enclosureImplantPoly = 0;
|
||||||
DbU::Unit enclosureGateImplant = 0;
|
DbU::Unit enclosureGateImplant = 0;
|
||||||
DbU::Unit extImplantActive = 0;
|
DbU::Unit extImplantActive = 0;
|
||||||
|
@ -289,6 +309,7 @@ void Transistor::createLayout() {
|
||||||
DbU::Unit dx23 = x10;
|
DbU::Unit dx23 = x10;
|
||||||
DbU::Unit dy23 = _w;
|
DbU::Unit dy23 = _w;
|
||||||
|
|
||||||
|
|
||||||
//_anonymous11
|
//_anonymous11
|
||||||
DbU::Unit extension11_1 = enclosureGateImplant;
|
DbU::Unit extension11_1 = enclosureGateImplant;
|
||||||
DbU::Unit extension11_2 = extImplantCut0 - x20;
|
DbU::Unit extension11_2 = extImplantCut0 - x20;
|
||||||
|
@ -296,7 +317,7 @@ void Transistor::createLayout() {
|
||||||
|
|
||||||
DbU::Unit extension11_4 = max(max(extension11_1, extension11_2), extension11_3);
|
DbU::Unit extension11_4 = max(max(extension11_1, extension11_2), extension11_3);
|
||||||
|
|
||||||
DbU::Unit x11 = extension11_4;
|
DbU::Unit x11 = -extension11_4;
|
||||||
|
|
||||||
extension11_1 = enclosureGateImplant + x00 + dx00;
|
extension11_1 = enclosureGateImplant + x00 + dx00;
|
||||||
extension11_2 = extImplantCut0 + x40 + dx40;
|
extension11_2 = extImplantCut0 + x40 + dx40;
|
||||||
|
@ -312,9 +333,24 @@ void Transistor::createLayout() {
|
||||||
Box box11(x11, y11, x11 + dx11, y11 + dy11);
|
Box box11(x11, y11, x11 + dx11, y11 + dy11);
|
||||||
_anonymous11->setBoundingBox(box11);
|
_anonymous11->setBoundingBox(box11);
|
||||||
|
|
||||||
#if 0
|
if (_polarity == Polarity::P) {
|
||||||
|
DbU::Unit x50 = x10 - enclosurePPlusActive;
|
||||||
|
DbU::Unit y50 = y10 - enclosurePPlusActive;
|
||||||
|
DbU::Unit dx50 = dx10 + 2 * enclosurePPlusActive;
|
||||||
|
DbU::Unit dy50 = dy10 + 2 * enclosurePPlusActive;
|
||||||
|
Box box50(x50, y50, x50 + dx50, y50 + dy50);
|
||||||
|
if (!_anonymous50) {
|
||||||
|
_anonymous50 = createPad(techno, _anonymous, "nWell");
|
||||||
|
}
|
||||||
|
_anonymous50->setBoundingBox(box50);
|
||||||
|
} else {
|
||||||
|
if (_anonymous50) {
|
||||||
|
_anonymous50->destroy();
|
||||||
|
_anonymous50 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//setAbutmentBox(getAbutmentBox());
|
//setAbutmentBox(getAbutmentBox());
|
||||||
#endif
|
|
||||||
UpdateSession::close();
|
UpdateSession::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ class Transistor : public Cell {
|
||||||
bool isRight() const { return _abutmentType == AbutmentType::RIGHT; };
|
bool isRight() const { return _abutmentType == AbutmentType::RIGHT; };
|
||||||
bool isSingle() const { return _abutmentType == AbutmentType::SINGLE; };
|
bool isSingle() const { return _abutmentType == AbutmentType::SINGLE; };
|
||||||
|
|
||||||
|
void setW(DbU::Unit value) { _w = value; createLayout(); }
|
||||||
|
void setL(DbU::Unit value) { _l = value; createLayout(); }
|
||||||
|
void setPolarity(const Polarity& polarity);
|
||||||
|
|
||||||
virtual Record* _getRecord() const;
|
virtual Record* _getRecord() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -75,7 +79,7 @@ class Transistor : public Cell {
|
||||||
Pad *_source20, *_source22;
|
Pad *_source20, *_source22;
|
||||||
Pad *_drain40, *_drain42;
|
Pad *_drain40, *_drain42;
|
||||||
Pad *_grid00, *_grid01, *_grid30, *_grid31;
|
Pad *_grid00, *_grid01, *_grid30, *_grid31;
|
||||||
Pad *_anonymous10, *_anonymous11, *_anonymous12;
|
Pad *_anonymous10, *_anonymous11, *_anonymous12, *_anonymous50;
|
||||||
|
|
||||||
Transistor(Library* library, const Name& name,
|
Transistor(Library* library, const Name& name,
|
||||||
const Polarity& polarity,
|
const Polarity& polarity,
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
INCLUDE_DIRECTORIES(${CHAMSIN_SOURCE_DIR}/src/dtr ${CHAMSIN_SOURCE_DIR}/src/analogic
|
||||||
|
${HURRICANE_INCLUDE_DIR})
|
||||||
|
|
||||||
|
#ADD_LIBRARY(device SHARED Device.cpp TrMos.cpp TrMos_PlaceRoute.cpp)
|
||||||
|
#
|
||||||
|
#TARGET_LINK_LIBRARIES(device analogic dtr hurricane)
|
||||||
|
#
|
||||||
|
#INSTALL(TARGETS device DESTINATION /lib)
|
|
@ -0,0 +1,161 @@
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// File: Device.cpp
|
||||||
|
// Authors: Wu YiFei
|
||||||
|
// Date : 21/12/2006
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#include "Device.h"
|
||||||
|
|
||||||
|
#include "Transformation.h"
|
||||||
|
#include "Point.h"
|
||||||
|
#include "Instance.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
|
#include "Cells.h"
|
||||||
|
#include "DtrAccess.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// Static data function
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
static Instance * refins = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static set<Cell*> cellSet;
|
||||||
|
|
||||||
|
|
||||||
|
static void getAllCells(Cell* cell)
|
||||||
|
// ********************************
|
||||||
|
{
|
||||||
|
cellSet.insert(cell);
|
||||||
|
|
||||||
|
if(!(cell->isLeaf())){
|
||||||
|
for_each_instance(instance, cell->getInstances())
|
||||||
|
Cell * mastercell = instance->getMasterCell();
|
||||||
|
getAllCells(mastercell);
|
||||||
|
end_for
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace DEVICE {
|
||||||
|
|
||||||
|
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// Device implementation
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
Device::Device(Library* library, const Name& name)
|
||||||
|
// **************************************************************************
|
||||||
|
: Inherit(library, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Device::_postCreate() {
|
||||||
|
Inherit::_postCreate();
|
||||||
|
|
||||||
|
//CDataBase* database = getCDataBase();
|
||||||
|
//CCatal* ccatal = database->getCCatal();
|
||||||
|
|
||||||
|
//CCatal::State* state = ccatal->getState(getName(), true);
|
||||||
|
//state->SetFlags(CCatal::State::LOGICAL|CCatal::State::PHYSICAL|CCatal::State::IN_MEMORY|CCatal::State::GDS, true);
|
||||||
|
//state->SetCell(this);
|
||||||
|
//state->SetLibrary(getLibrary());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Device::SaveLogicalView()
|
||||||
|
// ***************************
|
||||||
|
{
|
||||||
|
cellSet.clear();
|
||||||
|
getAllCells(this);
|
||||||
|
|
||||||
|
//CDataBase * db = getCDataBase();
|
||||||
|
|
||||||
|
// set<Cell*>::iterator i = cellSet.begin(), j = cellSet.end();
|
||||||
|
//
|
||||||
|
// while(i!=j) {
|
||||||
|
// db->SaveCell(*i, CCatal::State::LOGICAL );
|
||||||
|
// i++;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::_Place(Instance* ins, const Transformation::Orientation& orientation, const Point& point)
|
||||||
|
// **************************************************************************************************
|
||||||
|
{
|
||||||
|
if(!ins) {
|
||||||
|
throw Error("Can't Place Instance : ins is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ins->isPlaced()) {
|
||||||
|
throw Error("Can't Place " + getString(ins) + " : it has already been placed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Transformation transformation(Point(0,0), orientation);
|
||||||
|
Box orientedmastercellbox = transformation.getBox(ins->getMasterCell()->getAbutmentBox());
|
||||||
|
|
||||||
|
Point translation( point.getX() - orientedmastercellbox.getXMin()
|
||||||
|
, point.getY() - orientedmastercellbox.getYMin() );
|
||||||
|
|
||||||
|
Transformation transformation_ins = Transformation(translation, orientation);
|
||||||
|
|
||||||
|
ins->setTransformation(transformation_ins);
|
||||||
|
ins->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Device::_setRefIns(Instance* ins) const
|
||||||
|
// *****************************************
|
||||||
|
{
|
||||||
|
if(!ins) {
|
||||||
|
throw Error("Can't SetRefIns : ref instance is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ins->isUnplaced()) {
|
||||||
|
throw Error("Can't SetRefIns : ref instance has't been placed");
|
||||||
|
}
|
||||||
|
|
||||||
|
refins = ins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Device::_PlaceRight(Instance* ins, const Transformation::Orientation& orientation, const Point& offset)
|
||||||
|
// ********************************************************************************************************
|
||||||
|
{
|
||||||
|
if(!ins) {
|
||||||
|
throw Error("Can't PlaceRight Instance : ins is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ins->isPlaced()) {
|
||||||
|
throw Error("Can't PlaceRight " + getString(ins) + " : it has already been placed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!refins) {
|
||||||
|
throw Error("Can't Place Right " + getString(ins) + " : can't find refins");
|
||||||
|
}
|
||||||
|
|
||||||
|
Box refinsbox = refins->getAbutmentBox();
|
||||||
|
|
||||||
|
Transformation transformation(Point(0,0), orientation);
|
||||||
|
Box orientedmastercellbox = transformation.getBox(ins->getMasterCell()->getAbutmentBox());
|
||||||
|
|
||||||
|
Point translation( refinsbox.getXMax() - orientedmastercellbox.getXMin() + offset.getX()
|
||||||
|
, refinsbox.getYMin() - orientedmastercellbox.getYMin() + offset.getY() );
|
||||||
|
|
||||||
|
Transformation transformation_ins = Transformation(translation, orientation);
|
||||||
|
|
||||||
|
ins->setTransformation(transformation_ins);
|
||||||
|
ins->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
||||||
|
|
||||||
|
refins = ins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace Device
|
|
@ -0,0 +1,71 @@
|
||||||
|
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// File: Device.h
|
||||||
|
// Authors: Wu YiFei
|
||||||
|
// Date : 21/12/2006
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
#ifndef DEVICE_H
|
||||||
|
#define DEVICE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "Cell.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
namespace DEVICE {
|
||||||
|
|
||||||
|
class Device : public Cell {
|
||||||
|
|
||||||
|
#if !defined(__DOXYGEN_PROCESSOR__)
|
||||||
|
// Types
|
||||||
|
// *****
|
||||||
|
public : typedef Cell Inherit;
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
// **********
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
// ************
|
||||||
|
protected : Device(Library* library, const Name& name);
|
||||||
|
protected : virtual void _postCreate();
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Operations
|
||||||
|
// **********
|
||||||
|
// public : virtual void Create(const char, const bool) = 0;
|
||||||
|
public : virtual void dses() = 0;
|
||||||
|
public : virtual void shape() = 0;
|
||||||
|
// public : virtual void Generate() = 0;
|
||||||
|
|
||||||
|
|
||||||
|
# if !defined(__DOXYGEN_PROCESSOR__)
|
||||||
|
public : virtual void SaveLogicalView();
|
||||||
|
public : virtual void SavePhysicalView() {};
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
// *********
|
||||||
|
|
||||||
|
// Updators
|
||||||
|
// ********
|
||||||
|
|
||||||
|
// Others
|
||||||
|
// ******
|
||||||
|
public : virtual void _Flush() = 0;
|
||||||
|
|
||||||
|
// Description of Layout
|
||||||
|
// **********************
|
||||||
|
public: void _Place(Instance* ins, const Transformation::Orientation& orientation, const Point& point);
|
||||||
|
public: void _setRefIns(Instance*) const;
|
||||||
|
public: void _PlaceRight(Instance* ins, const Transformation::Orientation& orientation, const Point& offset=Point());
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DEVICE_H
|
|
@ -0,0 +1,417 @@
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// File: TrMos.cpp
|
||||||
|
// Authors: Wu YiFei
|
||||||
|
// Date : 21/12/2006
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
#include "Instance.h"
|
||||||
|
#include "MetaTransistor.h"
|
||||||
|
#include "Net.h"
|
||||||
|
#include "Transistor.h"
|
||||||
|
#include "Transistors.h"
|
||||||
|
|
||||||
|
#include "UpdateSession.h"
|
||||||
|
|
||||||
|
#include "DtrAccess.h"
|
||||||
|
|
||||||
|
#include "TrMos.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DEVICE {
|
||||||
|
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// TrMos implementation
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
TrMos::TrMos(Library* library, const Name& name):
|
||||||
|
Device(library, name),
|
||||||
|
_polarity(Transistor::N),
|
||||||
|
_isBsConnected(false),
|
||||||
|
_m(1),
|
||||||
|
_sourceIsFirst(true),
|
||||||
|
_hasDummy(false),
|
||||||
|
_hasRing(true),
|
||||||
|
_tr1(NULL),
|
||||||
|
_capaRouting(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
TrMos* TrMos::create(Library* library, const Name & name) {
|
||||||
|
TrMos* trmos= new TrMos(library, name);
|
||||||
|
trmos->_postCreate();
|
||||||
|
return trmos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrMos::_postCreate() {
|
||||||
|
Inherit::_postCreate();
|
||||||
|
|
||||||
|
// do something.
|
||||||
|
// Initialize pin order list and other attributes.
|
||||||
|
// **********************************************
|
||||||
|
// _lowPinOrder[0]=D;
|
||||||
|
// _lowPinOrder[1]=G;
|
||||||
|
|
||||||
|
// _highPinOrder[0]=S;
|
||||||
|
// _highPinOrder[1]=B;
|
||||||
|
|
||||||
|
_highPinOrder.push_back(D);
|
||||||
|
_highPinOrder.push_back(G);
|
||||||
|
|
||||||
|
_lowPinOrder.push_back(S);
|
||||||
|
_lowPinOrder.push_back(B);
|
||||||
|
|
||||||
|
double minWidth = (DtrAccess::getDtrAccess())->getSingleRealRuleByLabel(string("RW_ALU1"));
|
||||||
|
|
||||||
|
_widthOfSourceWire = minWidth;
|
||||||
|
_widthOfDrainWire = minWidth;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrMos::create(const Transistor::Polarity& polarity, const bool isbsconnected)
|
||||||
|
{
|
||||||
|
if( _tr1 ) {
|
||||||
|
throw Error("Can't Create Logical View of TrMos " + getString(getName()) +
|
||||||
|
" : " + "it has already been created");
|
||||||
|
}
|
||||||
|
|
||||||
|
_polarity = polarity;
|
||||||
|
_isBsConnected = isbsconnected;
|
||||||
|
|
||||||
|
// MetaTransistor is in the same library than Trmos
|
||||||
|
// ************************************************
|
||||||
|
Library * library = getLibrary();
|
||||||
|
|
||||||
|
// Create signals
|
||||||
|
// **************
|
||||||
|
Net * drain = NULL;
|
||||||
|
Net * source = NULL;
|
||||||
|
Net * grid = NULL;
|
||||||
|
Net * bulk = NULL;
|
||||||
|
|
||||||
|
(drain = Net::create(this, Name("drain")))->setExternal(true);
|
||||||
|
(source = Net::create(this, Name("source")))->setExternal(true);
|
||||||
|
(grid = Net::create(this, Name("grid")))->setExternal(true);
|
||||||
|
|
||||||
|
if(!isbsconnected) {
|
||||||
|
(bulk = Net::create(this, Name("bulk")))->setExternal(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Instancier a MetaTransistor and create the connection
|
||||||
|
// The name of MetaTransistor is nameoftrmos_tr1
|
||||||
|
// ****************************************************
|
||||||
|
|
||||||
|
_tr1 = MetaTransistor::create(library, Name( getString(getName())+"_Mos1" ), _polarity);
|
||||||
|
Instance * instance = Instance::create(this,
|
||||||
|
Name("Ins_" + getString(_tr1->getName())),
|
||||||
|
_tr1);
|
||||||
|
|
||||||
|
instance->getPlug(_tr1->getNet(Name("DRAIN")))->setNet(drain);
|
||||||
|
instance->getPlug(_tr1->getNet(Name("SOURCE")))->setNet(source);
|
||||||
|
instance->getPlug(_tr1->getNet(Name("GRID")))->setNet(grid);
|
||||||
|
|
||||||
|
if(!isbsconnected)
|
||||||
|
instance->getPlug(_tr1->getNet(Name("BULK")))->setNet(bulk);
|
||||||
|
else
|
||||||
|
instance->getPlug(_tr1->getNet(Name("BULK")))->setNet(source);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrMos::generate(const unsigned m, const bool sourceisfirst, const bool hasring
|
||||||
|
, const unsigned nbsourcecolumn, const unsigned nbdraincolumn)
|
||||||
|
// *********************************************************************************
|
||||||
|
{
|
||||||
|
if( !_tr1 ) {
|
||||||
|
throw Error("Can't Create Physical View for " + getString(this) +
|
||||||
|
" : " + "Logical view has't been created yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if( !(_transistorList.empty()) ) {
|
||||||
|
// throw Error("Can't Create Physical View of TrMos " + getString(getName()) + " : "
|
||||||
|
// + "it has already been created");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Check out param of realization.
|
||||||
|
// *******************************
|
||||||
|
if( m <= 0 )
|
||||||
|
throw Error("Can't generate for " + getString(this) + " : m "
|
||||||
|
+ getString(m) + " is invalid.");
|
||||||
|
|
||||||
|
if(nbsourcecolumn<1)
|
||||||
|
throw Error("Can't generate for " + getString(this)
|
||||||
|
+ " : nbsourcecolumn " + getString(nbsourcecolumn) + " is invalid.");
|
||||||
|
|
||||||
|
if(nbdraincolumn<1)
|
||||||
|
throw Error("Can't generate for" + getString(this) + " : nbdraincolumn "
|
||||||
|
+ getString(nbdraincolumn) + " is invalid.");
|
||||||
|
|
||||||
|
|
||||||
|
if(!(_transistorList.empty())) {
|
||||||
|
_Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
_m = m;
|
||||||
|
_sourceIsFirst = sourceisfirst;
|
||||||
|
_hasRing = hasring;
|
||||||
|
|
||||||
|
// Motifs are in the same library than Trmos
|
||||||
|
// *****************************************
|
||||||
|
Library * library = getLibrary();
|
||||||
|
|
||||||
|
cout << "################################################################" << endl <<
|
||||||
|
"#### BEGIN AUTOGENERATON FOR " + _getTypeName() + " " + getString(getName()) + " #####" << endl <<
|
||||||
|
"################################################################" << endl << endl;
|
||||||
|
|
||||||
|
// OpenUpdateSession();
|
||||||
|
|
||||||
|
/* (1) */
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 1 : CreateLayout of " + getString(this) + " Begin ***" <<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
// Create Motifs according to m, and instance the Motifs according
|
||||||
|
// to the Meta-Transistor .
|
||||||
|
// Set m of MetaTransistor.
|
||||||
|
// The name of motif is nameofDevice_nameofMetaTrans_finger_index
|
||||||
|
// ****************************************************************
|
||||||
|
_tr1->setM(_m);
|
||||||
|
|
||||||
|
for(unsigned i=0; i<m; i++){
|
||||||
|
Transistor* finger = Transistor::create(library,
|
||||||
|
getString(_tr1->getName()) + "_Finger_" + getString(i),
|
||||||
|
_polarity);
|
||||||
|
|
||||||
|
_transistorList.push_back(finger);
|
||||||
|
Instance::create(_tr1, Name("Ins_" + getString(finger->getName())), finger);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
|
||||||
|
cout << "*** Stage 1 : CreateLayout of " + getString(this) + " finish ***" <<endl;
|
||||||
|
cout << getString(_tr1) + " 's M is " + getString(_tr1->getM()) + ".\n"
|
||||||
|
<< getString(_m) + " Transistors are created.\n" <<endl;
|
||||||
|
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
/* (2) */
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 2 : CreateLayout of " + getString(this) + " Begin ***" <<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
// Create connexion for each MetaTransistor.
|
||||||
|
// *****************************************
|
||||||
|
_tr1->createConnection();
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 2 : CreateLayout of " + getString(this) + " finish ***" <<endl;
|
||||||
|
cout << " The connection in " + getString(_tr1) + " is created.\n"
|
||||||
|
<<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
// Pseudo dimensionnement of metatransistor.
|
||||||
|
// In the futur, this will be the work of auto-dimensionnement tool (DSES).
|
||||||
|
// ************************************************************************
|
||||||
|
// _tr1->setLe(10);
|
||||||
|
// _tr1->setWe(11);
|
||||||
|
|
||||||
|
/* (3) */
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 3 : CreateLayout of " + getString(this) + " Begin ***" <<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
// Set dessin Parameter of generation for each finger.
|
||||||
|
// ***************************************************
|
||||||
|
double l_finger = _tr1->getLe() ;
|
||||||
|
double w_finger = (_tr1->getWe()) / (double)(_tr1->getM()) ;
|
||||||
|
unsigned count = 0;
|
||||||
|
|
||||||
|
Transistor::MaskV1Info * masqueinfo = new Transistor::MaskV1Info(l_finger, w_finger);
|
||||||
|
masqueinfo->setNbSourceColumn(nbsourcecolumn);
|
||||||
|
masqueinfo->setNbDrainColumn(nbdraincolumn);
|
||||||
|
|
||||||
|
list<Transistor*>::iterator i = _transistorList.begin()
|
||||||
|
, j = _transistorList.end();
|
||||||
|
|
||||||
|
if(_m == 1) {
|
||||||
|
masqueinfo->setType(Transistor::Type::SINGLE);
|
||||||
|
(*(_transistorList.begin()))->setMaskInfo(masqueinfo);
|
||||||
|
} else if(_m%2==0) { // if m is pair, create two left fingers if is source first.
|
||||||
|
// and create two right fingers if is drain first.
|
||||||
|
while(i!=j) {
|
||||||
|
if(++count>2)
|
||||||
|
masqueinfo->setType(Transistor::Type::INTERNAL);
|
||||||
|
else {
|
||||||
|
if ( _sourceIsFirst )
|
||||||
|
masqueinfo->setType(Transistor::Type::LEFT);
|
||||||
|
else
|
||||||
|
masqueinfo->setType(Transistor::Type::RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*i)->setMaskInfo(masqueinfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else if(_m%2==1) { // if m is impair, create one left finger, one right finger.
|
||||||
|
while(i!=j){
|
||||||
|
++ count ;
|
||||||
|
if (count == 1)
|
||||||
|
masqueinfo-> setType(Transistor::Type::LEFT);
|
||||||
|
else if (count == 2)
|
||||||
|
masqueinfo-> setType(Transistor::Type::RIGHT);
|
||||||
|
else
|
||||||
|
masqueinfo-> setType(Transistor::Type::INTERNAL);
|
||||||
|
|
||||||
|
(*i)->setMaskInfo(masqueinfo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete masqueinfo;
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 3 : CreateLayout of " + getString(this) + " finish ***" <<endl;
|
||||||
|
cout << "Real l_finger is " + getString(l_finger) + "." << endl
|
||||||
|
<< "Real w_finger is " + getString(w_finger) + "." << endl
|
||||||
|
<<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
/* (4) */
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 4 : CreateLayout of " + getString(this) + " Begin ***" <<endl;
|
||||||
|
cout << "Call GenerateLayout for " + getString(_tr1)
|
||||||
|
+ " who will launch the generator of its fingers" << ".\n"
|
||||||
|
<<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
// Call function CreateLayout of MetaTransistor to launch the generator of finger.
|
||||||
|
// *******************************************************************************
|
||||||
|
|
||||||
|
setTerminal(false);
|
||||||
|
//
|
||||||
|
// IF_DEBUG_HUR_ANALOG
|
||||||
|
// cout << endl;
|
||||||
|
// cout << "Real l of " << (long)_tr1 << getString(_tr1) + " is " + getString(_tr1->_le) + "." << endl
|
||||||
|
// << "Real w of " << (long)_tr1 << getString(_tr1) + " is " + getString(_tr1->_we) + "." << endl
|
||||||
|
// <<endl;
|
||||||
|
// END_IF
|
||||||
|
//
|
||||||
|
_tr1->createLayout();
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << "*** Stage 4 : CreateLayout of " + getString(this) + " finish ***"<<endl
|
||||||
|
<< endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
/* (5) */
|
||||||
|
// Lauch Algo of Placement and routage selected.
|
||||||
|
// *********************************************
|
||||||
|
/* to do */
|
||||||
|
|
||||||
|
_PlaceAndRoute();
|
||||||
|
|
||||||
|
cout << " Place And Route " <<endl;
|
||||||
|
|
||||||
|
for_each_instance(instance, getInstances())
|
||||||
|
//instance->setTransformation(instance->getTransformation());
|
||||||
|
instance->unmaterialize();
|
||||||
|
instance->materialize();
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << getString(instance) <<" 's boundingBox is " << getString(instance->getBoundingBox())<<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
end_for
|
||||||
|
|
||||||
|
// CloseUpdateSession();
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << getString(this) << " 's primary (without wire) boundingBox is " << getString(getBoundingBox()) <<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
materialize();
|
||||||
|
|
||||||
|
//IF_DEBUG_HUR_ANALOG
|
||||||
|
cout << getString(this) << " 's boundingBox is " << getString(getBoundingBox()) <<endl;
|
||||||
|
//END_IF
|
||||||
|
|
||||||
|
cout << endl
|
||||||
|
<< "################################################################" <<endl
|
||||||
|
<< "#### END AUTOGENERATON FOR " + _getTypeName() + " " + getString(getName()) + " #####" <<endl
|
||||||
|
<< "################################################################" <<endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrMos::setLowPinOrder(const PinName pin1, const PinName pin2)
|
||||||
|
// ***************************************************************
|
||||||
|
{
|
||||||
|
_lowPinOrder[0]=pin1;
|
||||||
|
_lowPinOrder[1]=pin2;
|
||||||
|
|
||||||
|
vector<PinName>::iterator i = _lowPinOrder.begin(), j = _lowPinOrder.end();
|
||||||
|
|
||||||
|
cout << " Low Pin Order " << endl;
|
||||||
|
|
||||||
|
while(i!=j) {
|
||||||
|
cout << *i << endl;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrMos::setHighPinOrder(const PinName pin1, const PinName pin2)
|
||||||
|
// *****************************************************************
|
||||||
|
{
|
||||||
|
_highPinOrder[0]=pin1;
|
||||||
|
_highPinOrder[1]=pin2;
|
||||||
|
|
||||||
|
vector<PinName>::iterator i = _highPinOrder.begin(), j = _highPinOrder.end();
|
||||||
|
|
||||||
|
cout << " High Pin Order " << endl;
|
||||||
|
|
||||||
|
while(i!=j) {
|
||||||
|
cout << *i << endl;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TrMos::_Flush()
|
||||||
|
// ****************
|
||||||
|
{
|
||||||
|
if(_transistorList.empty()) {
|
||||||
|
throw Error("Can't delete Physical View of TrMos " + getString(getName()) + " : " + "il doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
_tr1->Flush();
|
||||||
|
|
||||||
|
_transistorList.clear();
|
||||||
|
|
||||||
|
// Delete all segments of TrMos
|
||||||
|
// ****************************
|
||||||
|
/* to do */
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string TrMos::_getString() const
|
||||||
|
// ***************************************
|
||||||
|
{
|
||||||
|
string s= Inherit::_getString();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Record* TrMos::_getRecord() const
|
||||||
|
// *********************************
|
||||||
|
{
|
||||||
|
Record* record = Inherit::_getRecord();
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace Device
|
|
@ -0,0 +1,126 @@
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// File: TrMos.h
|
||||||
|
// Authors: Wu YiFei
|
||||||
|
// Date : 21/12/2006
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
#ifndef TRMOS_H
|
||||||
|
#define TRMOS_H
|
||||||
|
|
||||||
|
#include "Net.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
#include "Transistor.h"
|
||||||
|
|
||||||
|
//#include "MetaTransistor.h"
|
||||||
|
#include "Device.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace DEVICE {
|
||||||
|
|
||||||
|
class TrMos : public Device {
|
||||||
|
|
||||||
|
public : enum PinName { D, G, S, B };
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
// *******************
|
||||||
|
|
||||||
|
// Structural parameter.
|
||||||
|
// ********************
|
||||||
|
private : Transistor::Polarity _polarity;
|
||||||
|
private : bool _isBsConnected;
|
||||||
|
private : unsigned _m;
|
||||||
|
|
||||||
|
// Parameter of the electric synthesis.
|
||||||
|
// ***********************************
|
||||||
|
/* to do */
|
||||||
|
|
||||||
|
// Physical parameter of realization.
|
||||||
|
// **********************************
|
||||||
|
/* Placement. */
|
||||||
|
private : bool _sourceIsFirst;
|
||||||
|
private : bool _hasDummy;
|
||||||
|
private : bool _hasRing;
|
||||||
|
|
||||||
|
/* Routing. */
|
||||||
|
private : vector<PinName> _lowPinOrder; // relative position of the connectors on the basis of the top.
|
||||||
|
private : vector<PinName> _highPinOrder;
|
||||||
|
|
||||||
|
private : map<Net*, Pin*> _mapNetToPinBoxInLeftSide;
|
||||||
|
private : map<Net*, Pin*> _mapNetToPinBoxInRightSide;
|
||||||
|
|
||||||
|
private : double _widthOfSourceWire; // by defect, minWidth, unit of valeur is Micro
|
||||||
|
private : double _widthOfDrainWire; // by defect, minWidth, unit of valeur is Micro
|
||||||
|
|
||||||
|
/* Others */
|
||||||
|
private : MetaTransistor * _tr1;
|
||||||
|
private : double _capaRouting;
|
||||||
|
private : list<Transistor*> _transistorList;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
// ************
|
||||||
|
protected : TrMos(Library* library, const Name& name);
|
||||||
|
protected : virtual void _postCreate();
|
||||||
|
|
||||||
|
public : static TrMos* create(Library* library, const Name & name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Operations
|
||||||
|
// **********
|
||||||
|
public : virtual void dses() { /* to do */};
|
||||||
|
public : virtual void shape() { /* to do */};
|
||||||
|
|
||||||
|
|
||||||
|
public : void create(const Transistor::Polarity& polarity, const bool isbsconnected);
|
||||||
|
public : void generate(const unsigned m, const bool sourceisfirst, const bool hasring,
|
||||||
|
const unsigned nbsourcecolumn, const unsigned nbdraincolumn);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
// *********
|
||||||
|
public : const Transistor::Polarity& getPolarity() const { return _polarity; };
|
||||||
|
public : unsigned getM() const { return _m; };
|
||||||
|
public : const double getWidthOfSourceWire() const { return _widthOfSourceWire; };
|
||||||
|
public : const double getWidthOfDrainWire() const { return _widthOfDrainWire; };
|
||||||
|
public : MetaTransistor* getTr1() const { return _tr1; };
|
||||||
|
|
||||||
|
// Updators
|
||||||
|
// ********
|
||||||
|
public : void setMosLength(const double length) { if(_tr1) _tr1->setLe(length); }
|
||||||
|
public : void setMosWidth(const double width) { if(_tr1) _tr1->setWe(width); }
|
||||||
|
public : void setWidthOfSourceWire(const double width) { _widthOfSourceWire = width; };
|
||||||
|
public : void setWidthOfDrainWire(const double width) { _widthOfDrainWire=width; };
|
||||||
|
public : void setLowPinOrder(const PinName, const PinName) ;
|
||||||
|
public : void setHighPinOrder(const PinName, const PinName) ;
|
||||||
|
|
||||||
|
// Predicats
|
||||||
|
// *********
|
||||||
|
public : bool isBsConnected() const { return _isBsConnected; };
|
||||||
|
public : bool sourceIsFirst() const { return _sourceIsFirst; };
|
||||||
|
public : bool hasRing() const { return _hasRing; };
|
||||||
|
|
||||||
|
|
||||||
|
# if !defined(__DOXYGEN_PROCESSOR__)
|
||||||
|
|
||||||
|
// Others
|
||||||
|
// ******
|
||||||
|
public: virtual string _getTypeName() const {return _TName("TrMos"); };
|
||||||
|
public: virtual string _getString() const;
|
||||||
|
public: virtual Record* _getRecord() const;
|
||||||
|
|
||||||
|
public: vector<PinName>& getLowPinOrder() { return _lowPinOrder; };
|
||||||
|
public: vector<PinName>& getHighPinOrder() { return _highPinOrder; };
|
||||||
|
|
||||||
|
public: map<Net*, Pin*>& getMapNetToPinBoxInLeftSide() { return _mapNetToPinBoxInLeftSide; };
|
||||||
|
public: map<Net*, Pin*>& getMapNetToPinBoxInRightSide() { return _mapNetToPinBoxInRightSide; };
|
||||||
|
|
||||||
|
public : virtual void _Flush();
|
||||||
|
protected : void _PlaceAndRoute();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TRMOS_H
|
|
@ -0,0 +1,685 @@
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// File: TrMos.cpp
|
||||||
|
// Authors: Wu YiFei
|
||||||
|
// Date : 21/12/2006
|
||||||
|
// ****************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#include "TrMos.h"
|
||||||
|
|
||||||
|
#include "Instances.h"
|
||||||
|
#include "MetaTransistor.h"
|
||||||
|
#include "Net.h"
|
||||||
|
#include "Transistors.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include "UpdateSession.h"
|
||||||
|
#include "HyperNet.h"
|
||||||
|
#include "DataBase.h"
|
||||||
|
#include "Technology.h"
|
||||||
|
#include "Vertical.h"
|
||||||
|
#include "Horizontal.h"
|
||||||
|
#include "Pin.h"
|
||||||
|
|
||||||
|
#include "RdsUnit.h"
|
||||||
|
#include "Transistor.h"
|
||||||
|
#include "DtrAccess.h"
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "DeviceUtil.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace DEVICE{
|
||||||
|
|
||||||
|
|
||||||
|
// ****************************************************************************************************
|
||||||
|
// TrMos implementation
|
||||||
|
// ****************************************************************************************************
|
||||||
|
void TrMos::_PlaceAndRoute()
|
||||||
|
// *************************
|
||||||
|
{
|
||||||
|
|
||||||
|
// get Dtr Rules And Calculate the Size of AbutmentBox of Device.
|
||||||
|
// **************************************************************
|
||||||
|
DtrAccess * dtraccess = DtrAccess::getDtrAccess();
|
||||||
|
|
||||||
|
Transistor::Polarity polarity;
|
||||||
|
if(_polarity == Transistor::Polarity::P) polarity = Transistor::Polarity::N;
|
||||||
|
else polarity = Transistor::Polarity::P;
|
||||||
|
|
||||||
|
long minImpWidth = dtraccess->getSingleRdsRuleByLabel("RW_", getString(polarity), "IMP");
|
||||||
|
long minContWidth = dtraccess->getSingleRdsRuleByLabel(string("RW_CONT"));
|
||||||
|
long minAlu1Width = dtraccess->getSingleRdsRuleByLabel(string("RW_ALU1"));
|
||||||
|
long minVia1Width = dtraccess->getSingleRdsRuleByLabel(string("RW_VIA1"));
|
||||||
|
|
||||||
|
long rdImp = dtraccess->getSingleRdsRuleByLabel(string("RD_NIMP"));
|
||||||
|
long rdActive = dtraccess->getSingleRdsRuleByLabel(string("RD_ACTI"));
|
||||||
|
long rdAlu2 = dtraccess->getSingleRdsRuleByLabel(string("RD_ALU1"));
|
||||||
|
|
||||||
|
long reImpActi = dtraccess->getSingleRdsRuleByLabel("RE_", getString(polarity), "IMP_CONT");
|
||||||
|
long reActiContact = dtraccess->getSingleRdsRuleByLabel("RE_ACTI_CONT");
|
||||||
|
long reAlu1Contact = dtraccess->getSingleRdsRuleByLabel("RE_ALU1_CONT");
|
||||||
|
long reAlu1Via1 = dtraccess->getSingleRdsRuleByLabel("RE_ALU1_VIA1");
|
||||||
|
|
||||||
|
long minActiWidth = 2*reActiContact + minContWidth;
|
||||||
|
|
||||||
|
long widthOfSourceWire = ConvertRealToRdsUnit(_widthOfSourceWire);
|
||||||
|
long widthOfDrainWire = ConvertRealToRdsUnit(_widthOfDrainWire);
|
||||||
|
|
||||||
|
long widthOfActive = MAX_INTEGER(minActiWidth, minContWidth + 2*reActiContact);
|
||||||
|
long widthOfImp = MAX_INTEGER(widthOfActive + 2*reImpActi, minImpWidth);
|
||||||
|
|
||||||
|
|
||||||
|
// **************************************************************
|
||||||
|
// Placing .
|
||||||
|
// **************************************************************
|
||||||
|
|
||||||
|
Transformation::Orientation::Code internalTransCode = Transformation::Orientation::ID;
|
||||||
|
|
||||||
|
Unit horizontalMargin = 0; // the horizontal margin of trmos.
|
||||||
|
Unit verticalLowMargin = 0; // the vertical low margin of trmos.
|
||||||
|
Unit verticalHighMargin = 0; // the vertical high margin of trmos.
|
||||||
|
|
||||||
|
Unit fingerHeight = 0; // the height of trmos.
|
||||||
|
Instance * leftins = NULL;
|
||||||
|
Instance * rightins = NULL;
|
||||||
|
|
||||||
|
OccurrenceLocator locator = getLeafInstanceOccurrences().getLocator();
|
||||||
|
Instance * instance = dynamic_cast<Instance*>(locator.getElement().getEntity());;
|
||||||
|
fingerHeight = instance->getCell()->getBoundingBox().getHeight();
|
||||||
|
horizontalMargin = getUnit(RETURN_EVEN((long)(getValue(fingerHeight))/4));
|
||||||
|
verticalLowMargin = getUnit(RETURN_EVEN((long)(getValue(fingerHeight))/2));
|
||||||
|
verticalHighMargin = getUnit(RETURN_EVEN((long)(getValue(fingerHeight))/2));
|
||||||
|
|
||||||
|
|
||||||
|
verticalLowMargin = MAX_INTEGER(verticalLowMargin, getUnit(RETURN_EVEN(rdImp + widthOfImp/2 + widthOfSourceWire
|
||||||
|
+ rdAlu2 + widthOfActive + rdActive)) );
|
||||||
|
|
||||||
|
verticalHighMargin = MAX_INTEGER(verticalHighMargin, horizontalMargin + getUnit(2*rdAlu2 + 2*widthOfDrainWire) );
|
||||||
|
horizontalMargin = MAX_INTEGER(horizontalMargin, getUnit(RETURN_EVEN(rdImp + widthOfImp/2)) );
|
||||||
|
|
||||||
|
UpdateSession::open();
|
||||||
|
|
||||||
|
if(_m == 1 ) { // If there is only one finger.
|
||||||
|
_Place( instance, Transformation::Orientation::ID, Point( horizontalMargin, verticalLowMargin ) );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// get instance who's model's abutment type is Left or Right.
|
||||||
|
// ************************************************************
|
||||||
|
for_each_occurrence(occurrence, getLeafInstanceOccurrences())
|
||||||
|
instance = dynamic_cast<Instance*>(occurrence.getEntity());
|
||||||
|
Transistor * trans = dynamic_cast<Transistor*>(instance->getMasterCell());
|
||||||
|
|
||||||
|
if ( _sourceIsFirst ) {
|
||||||
|
if(trans->isLeft() && !leftins)
|
||||||
|
leftins = instance;
|
||||||
|
else if ( trans->isLeft() && leftins)
|
||||||
|
rightins = instance;
|
||||||
|
else if ( trans->isRight())
|
||||||
|
rightins = instance;
|
||||||
|
} else {
|
||||||
|
if(trans->isRight() && !leftins)
|
||||||
|
leftins = instance;
|
||||||
|
else if (trans->isRight() && leftins )
|
||||||
|
rightins = instance;
|
||||||
|
else if (trans->isLeft())
|
||||||
|
rightins = instance;
|
||||||
|
}
|
||||||
|
end_for
|
||||||
|
|
||||||
|
// You must place this first instance who's model is left finger in a point who's
|
||||||
|
// x, y are all pair.
|
||||||
|
// Because if you do this, you can be sure that all rectangle of this instance are
|
||||||
|
// correctly in the grille of fondor.
|
||||||
|
// ***********************************************************************************
|
||||||
|
|
||||||
|
if(_sourceIsFirst)
|
||||||
|
_Place( leftins, Transformation::Orientation::ID, Point(horizontalMargin, verticalLowMargin) );
|
||||||
|
else
|
||||||
|
_Place( leftins, Transformation::Orientation::MX, Point(horizontalMargin, verticalLowMargin) );
|
||||||
|
|
||||||
|
_setRefIns(leftins);
|
||||||
|
|
||||||
|
if(_sourceIsFirst) // internal Finger's transformation.
|
||||||
|
internalTransCode = Transformation::Orientation::MX;
|
||||||
|
else
|
||||||
|
internalTransCode = Transformation::Orientation::ID;
|
||||||
|
|
||||||
|
// Place internal finger.
|
||||||
|
// *********************
|
||||||
|
for_each_occurrence(occurrence, getLeafInstanceOccurrences())
|
||||||
|
|
||||||
|
Instance * instance = dynamic_cast<Instance*>(occurrence.getEntity());
|
||||||
|
|
||||||
|
if(instance==leftins || instance==rightins )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_PlaceRight( instance, internalTransCode);
|
||||||
|
|
||||||
|
if(internalTransCode == Transformation::Orientation::MX)
|
||||||
|
internalTransCode = Transformation::Orientation::ID;
|
||||||
|
else
|
||||||
|
internalTransCode = Transformation::Orientation::MX;
|
||||||
|
|
||||||
|
end_for
|
||||||
|
|
||||||
|
// Place the last finger.
|
||||||
|
// **********************
|
||||||
|
Transistor * trans = dynamic_cast<Transistor*>(rightins->getMasterCell());
|
||||||
|
|
||||||
|
if( trans->isRight())
|
||||||
|
_PlaceRight( rightins, Transformation::Orientation::ID);
|
||||||
|
else
|
||||||
|
_PlaceRight( rightins, Transformation::Orientation::MX);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSession::close();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set AbutmentBox.
|
||||||
|
// ****************
|
||||||
|
for_each_instance(instance, getInstances())
|
||||||
|
instance->unmaterialize();
|
||||||
|
instance->materialize();
|
||||||
|
end_for
|
||||||
|
|
||||||
|
UpdateSession::open();
|
||||||
|
|
||||||
|
|
||||||
|
cout <<"Bounding box of TrMos is "<<getString(getBoundingBox())<<endl;
|
||||||
|
|
||||||
|
setAbutmentBox(Box(0, 0,
|
||||||
|
getBoundingBox().getWidth() + 2*horizontalMargin,
|
||||||
|
getBoundingBox().getHeight() + verticalLowMargin + verticalHighMargin
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// **************************************************************
|
||||||
|
// Routing .
|
||||||
|
// **************************************************************
|
||||||
|
|
||||||
|
Unit expectedInterval = getUnit(RETURN_EVEN((long)(getValue(horizontalMargin))/2));
|
||||||
|
Unit interval = 0;
|
||||||
|
Unit initialPosition = verticalLowMargin + fingerHeight + getUnit(rdAlu2 + widthOfDrainWire/2);
|
||||||
|
|
||||||
|
map<string, Unit> netName2PositionOfConnectorMap;
|
||||||
|
list<Box> routingZoneList;
|
||||||
|
list<Unit> sourcePositionList;
|
||||||
|
list<Unit> drainPositionList;
|
||||||
|
Unit sourceRoutingZoneWidth;
|
||||||
|
Unit drainRoutingZoneWidth;
|
||||||
|
|
||||||
|
DataBase * db = getDataBase();
|
||||||
|
if(!db) throw Error("Can't launch Trmos::PlaceAndRoute for " + getString(this) + " : can't find DataBase");
|
||||||
|
|
||||||
|
Layer * layerAlu1 = db->getTechnology()->getLayer(Name("ALU1"));
|
||||||
|
Layer * layerAlu2 = db->getTechnology()->getLayer(Name("ALU2"));
|
||||||
|
|
||||||
|
Layer * layerVia1 = db->getTechnology()->getLayer(Name("VIA1"));
|
||||||
|
Layer * layerActive = db->getTechnology()->getLayer(Name("ACTIVE"));
|
||||||
|
|
||||||
|
Layer * layerVia01 = db->getTechnology()->getLayer(Name("via01"));
|
||||||
|
Layer * layerVia12 = db->getTechnology()->getLayer(Name("via12"));
|
||||||
|
|
||||||
|
Layer * layerPoly = db->getTechnology()->getLayer(Name("POLY"));
|
||||||
|
Layer * layerNwell = db->getTechnology()->getLayer(Name("NWELL"));
|
||||||
|
Layer * layerCont = db->getTechnology()->getLayer(Name("CONT"));
|
||||||
|
|
||||||
|
Layer * layerImp = NULL;
|
||||||
|
|
||||||
|
if(_polarity == Transistor::Polarity::P)
|
||||||
|
layerImp = db->getTechnology()->getLayer(Name("NIMP"));
|
||||||
|
else
|
||||||
|
layerImp = db->getTechnology()->getLayer(Name("PIMP"));
|
||||||
|
|
||||||
|
Pin * pin = NULL; // For get the adresse of Created Pins.
|
||||||
|
|
||||||
|
long connectorPosition = 0;
|
||||||
|
|
||||||
|
|
||||||
|
cout << " Begin routage " << endl;
|
||||||
|
|
||||||
|
|
||||||
|
// Set position of four connectors.
|
||||||
|
// ********************************
|
||||||
|
vector<PinName>::iterator i = _highPinOrder.begin(),
|
||||||
|
j = _highPinOrder.end();
|
||||||
|
|
||||||
|
while(i!=j) {
|
||||||
|
if(*i == D)
|
||||||
|
netName2PositionOfConnectorMap[string("drain")] = initialPosition;
|
||||||
|
if(*i == G)
|
||||||
|
netName2PositionOfConnectorMap[string("grid")] = initialPosition;
|
||||||
|
|
||||||
|
interval = MAX_INTEGER(expectedInterval, getUnit(widthOfDrainWire + rdAlu2));
|
||||||
|
|
||||||
|
// initialPosition += horizontalMargin/2;
|
||||||
|
initialPosition += interval;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<PinName>::iterator m = _lowPinOrder.begin(),
|
||||||
|
n = _lowPinOrder.end();
|
||||||
|
|
||||||
|
//initialPosition = verticalMargin - horizontalMargin/2;
|
||||||
|
//initialPosition = verticalLowMargin - MAX_INTEGER(expectedInterval, getUnit(rdImp + widthOfImp/2));
|
||||||
|
initialPosition = verticalLowMargin - getUnit(rdImp + widthOfImp/2);
|
||||||
|
|
||||||
|
while(m!=n) {
|
||||||
|
if(*m == S)
|
||||||
|
netName2PositionOfConnectorMap[string("source")] = initialPosition;
|
||||||
|
if(*m == B)
|
||||||
|
netName2PositionOfConnectorMap[string("bulk")] = initialPosition;
|
||||||
|
|
||||||
|
interval = MAX_INTEGER(expectedInterval, getUnit(rdAlu2 + widthOfSourceWire));
|
||||||
|
|
||||||
|
initialPosition -= interval;
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << " Main loop "<< endl;
|
||||||
|
|
||||||
|
// Main Routing Algorithm.
|
||||||
|
// ***********************
|
||||||
|
|
||||||
|
// Main Loop.
|
||||||
|
// **********
|
||||||
|
for_each_net(net, getNets()) // For all hypernets.
|
||||||
|
|
||||||
|
if(getString(net->getName())=="bulk" || getString(net->getName())=="BULK" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// get Routing Zone.
|
||||||
|
// *****************
|
||||||
|
HyperNet hyperNet(Occurrence(net, Path()));
|
||||||
|
for_each_occurrence(occurrence, hyperNet.getNetOccurrences()) // For all net occurrences.
|
||||||
|
Net * net = dynamic_cast<Net*>(occurrence.getEntity());
|
||||||
|
Box routingZone;
|
||||||
|
|
||||||
|
if(net->getCell()->isLeaf()) {
|
||||||
|
Transistor * trans = dynamic_cast<Transistor*>(net->getCell());
|
||||||
|
if ( !trans )
|
||||||
|
throw Error("Can't launch Trmos::PlaceAndRoute for " + getString(this)
|
||||||
|
+ ", it is not a Transistor");
|
||||||
|
|
||||||
|
cout << getString(occurrence) << endl;
|
||||||
|
cout << getString(occurrence.getPath().getTransformation()) <<endl;
|
||||||
|
cout << getString((*(trans->_getMapNet2Box()))[net]) << endl;
|
||||||
|
|
||||||
|
// get Routing Zone.
|
||||||
|
// *****************
|
||||||
|
routingZone = occurrence.getPath().getTransformation().getBox((*(trans->_getMapNet2Box()))[net]);
|
||||||
|
routingZoneList.push_back(routingZone);
|
||||||
|
|
||||||
|
if(getString(net->getName())=="SOURCE") {
|
||||||
|
sourcePositionList.push_back(routingZone.getXCenter());
|
||||||
|
sourceRoutingZoneWidth = routingZone.getWidth();
|
||||||
|
}
|
||||||
|
else if (getString(net->getName())=="DRAIN") {
|
||||||
|
drainPositionList.push_back(routingZone.getXCenter());
|
||||||
|
drainRoutingZoneWidth = routingZone.getWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_for
|
||||||
|
|
||||||
|
|
||||||
|
cout <<"Print routing zone for " <<getString(net)<<endl;
|
||||||
|
|
||||||
|
list<Box>::iterator it_begin_listbox = routingZoneList.begin(),
|
||||||
|
it_end_listbox = routingZoneList.end();
|
||||||
|
|
||||||
|
while(it_begin_listbox != it_end_listbox)
|
||||||
|
{
|
||||||
|
cout<< getString(*it_begin_listbox) <<endl;
|
||||||
|
it_begin_listbox++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout <<"End Print Routing Zone for "<<getString(net)<<endl;
|
||||||
|
|
||||||
|
// Create routing line.
|
||||||
|
// ********************
|
||||||
|
list<Box>::iterator routingzonelist_begin_it = routingZoneList.begin(),
|
||||||
|
routingzonelist_end_it = routingZoneList.end();
|
||||||
|
|
||||||
|
connectorPosition = netName2PositionOfConnectorMap[getString(net->getName())];
|
||||||
|
cout << "Connector Position is " << netName2PositionOfConnectorMap[getString(net)] << endl;
|
||||||
|
|
||||||
|
while(routingzonelist_begin_it!=routingzonelist_end_it) {
|
||||||
|
|
||||||
|
Box routingZoneBox = *routingzonelist_begin_it;
|
||||||
|
|
||||||
|
// Create vertical line and Contact.
|
||||||
|
// ********************************
|
||||||
|
if(connectorPosition > routingZoneBox.getYMin()) {
|
||||||
|
Vertical::create(net, layerAlu1, routingZoneBox.getXCenter()
|
||||||
|
, routingZoneBox.getWidth() + getUnit(2*reAlu1Contact)
|
||||||
|
, routingZoneBox.getYMin() - getUnit(reAlu1Contact)
|
||||||
|
, connectorPosition);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Vertical::create(net, layerAlu1, routingZoneBox.getXCenter()
|
||||||
|
, routingZoneBox.getWidth() + getUnit(2*reAlu1Contact)
|
||||||
|
, connectorPosition
|
||||||
|
, routingZoneBox.getYMax() + getUnit(reAlu1Contact) ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Contact::create(net, layerVia12, routingZoneBox.getXCenter()
|
||||||
|
, connectorPosition
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
);
|
||||||
|
|
||||||
|
routingzonelist_begin_it ++ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create horizontal line.
|
||||||
|
// ***********************
|
||||||
|
long widthOfWire = 0;
|
||||||
|
|
||||||
|
if(getString(net->getName())=="source")
|
||||||
|
widthOfWire = widthOfSourceWire;
|
||||||
|
else if(getString(net->getName())=="drain")
|
||||||
|
widthOfWire = widthOfDrainWire;
|
||||||
|
else
|
||||||
|
widthOfWire = widthOfDrainWire;
|
||||||
|
|
||||||
|
|
||||||
|
Horizontal::create(net, layerAlu2, connectorPosition
|
||||||
|
, getUnit(widthOfWire)
|
||||||
|
, 0
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create Two Pins.
|
||||||
|
// ****************
|
||||||
|
pin = Pin::create(net
|
||||||
|
, Name(getString(net->getName())+"_west")
|
||||||
|
, Pin::AccessDirection(Pin::AccessDirection::WEST)
|
||||||
|
, Pin::PlacementStatus(Pin::PlacementStatus::PLACED)
|
||||||
|
, layerAlu2
|
||||||
|
, getAbutmentBox().getXMin()
|
||||||
|
, connectorPosition
|
||||||
|
, getUnit(widthOfWire)
|
||||||
|
, getUnit(widthOfWire)
|
||||||
|
);
|
||||||
|
|
||||||
|
_mapNetToPinBoxInLeftSide[net] = pin;
|
||||||
|
|
||||||
|
pin = Pin::create(net
|
||||||
|
, Name(getString(net->getName())+"_east")
|
||||||
|
, Pin::AccessDirection(Pin::AccessDirection::EAST)
|
||||||
|
, Pin::PlacementStatus(Pin::PlacementStatus::PLACED)
|
||||||
|
, layerAlu2
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
, connectorPosition
|
||||||
|
, getUnit(widthOfWire)
|
||||||
|
, getUnit(widthOfWire)
|
||||||
|
);
|
||||||
|
|
||||||
|
_mapNetToPinBoxInRightSide[net] = pin;
|
||||||
|
|
||||||
|
routingZoneList.clear();
|
||||||
|
|
||||||
|
// End Of Main Loop.
|
||||||
|
// *****************
|
||||||
|
end_for
|
||||||
|
|
||||||
|
// Route Net Bulk.
|
||||||
|
// ***************
|
||||||
|
connectorPosition = netName2PositionOfConnectorMap[string("bulk")];
|
||||||
|
|
||||||
|
Net * netBulk = getNet(Name("bulk"));
|
||||||
|
|
||||||
|
if(!netBulk) // bulk and source are connected.
|
||||||
|
netBulk = getNet(Name("source"));
|
||||||
|
|
||||||
|
// Calculate the width of Contact Alu1.
|
||||||
|
// ************************************
|
||||||
|
long widthOfAlu1 = MAX_INTEGER( MAX_INTEGER(minAlu1Width, 2*reAlu1Contact + minContWidth), 2*reAlu1Via1 + minVia1Width);
|
||||||
|
|
||||||
|
Unit bulkPosition = netName2PositionOfConnectorMap[string("bulk")];
|
||||||
|
Unit sourcePosition = netName2PositionOfConnectorMap[string("source")];
|
||||||
|
|
||||||
|
Horizontal::create( netBulk
|
||||||
|
, layerImp
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfImp)
|
||||||
|
, 0 - getUnit(reImpActi)
|
||||||
|
, getAbutmentBox().getXMax() + getUnit(reImpActi)
|
||||||
|
);
|
||||||
|
|
||||||
|
Horizontal::create( netBulk
|
||||||
|
, layerActive
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfActive)
|
||||||
|
, 0
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
Horizontal::create( netBulk
|
||||||
|
, layerAlu2
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfSourceWire)
|
||||||
|
, 0
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create Two Pins For Net bulk.
|
||||||
|
// *****************************
|
||||||
|
if(!_isBsConnected) {
|
||||||
|
|
||||||
|
pin = Pin::create(netBulk
|
||||||
|
, Name(getString(netBulk->getName())+"_west")
|
||||||
|
, Pin::AccessDirection(Pin::AccessDirection::WEST)
|
||||||
|
, Pin::PlacementStatus(Pin::PlacementStatus::PLACED)
|
||||||
|
, layerAlu2
|
||||||
|
, getAbutmentBox().getXMin()
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfSourceWire)
|
||||||
|
, getUnit(widthOfSourceWire)
|
||||||
|
);
|
||||||
|
|
||||||
|
_mapNetToPinBoxInLeftSide[netBulk] = pin;
|
||||||
|
|
||||||
|
pin = Pin::create(netBulk
|
||||||
|
, Name(getString(netBulk->getName())+"_east")
|
||||||
|
, Pin::AccessDirection(Pin::AccessDirection::EAST)
|
||||||
|
, Pin::PlacementStatus(Pin::PlacementStatus::PLACED)
|
||||||
|
, layerAlu2
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfSourceWire)
|
||||||
|
, getUnit(widthOfSourceWire)
|
||||||
|
);
|
||||||
|
|
||||||
|
_mapNetToPinBoxInRightSide[netBulk] = pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( netName2PositionOfConnectorMap[string("source")] > netName2PositionOfConnectorMap[string("bulk")] ) {
|
||||||
|
// Source Is Upper Than Bulk.
|
||||||
|
|
||||||
|
cout << " Source is Upper Than Bulk" << endl;
|
||||||
|
|
||||||
|
list<Unit>::iterator i = sourcePositionList.begin(), j = sourcePositionList.end();
|
||||||
|
|
||||||
|
while(i!=j) {
|
||||||
|
|
||||||
|
cout << " ######### Create Contact ###########" <<endl;
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerVia01, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(minContWidth)
|
||||||
|
, getUnit(minContWidth)
|
||||||
|
);
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerAlu1, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfAlu1)
|
||||||
|
, getUnit(widthOfAlu1)
|
||||||
|
);
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerVia12, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( _isBsConnected ) { // If bulk and Source are connected.
|
||||||
|
|
||||||
|
cout << " B S is connected in " << *i << endl;
|
||||||
|
|
||||||
|
Vertical::create(netBulk, layerAlu1, *i
|
||||||
|
, sourceRoutingZoneWidth
|
||||||
|
, bulkPosition
|
||||||
|
, sourcePosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
list<Unit>::iterator i , j;
|
||||||
|
|
||||||
|
|
||||||
|
if( _isBsConnected ) { // If bulk and Source are connected.
|
||||||
|
i = sourcePositionList.begin();
|
||||||
|
j = sourcePositionList.end();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i = drainPositionList.begin();
|
||||||
|
j = drainPositionList.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i!=j) {
|
||||||
|
|
||||||
|
cout << " ######### Create Contact ###########" <<endl;
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerVia01, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(minContWidth)
|
||||||
|
, getUnit(minContWidth)
|
||||||
|
);
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerAlu1, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(widthOfAlu1)
|
||||||
|
, getUnit(widthOfAlu1)
|
||||||
|
);
|
||||||
|
|
||||||
|
Contact::create(netBulk, layerVia12, *i
|
||||||
|
, bulkPosition
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
, getUnit(minVia1Width)
|
||||||
|
);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create Ring.
|
||||||
|
// ************
|
||||||
|
if( _hasRing ) {
|
||||||
|
widthOfImp = MAX_INTEGER(minImpWidth, minActiWidth + 2*reImpActi);
|
||||||
|
|
||||||
|
Net * netRing = Net::create(this, Name("RING"));
|
||||||
|
|
||||||
|
|
||||||
|
// Create rectangle in IMPLANT.
|
||||||
|
// ***************************
|
||||||
|
Horizontal::create( netRing
|
||||||
|
, layerImp
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
, getUnit(widthOfImp)
|
||||||
|
, getAbutmentBox().getXMin() - getUnit(widthOfImp/2)
|
||||||
|
, getAbutmentBox().getXMax() + getUnit(widthOfImp/2)
|
||||||
|
);
|
||||||
|
|
||||||
|
Horizontal::create( netRing
|
||||||
|
, layerImp
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getUnit(widthOfImp)
|
||||||
|
, getAbutmentBox().getXMin() - getUnit(widthOfImp/2)
|
||||||
|
, getAbutmentBox().getXMax() + getUnit(widthOfImp/2)
|
||||||
|
);
|
||||||
|
|
||||||
|
Vertical::create(netRing
|
||||||
|
, layerImp
|
||||||
|
, getAbutmentBox().getXMin()
|
||||||
|
, getUnit(widthOfImp)
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
Vertical::create(netRing
|
||||||
|
, layerImp
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
, getUnit(widthOfImp)
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Create rectangle in Active.
|
||||||
|
// ***************************
|
||||||
|
Horizontal::create( netRing
|
||||||
|
, layerActive
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
, getUnit(minActiWidth)
|
||||||
|
, getAbutmentBox().getXMin() - getUnit(minActiWidth/2)
|
||||||
|
, getAbutmentBox().getXMax() + getUnit(minActiWidth/2)
|
||||||
|
);
|
||||||
|
|
||||||
|
Horizontal::create( netRing
|
||||||
|
, layerActive
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getUnit(minActiWidth)
|
||||||
|
, getAbutmentBox().getXMin() - getUnit(minActiWidth/2)
|
||||||
|
, getAbutmentBox().getXMax() + getUnit(minActiWidth/2)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
Vertical::create(netRing
|
||||||
|
, layerActive
|
||||||
|
, getAbutmentBox().getXMin()
|
||||||
|
, getUnit(minActiWidth)
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
Vertical::create(netRing
|
||||||
|
, layerActive
|
||||||
|
, getAbutmentBox().getXMax()
|
||||||
|
, getUnit(minActiWidth)
|
||||||
|
, getAbutmentBox().getYMin()
|
||||||
|
, getAbutmentBox().getYMax()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Caission NWELL if this is a PMOS.
|
||||||
|
// ****************************************
|
||||||
|
if(_polarity == Transistor::Polarity::P) {
|
||||||
|
Net * netCaisson = Net::create(this, Name("CAISSON"));
|
||||||
|
Contact::create(netCaisson, layerNwell
|
||||||
|
, getAbutmentBox().getXCenter()
|
||||||
|
, getAbutmentBox().getYCenter()
|
||||||
|
, getAbutmentBox().getWidth()
|
||||||
|
, getAbutmentBox().getHeight()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSession::close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // END OF NAMESPACE DEVICE
|
|
@ -2,6 +2,7 @@
|
||||||
#define ATECHNOLOGY_H_
|
#define ATECHNOLOGY_H_
|
||||||
|
|
||||||
#include "hurricane/Property.h"
|
#include "hurricane/Property.h"
|
||||||
|
#include "hurricane/DbU.h"
|
||||||
using namespace Hurricane;
|
using namespace Hurricane;
|
||||||
|
|
||||||
namespace Hurricane {
|
namespace Hurricane {
|
||||||
|
|
|
@ -13,6 +13,7 @@ using namespace Hurricane;
|
||||||
#include "AEnv.h"
|
#include "AEnv.h"
|
||||||
#include "ATechnology.h"
|
#include "ATechnology.h"
|
||||||
#include "Transistor.h"
|
#include "Transistor.h"
|
||||||
|
#include "AnalogicViewer.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
@ -35,16 +36,9 @@ int main(int argc, char* argv[]) {
|
||||||
if (!aTechnology) {
|
if (!aTechnology) {
|
||||||
exit(56);
|
exit(56);
|
||||||
}
|
}
|
||||||
aTechnology->print();
|
|
||||||
|
|
||||||
DbU::Unit transistorMinL = aTechnology->getPhysicalRule("transistorMinL")->getValue();
|
AnalogicViewer* viewer = new AnalogicViewer(userLibrary);
|
||||||
DbU::Unit transistorMinW = aTechnology->getPhysicalRule("transistorMinW")->getValue();
|
|
||||||
|
|
||||||
DbU::Unit L = transistorMinL;
|
|
||||||
DbU::Unit W = 2 * transistorMinW;
|
|
||||||
Transistor* trans = Transistor::create(userLibrary, Name("TEST"), Transistor::Polarity::N, L, W);
|
|
||||||
trans->createLayout();
|
|
||||||
CellViewer* viewer = new CellViewer ( trans );
|
|
||||||
viewer->show();
|
viewer->show();
|
||||||
|
|
||||||
returnCode = qa->exec();
|
returnCode = qa->exec();
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
|
|
||||||
|
qt4_wrap_cpp(MOC_SRCS AnalogicViewer.h)
|
||||||
|
|
||||||
include_directories(${HURRICANE_INCLUDE_DIR} ${HURRICANE_GRAPHICAL_INCLUDE_DIR}
|
include_directories(${HURRICANE_INCLUDE_DIR} ${HURRICANE_GRAPHICAL_INCLUDE_DIR}
|
||||||
${CORIOLIS_INCLUDE_DIR} ${CHAMSIN_SOURCE_DIR}/src/technology
|
${CORIOLIS_INCLUDE_DIR} ${CHAMSIN_SOURCE_DIR}/src/technology
|
||||||
${CHAMSIN_SOURCE_DIR}/src/analogic ${CHAMSIN_SOURCE_DIR}/src/device)
|
${CHAMSIN_SOURCE_DIR}/src/analogic ${CHAMSIN_SOURCE_DIR}/src/device)
|
||||||
|
|
||||||
add_executable(atest AnalogicTest.cpp)
|
add_executable(atest AnalogicViewer.cpp ${MOC_SRCS} AnalogicTest.cpp)
|
||||||
|
|
||||||
target_link_libraries(atest atechnology analogic ${HURRICANE_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES} ${QT_LIBRARIES})
|
target_link_libraries(atest atechnology analogic ${HURRICANE_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES} ${QT_LIBRARIES})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue