576 lines
19 KiB
C++
576 lines
19 KiB
C++
|
|
// -*- C++ -*-
|
|
|
|
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <algorithm>
|
|
|
|
#include <QStringList>
|
|
#include <QXmlStreamReader>
|
|
|
|
#include "hurricane/Error.h"
|
|
#include "hurricane/Warning.h"
|
|
#include "hurricane/DbU.h"
|
|
#include "hurricane/DataBase.h"
|
|
#include "hurricane/Technology.h"
|
|
#include "hurricane/BasicLayer.h"
|
|
#include "hurricane/RegularLayer.h"
|
|
#include "hurricane/DiffusionLayer.h"
|
|
#include "hurricane/TransistorLayer.h"
|
|
#include "hurricane/ViaLayer.h"
|
|
#include "hurricane/ContactLayer.h"
|
|
|
|
#include "crlcore/SymbolicTechnologyParser.h"
|
|
#include "crlcore/Utilities.h"
|
|
|
|
|
|
|
|
|
|
namespace CRL {
|
|
|
|
|
|
using Hurricane::Error;
|
|
using Hurricane::Warning;
|
|
using Hurricane::DbU;
|
|
using Hurricane::RegularLayer;
|
|
using Hurricane::DiffusionLayer;
|
|
using Hurricane::TransistorLayer;
|
|
using Hurricane::TransistorLayer;
|
|
using Hurricane::ContactLayer;
|
|
using Hurricane::ViaLayer;
|
|
|
|
|
|
const QString SymbolicTechnologyParser::UnnamedRuleError = "Rule has an empty name.";
|
|
const QString SymbolicTechnologyParser::UnnamedBasicLayerError = "Missing name attribute in <basiclayer>.";
|
|
const QString SymbolicTechnologyParser::UnnamedSymbolicLayerError = "Missing name attribute in <%1>.";
|
|
const QString SymbolicTechnologyParser::UnnamedLayerError = "Missing name attribute in <layer>.";
|
|
const QString SymbolicTechnologyParser::InvalidRulePathError = "Invalid rule path \"%1\".";
|
|
const QString SymbolicTechnologyParser::MissingValueError = "Rule \"%1\" has no <value> attribute.";
|
|
const QString SymbolicTechnologyParser::UnknownRuleError = "Misspelled or unknown rule \"%1\".";
|
|
const QString SymbolicTechnologyParser::UndefinedLayerError = "Reference to yet undefined layer \"%1\".";
|
|
const QString SymbolicTechnologyParser::NotACompositeLayerError = "Rule layer \"%1\" is not a composite layer.";
|
|
const QString SymbolicTechnologyParser::NotABasicLayerError = "Rule sub-layer \"%1\" is not a basic layer.";
|
|
const QString SymbolicTechnologyParser::LayerOutnumber = "More than %1 sub-layers in <%2>.";
|
|
const QString SymbolicTechnologyParser::LayerMissingLayer = "Less than %1 sub-layers in <%2>.";
|
|
|
|
|
|
void SymbolicTechnologyParser::parseTechnology ()
|
|
{
|
|
parseTags ( TagsTechnology );
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseName ()
|
|
{
|
|
_technology->setName ( readTextAsString().toStdString().c_str() );
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseBasicLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
BasicLayer::Material layerMaterial = BasicLayer::Material::other;
|
|
unsigned extractNumber = 0;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedBasicLayerError );
|
|
|
|
value = _reader->attributes().value("material").toString();
|
|
if ( !value.isEmpty() ) {
|
|
if ( value == "nWell" ) layerMaterial = BasicLayer::Material::nWell;
|
|
else if ( value == "pWell" ) layerMaterial = BasicLayer::Material::pWell;
|
|
else if ( value == "nImplant" ) layerMaterial = BasicLayer::Material::nImplant;
|
|
else if ( value == "pImplant" ) layerMaterial = BasicLayer::Material::pImplant;
|
|
else if ( value == "active" ) layerMaterial = BasicLayer::Material::active;
|
|
else if ( value == "poly" ) layerMaterial = BasicLayer::Material::poly;
|
|
else if ( value == "cut" ) layerMaterial = BasicLayer::Material::cut;
|
|
else if ( value == "metal" ) layerMaterial = BasicLayer::Material::metal;
|
|
else if ( value == "blockage" ) layerMaterial = BasicLayer::Material::blockage;
|
|
else if ( value == "other" ) layerMaterial = BasicLayer::Material::other;
|
|
}
|
|
|
|
if ( !layerName.empty() ) {
|
|
_basicLayer = BasicLayer::create ( _technology, layerName, layerMaterial, extractNumber );
|
|
_layers [ _basicLayer->getName() ] = _basicLayer;
|
|
}
|
|
|
|
value = _reader->attributes().value("basiclayer").toString();
|
|
if ( not value.isEmpty() and (layerMaterial == BasicLayer::Material::blockage) ) {
|
|
layerName = value.toStdString ();
|
|
BasicLayer* routingLayer = _technology->getBasicLayer ( layerName.c_str() );
|
|
if ( routingLayer and _basicLayer ) {
|
|
routingLayer->setBlockageLayer ( _basicLayer );
|
|
}
|
|
}
|
|
|
|
parseNoChilds ();
|
|
|
|
_basicLayer = NULL;
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseRegularLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
RegularLayer* regularLayer = NULL;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedSymbolicLayerError.arg("regularlayer") );
|
|
|
|
_layerComponents.clear ();
|
|
|
|
parseTags ( TagsBasicLayers );
|
|
|
|
if ( !layerName.empty() ) {
|
|
if ( !_layerComponents.empty() ) {
|
|
if ( _layerComponents.size() > 1 )
|
|
printError ( LayerOutnumber.arg("1","regularlayer") );
|
|
|
|
regularLayer = RegularLayer::create ( _technology, layerName );
|
|
regularLayer->setBasicLayer ( _layerComponents[0] );
|
|
_layers [ regularLayer->getName() ] = regularLayer;
|
|
_layerComponents.clear ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseDiffusionLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
DiffusionLayer* layer = NULL;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedSymbolicLayerError.arg("diffusionlayer") );
|
|
|
|
_layerComponents.clear ();
|
|
|
|
parseTags ( TagsBasicLayers );
|
|
|
|
if ( !layerName.empty() ) {
|
|
reverse ( _layerComponents.begin(), _layerComponents.end() );
|
|
switch ( _layerComponents.size() ) {
|
|
case 0:
|
|
case 1:
|
|
printError ( LayerMissingLayer.arg("2","diffusionlayer") );
|
|
break;
|
|
case 2:
|
|
_layerComponents.push_back ( NULL );
|
|
default:
|
|
layer = DiffusionLayer::create ( _technology
|
|
, layerName
|
|
, _layerComponents[0]
|
|
, _layerComponents[1]
|
|
, _layerComponents[2]
|
|
);
|
|
_layers [ layer->getName() ] = layer;
|
|
if ( _layerComponents.size() > 3 )
|
|
printError ( LayerOutnumber.arg("3","diffusionlayer") );
|
|
}
|
|
}
|
|
|
|
_layerComponents.clear ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseTransistorLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
TransistorLayer* layer = NULL;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedSymbolicLayerError.arg("transistorlayer") );
|
|
|
|
_layerComponents.clear ();
|
|
|
|
parseTags ( TagsBasicLayers );
|
|
|
|
if ( !layerName.empty() ) {
|
|
reverse ( _layerComponents.begin(), _layerComponents.end() );
|
|
switch ( _layerComponents.size() ) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
printError ( LayerMissingLayer.arg("3","transistorlayer") );
|
|
break;
|
|
case 3:
|
|
_layerComponents.push_back ( NULL );
|
|
default:
|
|
layer = TransistorLayer::create ( _technology
|
|
, layerName
|
|
, _layerComponents[0]
|
|
, _layerComponents[1]
|
|
, _layerComponents[2]
|
|
, _layerComponents[3]
|
|
);
|
|
_layers [ layer->getName() ] = layer;
|
|
if ( _layerComponents.size() > 4 )
|
|
printError ( LayerOutnumber.arg("4","transistorlayer") );
|
|
}
|
|
}
|
|
|
|
_layerComponents.clear ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseContactLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
ContactLayer* layer = NULL;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedSymbolicLayerError.arg("contactlayer") );
|
|
|
|
_layerComponents.clear ();
|
|
|
|
parseTags ( TagsBasicLayers );
|
|
|
|
if ( !layerName.empty() ) {
|
|
reverse ( _layerComponents.begin(), _layerComponents.end() );
|
|
switch ( _layerComponents.size() ) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
printError ( LayerMissingLayer.arg("3","contactlayer") );
|
|
break;
|
|
case 4:
|
|
_layerComponents.push_back ( NULL );
|
|
default:
|
|
layer = ContactLayer::create ( _technology
|
|
, layerName
|
|
, _layerComponents[0]
|
|
, _layerComponents[1]
|
|
, _layerComponents[2]
|
|
, _layerComponents[3]
|
|
, _layerComponents[4]
|
|
);
|
|
_layers [ layer->getName() ] = layer;
|
|
if ( _layerComponents.size() > 5 )
|
|
printError ( LayerOutnumber.arg("5","contactlayer") );
|
|
}
|
|
}
|
|
|
|
_layerComponents.clear ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseViaLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
ViaLayer* layer = NULL;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedSymbolicLayerError.arg("vialayer") );
|
|
|
|
_layerComponents.clear ();
|
|
|
|
parseTags ( TagsBasicLayers );
|
|
|
|
if ( !layerName.empty() ) {
|
|
reverse ( _layerComponents.begin(), _layerComponents.end() );
|
|
switch ( _layerComponents.size() ) {
|
|
case 0:
|
|
case 1:
|
|
printError ( LayerMissingLayer.arg("3","vialayer") );
|
|
break;
|
|
default:
|
|
layer = ViaLayer::create ( _technology
|
|
, layerName
|
|
, _layerComponents[0]
|
|
, _layerComponents[1]
|
|
, _layerComponents[2]
|
|
);
|
|
_layers [ layer->getName() ] = layer;
|
|
if ( _layerComponents.size() > 3 )
|
|
printError ( LayerOutnumber.arg("3","vialayer") );
|
|
}
|
|
}
|
|
|
|
_layerComponents.clear ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseLayer ()
|
|
{
|
|
QString value;
|
|
string layerName;
|
|
|
|
value = _reader->attributes().value("name").toString();
|
|
if ( !value.isEmpty() )
|
|
layerName = value.toStdString ();
|
|
else
|
|
printError ( UnnamedLayerError );
|
|
|
|
if ( !layerName.empty() ) {
|
|
BasicLayer* basicLayer = getBasicLayer ( QString(layerName.c_str()), false );
|
|
if ( basicLayer )
|
|
_layerComponents.push_back ( basicLayer );
|
|
}
|
|
|
|
parseNoChilds ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseSymbolic ()
|
|
{
|
|
parseTags ( TagsSymbolic );
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parsePrecision ()
|
|
{
|
|
DbU::setPrecision ( readTextAsUInt() );
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseGridStep ()
|
|
{
|
|
//DbU::setGridStep ( DbU::symbolic( readTextAsDouble()) );
|
|
parseNoChilds ();
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseRules ()
|
|
{
|
|
parseTags ( TagsRules );
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::parseRule ()
|
|
{
|
|
double doubleValue = 0.0;
|
|
Layer* ruleLayer = NULL;
|
|
BasicLayer* basicLayer = NULL;
|
|
QString ruleName;
|
|
unsigned int ruleType;
|
|
|
|
ruleName = _reader->attributes().value("name").toString();
|
|
if ( !ruleName.isEmpty() ) {
|
|
//cerr << qPrintable(ruleName) << endl;
|
|
ruleType = splitRulePath ( ruleName, ruleLayer, basicLayer );
|
|
if ( ( ruleType != InvalidRule ) && ( ruleLayer ) ) {
|
|
QString ruleValue = _reader->attributes().value("value").toString();
|
|
if ( !ruleValue.isEmpty() ) {
|
|
switch ( ruleType & ValueMask ) {
|
|
case DoubleValue: doubleValue = ruleValue.toDouble(); break;
|
|
}
|
|
switch ( ruleType ) {
|
|
case ExtentionCap: ruleLayer->setExtentionCap (basicLayer,DbU::lambda(doubleValue)); break;
|
|
case ExtentionWidth: ruleLayer->setExtentionWidth(basicLayer,DbU::lambda(doubleValue)); break;
|
|
case Enclosure: ruleLayer->setEnclosure (basicLayer,DbU::lambda(doubleValue)); break;
|
|
case MinimumWidth: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break;
|
|
case MinimumSide: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break;
|
|
}
|
|
} else
|
|
printError ( MissingValueError.arg(ruleName) );
|
|
} else
|
|
if ( ruleLayer )
|
|
printError ( UnknownRuleError.arg(ruleName) );
|
|
} else
|
|
printError ( UnnamedRuleError );
|
|
|
|
parseNoChilds ();
|
|
}
|
|
|
|
|
|
unsigned int SymbolicTechnologyParser::splitRulePath ( const QString& path
|
|
, Layer*& ruleLayer
|
|
, BasicLayer*& basicLayer
|
|
)
|
|
{
|
|
ruleLayer = NULL;
|
|
basicLayer = NULL;
|
|
|
|
unsigned int ruleType = InvalidRule;
|
|
QStringList pathElements = path.split ( "." );
|
|
|
|
if ( pathElements.isEmpty() ) {
|
|
printError ( InvalidRulePathError.arg(path) );
|
|
return ruleType;
|
|
}
|
|
|
|
ruleLayer = getLayer ( pathElements[0], false );
|
|
pathElements.pop_front ();
|
|
|
|
basicLayer = getBasicLayer ( pathElements[0], true );
|
|
if ( basicLayer ) pathElements.pop_front ();
|
|
|
|
QString tailPath = pathElements.join ( "." );
|
|
|
|
if ( tailPath == "extention.cap" ) ruleType = ExtentionCap;
|
|
else if ( tailPath == "extention.width" ) ruleType = ExtentionWidth;
|
|
else if ( tailPath == "enclosure" ) ruleType = Enclosure;
|
|
else if ( tailPath == "minimum.width" ) ruleType = MinimumWidth;
|
|
else if ( tailPath == "minimum.side" ) ruleType = MinimumSide;
|
|
|
|
return ruleType;
|
|
}
|
|
|
|
|
|
Layer* SymbolicTechnologyParser::getLayer ( const QString& name, bool ignoreError )
|
|
{
|
|
Name layerName = name.toStdString();
|
|
map<const Name,Layer*>::iterator it = _layers.find ( layerName );
|
|
|
|
if ( it == _layers.end() ) {
|
|
if ( !ignoreError )
|
|
printError ( UndefinedLayerError.arg(name) );
|
|
return NULL;
|
|
}
|
|
|
|
return it->second;
|
|
}
|
|
|
|
|
|
BasicLayer* SymbolicTechnologyParser::getBasicLayer ( const QString& name, bool ignoreError )
|
|
{
|
|
Name layerName = name.toStdString();
|
|
map<const Name,Layer*>::iterator it = _layers.find ( layerName );
|
|
|
|
if ( it == _layers.end() ) {
|
|
if ( !ignoreError )
|
|
printError ( UndefinedLayerError.arg(name) );
|
|
return NULL;
|
|
}
|
|
|
|
BasicLayer* basicLayer = dynamic_cast<BasicLayer*> ( it->second );
|
|
if ( !basicLayer )
|
|
printError ( NotABasicLayerError.arg(name) );
|
|
|
|
return basicLayer;
|
|
}
|
|
|
|
|
|
SymbolicTechnologyParser::SymbolicTechnologyParser ( DataBase* db, QXmlStreamReader* reader )
|
|
: XmlParser(reader,TagSetSize)
|
|
, _dataBase(db)
|
|
, _technology(NULL)
|
|
, _basicLayer(NULL)
|
|
, _layers()
|
|
, _layerComponents()
|
|
{
|
|
assert ( _dataBase != NULL );
|
|
|
|
_technology = db->getTechnology ();
|
|
if ( !_technology )
|
|
_technology = Technology::create ( db, "<SymbolicTechnologyParser>" );
|
|
|
|
addTagEntry ( TagsStandAlone , "technology" , (tagParser_t)&SymbolicTechnologyParser::parseTechnology );
|
|
addTagEntry ( TagsTechnology , "name" , (tagParser_t)&SymbolicTechnologyParser::parseName );
|
|
addTagEntry ( TagsTechnology , "basiclayer" , (tagParser_t)&SymbolicTechnologyParser::parseBasicLayer );
|
|
addTagEntry ( TagsTechnology , "regularlayer" , (tagParser_t)&SymbolicTechnologyParser::parseRegularLayer );
|
|
addTagEntry ( TagsTechnology , "diffusionlayer" , (tagParser_t)&SymbolicTechnologyParser::parseDiffusionLayer );
|
|
addTagEntry ( TagsTechnology , "transistorlayer", (tagParser_t)&SymbolicTechnologyParser::parseTransistorLayer );
|
|
addTagEntry ( TagsTechnology , "vialayer" , (tagParser_t)&SymbolicTechnologyParser::parseViaLayer );
|
|
addTagEntry ( TagsTechnology , "contactlayer" , (tagParser_t)&SymbolicTechnologyParser::parseContactLayer );
|
|
addTagEntry ( TagsBasicLayers , "layer" , (tagParser_t)&SymbolicTechnologyParser::parseLayer );
|
|
addTagEntry ( TagsTechnology , "symbolic" , (tagParser_t)&SymbolicTechnologyParser::parseSymbolic );
|
|
addTagEntry ( TagsSymbolic , "precision" , (tagParser_t)&SymbolicTechnologyParser::parsePrecision );
|
|
addTagEntry ( TagsSymbolic , "gridstep" , (tagParser_t)&SymbolicTechnologyParser::parseGridStep );
|
|
addTagEntry ( TagsSymbolic , "rules" , (tagParser_t)&SymbolicTechnologyParser::parseRules );
|
|
addTagEntry ( TagsRules , "rule" , (tagParser_t)&SymbolicTechnologyParser::parseRule );
|
|
}
|
|
|
|
|
|
SymbolicTechnologyParser* SymbolicTechnologyParser::create ( DataBase* db, QXmlStreamReader* reader )
|
|
{
|
|
return new SymbolicTechnologyParser ( db, reader );
|
|
}
|
|
|
|
|
|
bool SymbolicTechnologyParser::load ( DataBase* db, const string& path )
|
|
{
|
|
bool aborted = false;
|
|
|
|
try {
|
|
SymbolicTechnologyParser tp ( db );
|
|
return tp._load ( path );
|
|
}
|
|
catch ( Error& e ) {
|
|
cerr << e.what() << endl;
|
|
aborted = true;
|
|
}
|
|
catch ( ... ) {
|
|
cout << "[ERROR] Abnormal termination: unknown exception.\n" << endl;
|
|
exit ( 2 );
|
|
}
|
|
|
|
if ( aborted ) {
|
|
cerr << "[ERROR] Aborting & unloading Technology." << endl;
|
|
|
|
//Technology* technology = db->getTechnology ();
|
|
//if ( technology ) technology->destroy ();
|
|
|
|
exit ( 1 );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void SymbolicTechnologyParser::_postLoad ()
|
|
{
|
|
// Fixme.
|
|
_technology->setSymbolicLayer ( "POLY" );
|
|
_technology->setSymbolicLayer ( "METAL1" );
|
|
_technology->setSymbolicLayer ( "METAL2" );
|
|
_technology->setSymbolicLayer ( "METAL3" );
|
|
_technology->setSymbolicLayer ( "METAL4" );
|
|
_technology->setSymbolicLayer ( "METAL5" );
|
|
_technology->setSymbolicLayer ( "METAL6" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE1" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE2" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE3" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE4" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE5" );
|
|
_technology->setSymbolicLayer ( "BLOCKAGE6" );
|
|
_technology->setSymbolicLayer ( "gmetalh" );
|
|
_technology->setSymbolicLayer ( "gmetalv" );
|
|
_technology->setSymbolicLayer ( "VIA12" );
|
|
_technology->setSymbolicLayer ( "VIA23" );
|
|
_technology->setSymbolicLayer ( "VIA34" );
|
|
_technology->setSymbolicLayer ( "VIA45" );
|
|
_technology->setSymbolicLayer ( "VIA56" );
|
|
_technology->setSymbolicLayer ( "gcontact" );
|
|
}
|
|
|
|
|
|
const char* SymbolicTechnologyParser::_getMessage ( MessageId id )
|
|
{
|
|
const char* message = "<unknwown message id>";
|
|
switch ( id ) {
|
|
case OpenFile: message = "Technology configuration"; break;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
} // End of CRL namespace.
|