Skip to content

Commit 52ce7d8

Browse files
authored
Merge pull request #10909 from AcKoucher/rcx-set-corners-refactor
rcx: refactor to isolate extraction rules parsing logic into its own function
2 parents 8e9ec4b + 44c6cb8 commit 52ce7d8

7 files changed

Lines changed: 151 additions & 117 deletions

File tree

src/rcx/include/rcx/extRCap.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,7 @@ class extMain
18271827
const char* prefix,
18281828
const char* postfix,
18291829
bool v = false);
1830-
bool modelExists(const char* extRules);
1830+
bool modelExists();
18311831

18321832
void addInstsGeometries(const Array1D<uint32_t>* instTable,
18331833
Array1D<uint32_t>* tmpInstIdTable,
@@ -2267,7 +2267,7 @@ class extMain
22672267
void cleanCornerTables();
22682268
int getDbCornerIndex(const char* name);
22692269
int getDbCornerModel(const char* name);
2270-
bool setCorners(const char* rulesFileName);
2270+
void registerRulesModel(extRCModel* rules_model);
22712271
int getProcessCornerDbIndex(int pcidx);
22722272
void getScaledCornerDbIndex(int pcidx, int& scidx, int& scdbIdx);
22732273
void getScaledRC(int sidx, double& res, double& cap);
@@ -2713,7 +2713,6 @@ class extMain
27132713
int _ccMaxY;
27142714
double _mergeResBound = 0.0;
27152715
bool _mergeViaRes = false;
2716-
const char* rules_file_path_{nullptr};
27172716
const char* target_nets_names_{nullptr};
27182717
bool _mergeParallelCC = false;
27192718
bool _reportNetNoWire = false;
@@ -2829,4 +2828,10 @@ class extMain
28292828
// ---------------------------------------------------------
28302829
};
28312830

2831+
std::unique_ptr<extRCModel> parseRules(
2832+
odb::dbTech* tech,
2833+
const Array1D<extCorner*>* extractor_corner_table,
2834+
bool is_v2,
2835+
utl::Logger* logger);
2836+
28322837
} // namespace rcx

src/rcx/src/OpenRCX.tcl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,7 @@ proc extract_parasitics { args } {
8383

8484
set ext_model_file ""
8585
if { [info exists keys(-ext_model_file)] } {
86-
utl::warn RCX 514 "The -ext_model_file option is deprecated. Use\
87-
set_extraction_rules_file command instead."
88-
89-
# We may have multiple technologies loaded, so use the current block's
90-
# tech to prevent an error resolving an ambiguous default tech.
91-
set tech [[ord::get_db_block] getTech]
92-
set_extraction_rules_file -tech [$tech getName] $keys(-ext_model_file)
86+
set ext_model_file $keys(-ext_model_file)
9387
}
9488

9589
set corner_cnt 1

src/rcx/src/ext.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,17 @@ void Ext::extract(ExtractOptions options)
216216

217217
odb::orderWires(logger_, block);
218218

219-
std::string rules_file = block->getTech()->getExtractionRulesFile();
219+
odb::dbTech* tech = block->getTech();
220+
if (options.ext_model_file != nullptr && options.ext_model_file[0] != '\0') {
221+
logger_->warn(RCX,
222+
514,
223+
"The ext_model_file option is deprecated. Use "
224+
"set_extraction_rules_file command instead.");
225+
226+
tech->setExtractionRulesFile(options.ext_model_file);
227+
}
228+
229+
std::string rules_file = tech->getExtractionRulesFile();
220230
if (!rules_file.empty()) {
221231
options.ext_model_file = rules_file.c_str();
222232
}

src/rcx/src/extmain.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ void extMain::setExtractionOptions(const ExtractOptions& options)
4343
_lef_res = options.lef_res;
4444
_lefRC = options.lef_rc;
4545
_dbgOption = options._dbg;
46-
rules_file_path_ = options.ext_model_file;
4746
target_nets_names_ = options.net;
4847
}
4948

src/rcx/src/extmain_v2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void extMain::makeBlockRCsegs_v2(const char* netNames, const char* extRules)
7272
// Model file is required if not option _lefRC is used.
7373
// _lefRC option requires Resistance and Capacitance values per Layer and
7474
// Technology to be taken from LEF file.
75-
if (!_lefRC && !modelExists(extRules)) {
75+
if (!_lefRC && !modelExists()) {
7676
return;
7777
}
7878

src/rcx/src/netRC.cpp

Lines changed: 127 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -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

15831606
void 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

16511674
void 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;

src/rcx/test/rcx_aux.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import utl
21
import rcx
32

43
# Thin wrapper over api defined in ext.i (and reused by ext-py.i)
@@ -28,21 +27,11 @@ def extract_parasitics(
2827
dbg=0
2928
):
3029

31-
if ext_model_file is not None:
32-
utl.warn(
33-
utl.RCX,
34-
514,
35-
"The ext_model_file option is deprecated. Use "
36-
"set_extraction_rules_file command instead.",
37-
)
38-
39-
# We may have multiple technologies loaded, so use the current block's
40-
# tech to prevent an error resolving an ambiguous default tech.
41-
db_tech = design.getBlock().getTech()
42-
db_tech.setExtractionRulesFile(ext_model_file)
43-
4430
opts = rcx.ExtractOptions()
4531

32+
if ext_model_file is not None:
33+
opts.ext_model_file = ext_model_file
34+
4635
opts.corner_cnt = corner_cnt
4736
opts.corner = corner
4837
opts.max_res = max_res

0 commit comments

Comments
 (0)