#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; igetLayer(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(); }