@@ -1469,88 +1469,121 @@ void extMain::makeCornerNameMap()
14691469 updatePrevControl ();
14701470}
14711471
1472- bool extMain::setCorners (const char * rulesFileName)
1472+ std::unique_ptr<extRCModel> parseRules (
1473+ odb::dbTech* tech,
1474+ const Array1D<extCorner*>* extractor_corner_table,
1475+ bool is_v2,
1476+ utl::Logger* logger)
14731477{
1474- _modelMap.resetCnt (0 );
1475- _metRCTable.resetCnt (0 );
1478+ // Rules files are written assuming this DBU-per-micron resolution; the
1479+ // tech may use a finer one, in which case rules-file values are scaled
1480+ // up when read.
1481+ constexpr int rules_file_dbu_per_micron = 1000 ;
1482+ const int tech_dbu_per_micron = tech->getDbUnitsPerMicron ();
1483+ double rules_to_dbu_scale = 1.0 ;
1484+
1485+ if (tech_dbu_per_micron > rules_file_dbu_per_micron) {
1486+ rules_to_dbu_scale
1487+ = static_cast <double >(tech_dbu_per_micron) / rules_file_dbu_per_micron;
1488+ }
14761489
1477- if (rulesFileName != nullptr ) { // read rules
1490+ auto model = std::make_unique<extRCModel>( " MINTYPMAX " , logger);
14781491
1479- int dbunit = _block->getDbUnitsPerMicron ();
1480- double dbFactor = 1 ;
1481- if (dbunit > 1000 ) {
1482- dbFactor = dbunit * 0.001 ;
1492+ std::vector<uint32_t > corner_table;
1493+ if (extractor_corner_table) {
1494+ for (uint32_t ii = 0 ; ii < extractor_corner_table->getCnt (); ii++) {
1495+ extCorner* corner = extractor_corner_table->get (ii);
1496+ corner_table.push_back (corner->_model );
14831497 }
1498+ }
14841499
1485- extRCModel* m = new extRCModel (" MINTYPMAX" , logger_);
1486- _modelTable->add (m);
1500+ const std::string rules_file = tech->getExtractionRulesFile ();
1501+ if (rules_file.empty ()) {
1502+ logger->error (RCX ,
1503+ 17 ,
1504+ " Could not parse extraction rules. No extraction rules file "
1505+ " specified. Use set_extraction_rules_file to specify it." );
1506+ }
14871507
1488- uint32_t cornerTable[10 ];
1489- uint32_t extDbCnt = 0 ;
1508+ logger->info (RCX , 435 , " Reading extraction model file {} ..." , rules_file);
14901509
1491- if (_processCornerTable != nullptr ) {
1492- for (uint32_t ii = 0 ; ii < _processCornerTable->getCnt (); ii++) {
1493- extCorner* s = _processCornerTable->get (ii);
1494- cornerTable[extDbCnt++] = s->_model ;
1495- _modelMap.add (ii);
1496- }
1510+ FILE * file = fopen (rules_file.c_str (), " r" );
1511+ if (file == nullptr ) {
1512+ logger->error (RCX , 468 , " Can't open extraction model file {}" , rules_file);
1513+ }
1514+
1515+ fclose (file);
1516+
1517+ const bool is_v2_rules_file
1518+ = model->isRulesFile_v2 ((char *) rules_file.c_str (), false );
1519+
1520+ if (is_v2 || is_v2_rules_file) {
1521+ model->_v2_flow = is_v2;
1522+ if (!model->readRules ((char *) rules_file.c_str (),
1523+ false ,
1524+ true ,
1525+ true ,
1526+ true ,
1527+ true ,
1528+ corner_table.size (),
1529+ corner_table.data (),
1530+ rules_to_dbu_scale)) {
1531+ logger->error (
1532+ RCX , 14 , " Failed to parse extraction model file {}" , rules_file);
14971533 }
1534+ } else {
1535+ if (!model->readRules_v1 ((char *) rules_file.c_str (),
1536+ false ,
1537+ true ,
1538+ true ,
1539+ true ,
1540+ true ,
1541+ corner_table.size (),
1542+ corner_table.data (),
1543+ rules_to_dbu_scale)) {
1544+ logger->error (
1545+ RCX , 15 , " Failed to parse extraction model file {}" , rules_file);
1546+ }
1547+ }
14981548
1499- logger_->info (
1500- RCX , 435 , " Reading extraction model file {} ..." , rulesFileName);
1549+ if (model->getModelCnt () == 0 ) {
1550+ logger->error (RCX ,
1551+ 487 ,
1552+ " No RC model read from the extraction model! "
1553+ " Ensure the right extRules file is used!" );
1554+ }
15011555
1502- FILE * rules_file = fopen (rulesFileName, " r" );
1503- if (rules_file == nullptr ) {
1504- logger_->error (
1505- RCX , 468 , " Can't open extraction model file {}" , rulesFileName);
1506- }
1507- fclose (rules_file);
1508- bool v2_rules_file = m->isRulesFile_v2 ((char *) rulesFileName, false );
1509-
1510- if (_v2 || v2_rules_file) {
1511- m->_v2_flow = _v2;
1512-
1513- if (!(m->readRules ((char *) rulesFileName,
1514- false ,
1515- true ,
1516- true ,
1517- true ,
1518- true ,
1519- extDbCnt,
1520- cornerTable,
1521- dbFactor))) {
1522- return false ;
1523- }
1524- } else {
1525- if (!(m->readRules_v1 ((char *) rulesFileName,
1526- false ,
1527- true ,
1528- true ,
1529- true ,
1530- true ,
1531- extDbCnt,
1532- cornerTable,
1533- dbFactor))) {
1534- return false ;
1535- }
1556+ return model;
1557+ }
1558+
1559+ void extMain::registerRulesModel (extRCModel* rules_model)
1560+ {
1561+ // Differently from the other corner-related structures, the
1562+ // list of models is cleared at the end of the extraction flow.
1563+ _modelTable->add (rules_model);
1564+
1565+ // Clear rules data per corner.
1566+ _metRCTable.resetCnt (0 );
1567+
1568+ // Clear corner -> model mapping.
1569+ _modelMap.resetCnt (0 );
1570+
1571+ if (_processCornerTable != nullptr ) {
1572+ for (uint32_t ii = 0 ; ii < _processCornerTable->getCnt (); ii++) {
1573+ _modelMap.add (ii);
15361574 }
1537- int modelCnt = getRCmodel ( 0 )-> getModelCnt ();
1575+ }
15381576
1539- // If RCX reads wrong extRules file format
1540- if (modelCnt == 0 ) {
1541- logger_->error (RCX ,
1542- 487 ,
1543- " No RC model read from the extraction model! "
1544- " Ensure the right extRules file is used!" );
1545- }
1546- if (_processCornerTable == nullptr ) {
1547- for (int ii = 0 ; ii < modelCnt; ii++) {
1548- addRCCorner (nullptr , ii, 0 );
1549- _modelMap.add (ii);
1550- }
1577+ if (_processCornerTable == nullptr ) {
1578+ const int modelCnt = getRCmodel (0 )->getModelCnt ();
1579+ for (int ii = 0 ; ii < modelCnt; ii++) {
1580+ addRCCorner (nullptr , ii, 0 );
1581+ _modelMap.add (ii);
15511582 }
15521583 }
1584+
15531585 _currentModel = getRCmodel (0 );
1586+
15541587 if (_v2) {
15551588 if (_processCornerTable != nullptr && _couplingFlag > 0 ) {
15561589 for (uint32_t ii = 0 ; ii < _processCornerTable->getCnt (); ii++) {
@@ -1566,18 +1599,8 @@ bool extMain::setCorners(const char* rulesFileName)
15661599 _metRCTable.add (_currentModel->getMetRCTable (jj));
15671600 }
15681601 }
1569- _extDbCnt = _processCornerTable->getCnt ();
1570-
1571- #ifndef NDEBUG
1572- uint32_t scaleCornerCnt = 0 ;
1573- if (_scaledCornerTable != nullptr ) {
1574- scaleCornerCnt = _scaledCornerTable->getCnt ();
1575- }
1576- assert (_cornerCnt == _extDbCnt + scaleCornerCnt);
1577- #endif
15781602
1579- _block->setCornerCount (_cornerCnt, _extDbCnt, nullptr );
1580- return true ;
1603+ _extDbCnt = _processCornerTable->getCnt ();
15811604}
15821605
15831606void extMain::addDummyCorners (uint32_t cornerCnt)
@@ -1635,10 +1658,10 @@ void extMain::getPrevControl()
16351658 _ccNoPowerTarget = _prevControl->_ccNoPowerTarget ;
16361659 _usingMetalPlanes = _prevControl->_usingMetalPlanes ;
16371660}
1638- bool extMain::modelExists (const char * extRules )
1661+ bool extMain::modelExists ()
16391662{
16401663 if ((_prevControl->_ruleFileName .empty ()) && (getRCmodel (0 ) == nullptr )
1641- && (extRules == nullptr )) {
1664+ && (_block-> getTech ()-> getExtractionRulesFile (). empty () )) {
16421665 logger_->warn (RCX ,
16431666 127 ,
16441667 " No RC model was read with command <load_model>, "
@@ -1650,7 +1673,7 @@ bool extMain::modelExists(const char* extRules)
16501673
16511674void extMain::makeBlockRCsegs ()
16521675{
1653- if (!modelExists (rules_file_path_ )) {
1676+ if (!modelExists ()) {
16541677 return ;
16551678 }
16561679
@@ -1659,17 +1682,31 @@ void extMain::makeBlockRCsegs()
16591682 _diagFlow = true ;
16601683 _usingMetalPlanes = true ;
16611684
1685+ odb::dbTech* tech = _block->getTech ();
1686+ const bool has_rules_file = !tech->getExtractionRulesFile ().empty ();
1687+
16621688 if ((_processCornerTable != nullptr )
1663- || ((_processCornerTable == nullptr ) && (rules_file_path_ != nullptr ))) {
1664- const char * rules_file_path = rules_file_path_
1665- ? rules_file_path_
1666- : _prevControl->_ruleFileName .c_str ();
1667-
1668- // Reading model file
1669- if (!setCorners (rules_file_path)) {
1670- logger_->info (RCX , 128 , " skipping Extraction ..." );
1671- return ;
1689+ || ((_processCornerTable == nullptr ) && has_rules_file)) {
1690+ std::unique_ptr<extRCModel> rules_model
1691+ = parseRules (tech, _processCornerTable, _v2, logger_);
1692+ registerRulesModel (rules_model.release ());
1693+
1694+ uint32_t scaled_corner_count = 0 ;
1695+ if (_scaledCornerTable != nullptr ) {
1696+ scaled_corner_count = _scaledCornerTable->getCnt ();
1697+ }
1698+
1699+ if (_cornerCnt != _extDbCnt + scaled_corner_count) {
1700+ logger_->error (RCX ,
1701+ 16 ,
1702+ " Corner count invariant violated: total corners ({}) != "
1703+ " process corners ({}) + scaled corners ({})" ,
1704+ _cornerCnt,
1705+ _extDbCnt,
1706+ scaled_corner_count);
16721707 }
1708+
1709+ _block->setCornerCount (_cornerCnt, _extDbCnt, nullptr );
16731710 } else if (setMinTypMax (false , false , false , -1 , -1 , -1 , 1 ) < 0 ) {
16741711 logger_->warn (RCX , 129 , " Wrong combination of corner related options!" );
16751712 return ;
0 commit comments