-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ant: return CAR and CSR violations to repair_antennas #5242
Changes from 4 commits
a3b4df2
15c04d7
2f396b3
932785e
b29ffd8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -740,6 +740,92 @@ bool AntennaChecker::checkCSR(odb::dbTechLayer* tech_layer, | |
return violation; | ||
} | ||
|
||
bool AntennaChecker::checkRatioViolations(odb::dbTechLayer* layer, | ||
const NodeInfo& node_info, | ||
bool verbose, | ||
bool report, | ||
std::ofstream& report_file) | ||
{ | ||
bool node_has_violation = false; | ||
auto par_violation = checkPAR(layer, node_info, verbose, report, report_file); | ||
bool car_violation = checkCAR(layer, node_info, verbose, report, report_file); | ||
node_has_violation = par_violation.first || car_violation; | ||
|
||
if (layer->getRoutingLevel() != 0) { | ||
auto psr_violation | ||
= checkPSR(layer, node_info, verbose, report, report_file); | ||
bool csr_violation | ||
= checkCSR(layer, node_info, verbose, report, report_file); | ||
node_has_violation | ||
= node_has_violation || psr_violation.first || csr_violation; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does check* have a side-effect or should we skip this if node_has_violation was already set by PAR/CAR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should not skip because a net can have both PAR/CAR and PSR/CSR. Skipping it will give us the wrong number of violations and make the report incorrect. |
||
|
||
return node_has_violation; | ||
} | ||
|
||
void AntennaChecker::reportNet(odb::dbNet* db_net, | ||
GateToLayerToNodeInfo& gate_info, | ||
GateToViolationLayers& gates_with_violations, | ||
bool verbose, | ||
std::ofstream& report_file) | ||
{ | ||
std::string net_name = fmt::format("Net: {}", db_net->getConstName()); | ||
if (verbose) { | ||
logger_->report("{}", net_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << net_name << "\n"; | ||
} | ||
for (const auto& [node, layer_to_node] : gate_info) { | ||
if (!verbose | ||
&& gates_with_violations.find(node) == gates_with_violations.end()) { | ||
continue; | ||
} | ||
std::string pin_name = fmt::format(" Pin: {}", node); | ||
if (verbose) { | ||
logger_->report("{}", pin_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << pin_name << "\n"; | ||
} | ||
for (const auto& [layer, node_info] : layer_to_node) { | ||
if (!verbose | ||
&& gates_with_violations[node].find(layer) | ||
== gates_with_violations[node].end()) { | ||
continue; | ||
} | ||
std::string layer_name | ||
= fmt::format(" Layer: {}", layer->getConstName()); | ||
if (verbose) { | ||
logger_->report("{}", layer_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << layer_name << "\n"; | ||
} | ||
// re-check to report violations | ||
checkRatioViolations(layer, node_info, verbose, true, report_file); | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
} | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
} | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
} | ||
|
||
int AntennaChecker::checkGates(odb::dbNet* db_net, | ||
bool verbose, | ||
bool report_if_no_violation, | ||
|
@@ -752,42 +838,19 @@ int AntennaChecker::checkGates(odb::dbNet* db_net, | |
ratio_margin_ = ratio_margin; | ||
int pin_violation_count = 0; | ||
|
||
std::unordered_map<std::string, std::unordered_set<odb::dbTechLayer*>> | ||
gates_with_violations; | ||
GateToViolationLayers gates_with_violations; | ||
|
||
for (const auto& gate_info : gate_info) { | ||
for (const auto& [node, layer_to_node] : gate_info) { | ||
bool pin_has_violation = false; | ||
|
||
for (const auto& layer_info : gate_info.second) { | ||
bool node_has_violation = false; | ||
if (layer_info.first->hasDefaultAntennaRule()) { | ||
// check if node has violation | ||
if (layer_info.first->getRoutingLevel() != 0) { | ||
auto par_violation = checkPAR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
auto psr_violation = checkPSR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
bool car_violation = checkCAR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
bool csr_violation = checkCSR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
for (const auto& [layer, node_info] : layer_to_node) { | ||
if (layer->hasDefaultAntennaRule()) { | ||
bool node_has_violation | ||
= checkRatioViolations(layer, node_info, false, false, report_file); | ||
|
||
if (par_violation.first || psr_violation.first || car_violation | ||
|| csr_violation) { | ||
node_has_violation = true; | ||
} | ||
} else { | ||
auto par_violation = checkPAR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
bool car_violation = checkCAR( | ||
layer_info.first, layer_info.second, false, false, report_file); | ||
if (par_violation.first || car_violation) { | ||
node_has_violation = true; | ||
} | ||
} | ||
if (node_has_violation) { | ||
pin_has_violation = true; | ||
gates_with_violations[gate_info.first].insert(layer_info.first); | ||
gates_with_violations[node].insert(layer); | ||
} | ||
} | ||
} | ||
|
@@ -799,95 +862,25 @@ int AntennaChecker::checkGates(odb::dbNet* db_net, | |
// iterate the gates with violations to report | ||
if (((pin_violation_count > 0) || report_if_no_violation) | ||
&& diode_mterm == nullptr) { | ||
std::string net_name = fmt::format("Net: {}", db_net->getConstName()); | ||
if (verbose) { | ||
logger_->report("{}", net_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << net_name << "\n"; | ||
} | ||
for (const auto& gate_it : gate_info) { | ||
if (!verbose | ||
&& gates_with_violations.find(gate_it.first) | ||
== gates_with_violations.end()) { | ||
continue; | ||
} | ||
std::string pin_name = fmt::format(" Pin: {}", gate_it.first); | ||
if (verbose) { | ||
logger_->report("{}", pin_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << pin_name << "\n"; | ||
} | ||
for (const auto& layer_info : gate_info[gate_it.first]) { | ||
if (!verbose | ||
&& gates_with_violations[gate_it.first].find(layer_info.first) | ||
== gates_with_violations[gate_it.first].end()) { | ||
continue; | ||
} | ||
std::string layer_name | ||
= fmt::format(" Layer: {}", layer_info.first->getConstName()); | ||
if (verbose) { | ||
logger_->report("{}", layer_name); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << layer_name << "\n"; | ||
} | ||
// re-check to report violations | ||
if (layer_info.first->getRoutingLevel() != 0) { | ||
checkPAR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
checkPSR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
checkCAR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
checkCSR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
} else { | ||
checkPAR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
checkCAR( | ||
layer_info.first, layer_info.second, verbose, true, report_file); | ||
} | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
} | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
} | ||
if (verbose) { | ||
logger_->report(""); | ||
} | ||
if (report_file.is_open()) { | ||
report_file << "\n"; | ||
} | ||
reportNet(db_net, gate_info, gates_with_violations, verbose, report_file); | ||
} | ||
|
||
std::unordered_map<odb::dbTechLayer*, std::unordered_set<std::string>> | ||
pin_added; | ||
// if checkGates is used by repair antennas | ||
if (pin_violation_count > 0) { | ||
for (const auto& gate_iter : gates_with_violations) { | ||
for (const auto& layer_info : gate_iter.second) { | ||
for (const auto& [gate, violation_layers] : gates_with_violations) { | ||
for (odb::dbTechLayer* layer : violation_layers) { | ||
// when repair antenna is running, calculate number of diodes | ||
if (layer_info->getRoutingLevel() != 0 | ||
&& pin_added[layer_info].find(gate_iter.first) | ||
== pin_added[layer_info].end()) { | ||
if (layer->getRoutingLevel() != 0 | ||
&& pin_added[layer].find(gate) == pin_added[layer].end()) { | ||
double diode_diff_area = 0.0; | ||
if (diode_mterm) { | ||
diode_diff_area = diffArea(diode_mterm); | ||
} | ||
NodeInfo violation_info = gate_info[gate_iter.first][layer_info]; | ||
NodeInfo violation_info = gate_info[gate][layer]; | ||
std::vector<odb::dbITerm*> gates = violation_info.iterms; | ||
odb::dbTechLayer* violation_layer = layer_info; | ||
odb::dbTechLayer* violation_layer = layer; | ||
int diode_count_per_gate = 0; | ||
// check violations only PAR & PSR | ||
auto par_violation = checkPAR( | ||
|
@@ -926,7 +919,23 @@ int AntennaChecker::checkGates(odb::dbNet* db_net, | |
// save antenna violation | ||
if (violated) { | ||
antenna_violations.push_back( | ||
{layer_info->getRoutingLevel(), gates, diode_count_per_gate}); | ||
{layer->getRoutingLevel(), gates, diode_count_per_gate}); | ||
} | ||
|
||
bool car_violation = checkCAR( | ||
violation_layer, violation_info, false, false, report_file); | ||
bool csr_violation = checkCSR( | ||
violation_layer, violation_info, false, false, report_file); | ||
|
||
// naive approach for cumulative area violations. here, all the pins | ||
// of the net are included, and placing one diode per pin is not the | ||
// best approach. as a first implementation, insert one diode per net. | ||
// TODO: implement a proper approach for CAR violations | ||
if (car_violation || csr_violation) { | ||
std::vector<odb::dbITerm*> gates_for_violation; | ||
gates_for_violation.push_back(gates[0]); | ||
antenna_violations.push_back( | ||
{layer->getRoutingLevel(), gates_for_violation, 1}); | ||
} | ||
} | ||
} | ||
|
@@ -936,8 +945,7 @@ int AntennaChecker::checkGates(odb::dbNet* db_net, | |
} | ||
|
||
void AntennaChecker::buildLayerMaps(odb::dbNet* db_net, | ||
LayerToGraphNodes& node_by_layer_map, | ||
GateToLayerToNodeInfo& gate_info) | ||
LayerToGraphNodes& node_by_layer_map) | ||
{ | ||
odb::dbWire* wires = db_net->getWire(); | ||
|
||
|
@@ -1023,7 +1031,7 @@ void AntennaChecker::checkNet(odb::dbNet* db_net, | |
if (wire) { | ||
LayerToGraphNodes node_by_layer_map; | ||
GateToLayerToNodeInfo gate_info; | ||
buildLayerMaps(db_net, node_by_layer_map, gate_info); | ||
buildLayerMaps(db_net, node_by_layer_map); | ||
|
||
calculateAreas(node_by_layer_map, gate_info); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to define node_has_violation and then set it afterwards, just combine 749 & 752