221 lines
7.6 KiB
C++
221 lines
7.6 KiB
C++
#include "hurricane/DataBase.h"
|
|
#include "hurricane/Technology.h"
|
|
#include "hurricane/UpdateSession.h"
|
|
#include "hurricane/Pad.h"
|
|
using namespace Hurricane;
|
|
|
|
#include "AEnv.h"
|
|
#include "ATechnology.h"
|
|
#include "Transistor.h"
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
void createContactMatrix(Net* net, const Layer* layer, const Box& box, unsigned columns,
|
|
const DbU::Unit& rwCont, const DbU::Unit& rdCont) {
|
|
unsigned contacts = 0;
|
|
if (box.getHeight() < rwCont) {
|
|
contacts = 0;
|
|
} else {
|
|
contacts = (box.getHeight() - rwCont) / (rwCont + rdCont) + 1;
|
|
}
|
|
|
|
Point padMin(box.getXMin(), box.getYMin());
|
|
Point padMax(padMin);
|
|
padMax += Point(rwCont, rwCont);
|
|
|
|
for (unsigned i=0; i<columns; i++) {
|
|
for (unsigned j=0; j<contacts; j++) {
|
|
Box padBox(padMin, padMax);
|
|
Pad::create(net, layer, padBox);
|
|
padMin.setY(padMin.getY() + rwCont + rdCont);
|
|
padMax.setY(padMax.getY() + rwCont + rdCont);
|
|
}
|
|
padMin.setX(padMin.getX() + rwCont + rdCont);
|
|
padMax.setX(padMax.getX() + rwCont + rdCont);
|
|
padMin.setY(box.getYMin());
|
|
padMax.setY(box.getYMax());
|
|
}
|
|
}
|
|
|
|
Layer* getLayer(Technology* technology, const string& layerStr) {
|
|
Layer* layer = technology->getLayer(layerStr);
|
|
if (!layer) {
|
|
throw Error("Unknown Layer : " + layerStr);
|
|
}
|
|
return layer;
|
|
}
|
|
|
|
Pad* createPad(Technology* technology, Net* net, const string& layerName) {
|
|
static Box emptyBox(0, 0, 0, 0);
|
|
Layer* layer = getLayer(technology, layerName);
|
|
Pad* pad = Pad::create(net, layer, emptyBox);
|
|
return pad;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
const Name Transistor::DrainName("DRAIN");
|
|
const Name Transistor::SourceName("SOURCE");
|
|
const Name Transistor::GridName("GRID");
|
|
const Name Transistor::BulkName("BULK");
|
|
const Name Transistor::AnonymousName("ANONYMOUS");
|
|
|
|
Transistor::Transistor(Library* library, const Name& name, const Polarity& polarity):
|
|
Cell(library, name),
|
|
_drain(NULL),
|
|
_source(NULL),
|
|
_grid(NULL),
|
|
_bulk(NULL),
|
|
_anonymous(NULL),
|
|
_polarity(polarity),
|
|
_abutmentType(),
|
|
_l(DbU::Min),
|
|
_w(DbU::Min),
|
|
_source20(NULL), _source22(NULL),
|
|
_drain40(NULL), _drain42(NULL),
|
|
_grid00(NULL), _grid01(NULL), _grid30(NULL), _grid31(NULL),
|
|
_anonymous10(NULL), _anonymous11(NULL), _anonymous12(NULL)
|
|
{}
|
|
|
|
|
|
Transistor* Transistor::create(Library* library, const Name& name, const Polarity& polarity) {
|
|
Transistor* transistor = new Transistor(library, name, polarity);
|
|
|
|
transistor->_postCreate();
|
|
|
|
return transistor;
|
|
}
|
|
|
|
void Transistor::_postCreate() {
|
|
Inherit::_postCreate();
|
|
DataBase* db = DataBase::getDB();
|
|
Technology* technology = db->getTechnology();
|
|
_drain = Net::create(this, DrainName);
|
|
_drain->setExternal(true);
|
|
_source = Net::create(this, SourceName);
|
|
_source->setExternal(true);
|
|
_grid = Net::create(this, GridName);
|
|
_grid->setExternal(true);
|
|
_bulk = Net::create(this, BulkName);
|
|
_bulk->setExternal(true);
|
|
_anonymous = Net::create(this, AnonymousName);
|
|
_source20 = createPad(technology, _source, "cut0");
|
|
_source22 = createPad(technology, _source, "cut1");
|
|
_drain40 = createPad(technology, _drain, "cut0");
|
|
_drain42 = createPad(technology, _drain, "cut1");
|
|
_grid00 = createPad(technology, _grid, "poly");
|
|
_grid01 = createPad(technology, _grid, "poly");
|
|
_grid30 = createPad(technology, _grid, "cut0");
|
|
_grid31 = createPad(technology, _grid, "metal1");
|
|
_anonymous10 = createPad(technology, _anonymous, "active");
|
|
if (_polarity == N) {
|
|
_anonymous11 = createPad(technology, _anonymous, "nImplant");
|
|
_anonymous12 = createPad(technology, _anonymous, "nImplant");
|
|
} else {
|
|
_anonymous11 = createPad(technology, _anonymous, "pImplant");
|
|
_anonymous12 = createPad(technology, _anonymous, "pImplant");
|
|
}
|
|
}
|
|
|
|
void Transistor::createLayout() {
|
|
DataBase* db = DataBase::getDB();
|
|
if (!db) {
|
|
throw Error("Error : no DataBase");
|
|
}
|
|
Technology* techno = db->getTechnology();
|
|
if (!techno) {
|
|
throw Error("Error : no Technology");
|
|
}
|
|
ATechnology* atechno = AEnv::getATechnology();
|
|
|
|
DbU::Unit widthCut0 = atechno->getPhysicalRule("minWidth", getLayer(techno, "cut0"))->getValue();
|
|
DbU::Unit extGateActive = atechno->getPhysicalRule("minGateExtension",
|
|
getLayer(techno, "poly"), getLayer(techno, "active"))->getValue();
|
|
DbU::Unit extPolyCut0 = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "poly"), getLayer(techno, "cut0"))->getValue();
|
|
DbU::Unit spacingActiveCut0 = atechno->getPhysicalRule("minSpacing",
|
|
getLayer(techno, "active"), getLayer(techno, "cut0"))->getValue();
|
|
DbU::Unit spacingActivePoly = atechno->getPhysicalRule("minSpacing",
|
|
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
|
|
DbU::Unit extImplantPoly = 0;
|
|
DbU::Unit extImplantActive = 0;
|
|
DbU::Unit extImplantCut0 = 0;
|
|
if (_polarity == N) {
|
|
extImplantPoly = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "nImplant"), getLayer(techno, "poly"))->getValue();
|
|
extImplantActive = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "nImplant"), getLayer(techno, "active"))->getValue();
|
|
extImplantCut0 = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "nImplant"), getLayer(techno, "cut0"))->getValue();
|
|
} else {
|
|
extImplantPoly = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "pImplant"), getLayer(techno, "poly"))->getValue();
|
|
extImplantActive = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "pImplant"), getLayer(techno, "active"))->getValue();
|
|
extImplantCut0 = atechno->getPhysicalRule("minExtension",
|
|
getLayer(techno, "pImplant"), getLayer(techno, "cut0"))->getValue();
|
|
}
|
|
|
|
UpdateSession::open();
|
|
|
|
//grid 00
|
|
DbU::Unit x00 = 0;
|
|
DbU::Unit y00 = -extGateActive;
|
|
DbU::Unit dx00 = _l;
|
|
DbU::Unit dy00 = _w - y00*2;
|
|
Box box00(x00, y00, dx00, dy00);
|
|
_grid00->setBoundingBox(box00);
|
|
|
|
//grid30
|
|
DbU::Unit maxValue = widthCut0 + 2*extPolyCut0;
|
|
DbU::Unit x30 = 0, dx30 = 0, y30 = 0, dy30 = 0;
|
|
if (maxValue > _l) {
|
|
dx30 = widthCut0;
|
|
dy30 = dx30;
|
|
y30 = _w + max(spacingActiveCut0, spacingActivePoly + extPolyCut0);
|
|
} else {
|
|
dx30 = dx00 - 2*extPolyCut0;
|
|
dy30 = widthCut0;
|
|
y30 = _w + spacingActiveCut0;
|
|
}
|
|
x30 = x00 + dx00/2 - dx30/2;
|
|
Box box30(x30, y30, dx30, dy30);
|
|
_grid30->setBoundingBox(box30);
|
|
|
|
//grid31
|
|
DbU::Unit dx31 = dx30 + 2*extPolyCut0;
|
|
DbU::Unit dy31 = dy30 + 2*extPolyCut0;
|
|
DbU::Unit x31 = x30 - extPolyCut0;
|
|
DbU::Unit y31 = y30 - extPolyCut0;
|
|
Box box31(x31, y31, dx31, dy31);
|
|
_grid31->setBoundingBox(box31);
|
|
|
|
//grid01
|
|
DbU::Unit x01 = 0, y01 = 0, dx01 = 0, dy01 = 0;
|
|
if (y31 <= y00+dy00) {
|
|
x01 = 0; y01 = 0; dx01 = 0; dy01 = 0;
|
|
} else {
|
|
x01 = x00;
|
|
y01 = y00 + dy00;
|
|
dx01 = dx00;
|
|
dy01 = y31 - (y00 + dy00);
|
|
}
|
|
Box box01(x01, y01, dx01, dy01);
|
|
_grid01->setBoundingBox(box01);
|
|
|
|
//anonymous12
|
|
DbU::Unit x12 = min(x31, x00) - extImplantPoly;
|
|
DbU::Unit y12 = min(0 - extImplantActive, y00 - extImplantPoly);
|
|
DbU::Unit dx12 = max(dx31, dx00) + 2 * extImplantPoly;
|
|
DbU::Unit yMax = max( max(y30 + dy30 + extImplantCut0, max(y31 + dy31, y00 + dy00) + extImplantPoly), _w + extImplantActive);
|
|
DbU::Unit dy12 = yMax - y12;
|
|
|
|
Box box12(x12, y12, dx12, dy12);
|
|
_anonymous12->setBoundingBox(box12);
|
|
|
|
UpdateSession::close();
|
|
}
|