// **************************************************************************************************** // 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(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(occurrence.getEntity()); Transistor * trans = dynamic_cast(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(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(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 "< netName2PositionOfConnectorMap; list routingZoneList; list sourcePositionList; list 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::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::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(occurrence.getEntity()); Box routingZone; if(net->getCell()->isLeaf()) { Transistor * trans = dynamic_cast(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()) <_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 " <::iterator it_begin_listbox = routingZoneList.begin(), it_end_listbox = routingZoneList.end(); while(it_begin_listbox != it_end_listbox) { cout<< getString(*it_begin_listbox) <::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::iterator i = sourcePositionList.begin(), j = sourcePositionList.end(); while(i!=j) { cout << " ######### Create Contact ###########" <::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 ###########" <