coriolis/chamsin/src/analogic/Transistor.cpp

348 lines
12 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 {
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::Type::Type(const Code& code):
_code(code)
{}
Transistor::Type::Type(const Type& type):
_code(type._code)
{}
Transistor::Type& Transistor::Type::operator=(const Type& type) {
_code = type._code;
return *this;
}
Transistor::Transistor(Library* library, const Name& name):
AnalogComponent(library, name),
_drain(NULL),
_source(NULL),
_grid(NULL),
_bulk(NULL),
_anonymous(NULL),
_type(),
_l(0),
_w(0),
//_source20(NULL),
_source22(NULL),
//_drain40(NULL),
_drain42(NULL),
_grid00(NULL), _grid01(NULL), _grid30(NULL), _grid31(NULL),
_anonymous10(NULL), _anonymous11(NULL), _anonymous12(NULL), _anonymous50(NULL)
{}
Transistor* Transistor::create(Library* library, const Name& name) {
Transistor* transistor = new Transistor(library, name);
transistor->_postCreate();
return transistor;
}
void Transistor::_postCreate() {
Inherit::_postCreate();
//ChoiceParameter<Transistor>::Choices choices;
//choices.push_back(string("N"));
//choices.push_back(string("P"));
//addParameter(ChoiceParameter<Transistor>("type", choices, 0, new CallBack<Transistor>(this, &Transistor::updateType)));
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 (_type == Type::NMOS) {
_anonymous11 = createPad(technology, _anonymous, "nImplant");
_anonymous12 = createPad(technology, _anonymous, "nImplant");
} else {
_anonymous11 = createPad(technology, _anonymous, "pImplant");
_anonymous12 = createPad(technology, _anonymous, "pImplant");
}
setTerminal(false);
}
void Transistor::setType(Type type) {
UpdateSession::open();
if (type != _type) {
_type = type;
DataBase* db = DataBase::getDB();
Technology* technology = db->getTechnology();
if (_type == Type::NMOS) {
_anonymous11->setLayer(getLayer(technology, "nImplant"));
_anonymous12->setLayer(getLayer(technology, "nImplant"));
} else {
_anonymous11->setLayer(getLayer(technology, "pImplant"));
_anonymous12->setLayer(getLayer(technology, "pImplant"));
}
updateLayout();
}
UpdateSession::close();
}
void Transistor::updateLayout() {
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 spacingCut0 = atechno->getPhysicalRule("minSpacing", getLayer(techno, "cut0"))->getValue();
DbU::Unit extGateActive = atechno->getPhysicalRule("minExtension",
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 spacingGateCut0 = atechno->getPhysicalRule("minGateSpacing",
getLayer(techno, "cut0"), getLayer(techno, "active"))->getValue();
DbU::Unit spacingActivePoly = atechno->getPhysicalRule("minSpacing",
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
DbU::Unit sourceDrainWidth = atechno->getPhysicalRule("minExtension",
getLayer(techno, "active"), getLayer(techno, "poly"))->getValue();
DbU::Unit extActiveCut0 = atechno->getPhysicalRule("minExtension",
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 enclosureGateImplant = 0;
DbU::Unit extImplantActive = 0;
DbU::Unit extImplantCut0 = 0;
if (_type == Type::NMOS) {
enclosureImplantPoly = atechno->getPhysicalRule("minEnclosure",
getLayer(techno, "nImplant"), getLayer(techno, "poly"))->getValue();
enclosureGateImplant = atechno->getPhysicalRule("minGateEnclosure",
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 {
enclosureImplantPoly = atechno->getPhysicalRule("minEnclosure",
getLayer(techno, "pImplant"), getLayer(techno, "poly"))->getValue();
enclosureGateImplant = atechno->getPhysicalRule("minGateEnclosure",
getLayer(techno, "nImplant"), 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();
DbU::setStringMode(1);
//grid 00
DbU::Unit x00 = 0;
DbU::Unit y00 = -extGateActive;
DbU::Unit dx00 = _l;
DbU::Unit dy00 = _w + extGateActive;
Box box00(x00, y00, x00 + dx00, y00 + 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, x30 + dx30, y30 + 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, x31 + dx31, y31 + 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, x01 + dx01, y01 + dy01);
_grid01->setBoundingBox(box01);
//anonymous12
DbU::Unit x12 = min(x31, x00) - enclosureImplantPoly;
DbU::Unit y12 = min(0 - extImplantActive, y00 - enclosureImplantPoly);
DbU::Unit dx12 = max(dx31, dx00) + 2 * enclosureImplantPoly;
DbU::Unit yMax = max( max(y30 + dy30 + extImplantCut0, max(y31 + dy31, y00 + dy00) + enclosureImplantPoly), _w + extImplantActive);
DbU::Unit dy12 = yMax - y12;
Box box12(x12, y12, x12 + dx12, y12 + dy12);
_anonymous12->setBoundingBox(box12);
////_source20
DbU::Unit y20 = extActiveCut0;
DbU::Unit dy20 = _w - 2 * extActiveCut0;
unsigned sourceColumnNumber = 1;
DbU::Unit dx20 = sourceColumnNumber * widthCut0 + (sourceColumnNumber - 1) * spacingCut0;
DbU::Unit x20 = -(dx20 + spacingGateCut0);
//Box box20(x20, y20, x20 + dx20, y20 + dy20);
////_source20->setBoundingBox(box20);
////_drain40
//DbU::Unit y40 = y20;
DbU::Unit x40 = x00 + dx00 + spacingGateCut0;
unsigned drainColumnNumber = 1;
DbU::Unit dx40 = drainColumnNumber * widthCut0 + (drainColumnNumber - 1) * (spacingCut0);
//DbU::Unit dy40 = dy20;
//Box box40(x40, y40, x40 + dx40, y40 + dy40);
//_drain40->setBoundingBox(box40);
//_anonymous10
DbU::Unit y10 = 0;
DbU::Unit x10 = min(x20 - spacingActiveCut0, sourceDrainWidth);
DbU::Unit dy10 = _w;
DbU::Unit extension10 = max(x40 + dx40 + spacingActiveCut0, dx00 + sourceDrainWidth);
DbU::Unit dx10 = -x10 + extension10;
Box box10(x10, y10, x10 + dx10, y10 + dy10);
_anonymous10->setBoundingBox(box10);
//Rectangle 23
DbU::Unit x23 = x10;
DbU::Unit y23 = y10;
DbU::Unit dx23 = x10;
DbU::Unit dy23 = _w;
//_anonymous11
DbU::Unit extension11_1 = enclosureGateImplant;
DbU::Unit extension11_2 = extImplantCut0 - x20;
DbU::Unit extension11_3 = extImplantActive - x10;
DbU::Unit extension11_4 = max(max(extension11_1, extension11_2), extension11_3);
DbU::Unit x11 = -extension11_4;
extension11_1 = enclosureGateImplant + x00 + dx00;
extension11_2 = extImplantCut0 + x40 + dx40;
extension11_3 = extImplantActive + x10 + dx10;
extension11_4 = max(max(extension11_1, extension11_2), extension11_3);
DbU::Unit dx11 = -x11 + extension11_4;
DbU::Unit y11 = min(y20 - extImplantCut0, y23 - extImplantActive);
DbU::Unit dy11 = max(y20 + dy20 + extImplantCut0, y23 + dy23 + extImplantActive) - y11;
Box box11(x11, y11, x11 + dx11, y11 + dy11);
_anonymous11->setBoundingBox(box11);
if (_type == Type::PMOS) {
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(box12);
UpdateSession::close();
}
Record* Transistor::_getRecord() const {
Record* record = Inherit::_getRecord();
if (record) {
record->add(getSlot("Drain", _drain));
record->add(getSlot("Source", _source));
record->add(getSlot("Grid", _grid));
record->add(getSlot("Bulk", _bulk));
record->add(getSlot("L", &_l));
record->add(getSlot("W", &_w));
//record->add(getSlot("Source20", _source20));
record->add(getSlot("Source22", _source22));
//record->add(getSlot("Drain40", _drain40));
record->add(getSlot("Drain42", _drain42));
record->add(getSlot("Grid00", _grid00));
record->add(getSlot("Grid01", _grid01));
record->add(getSlot("Grid30", _grid30));
record->add(getSlot("Grid31", _grid31));
record->add(getSlot("10", _anonymous10));
record->add(getSlot("11", _anonymous11));
record->add(getSlot("12", _anonymous12));
}
return record;
}