diff --git a/src/drt/src/io/io.cpp b/src/drt/src/io/io.cpp index df38760199..1f55d484ad 100644 --- a/src/drt/src/io/io.cpp +++ b/src/drt/src/io/io.cpp @@ -457,9 +457,7 @@ void io::Parser::createNDR(odb::dbTechNonDefaultRule* ndr) == odb::dbTechLayerType::CUT) { continue; } - if (via->getViaLayerRule(i)->getLayer()->getNumber() / 2 < z) { - z = via->getViaLayerRule(i)->getLayer()->getNumber() / 2; - } + z = std::min(via->getViaLayerRule(i)->getLayer()->getNumber() / 2, z); } fnd->addViaRule(getTech()->getViaRule(via->getName()), z); } diff --git a/src/drt/src/pa/FlexPA.h b/src/drt/src/pa/FlexPA.h index 605256f816..7464d7137d 100644 --- a/src/drt/src/pa/FlexPA.h +++ b/src/drt/src/pa/FlexPA.h @@ -372,7 +372,8 @@ class FlexPA std::map& y_coords, frAccessPointEnum lower_type, frAccessPointEnum upper_type, - bool is_macro_cell_pin); + bool is_macro_cell_pin, + bool is_bterm = false); /** * @brief Generates an OnGrid access coordinate (on or half track) @@ -420,7 +421,8 @@ class FlexPA void genAPEnclosedBoundary(std::map& coords, const gtl::rectangle_data& rect, frLayerNum layer_num, - bool is_curr_layer_horz); + bool is_curr_layer_horz, + bool is_bterm = false); /** * @brief Calls the other genAP functions according to the informed cost @@ -441,7 +443,8 @@ class FlexPA frLayerNum base_layer_num, frLayerNum layer_num, const gtl::rectangle_data& rect, - int offset = 0); + int offset = 0, + bool is_bterm = false); bool OnlyAllowOnGridAccess(frLayerNum layer_num, bool is_macro_cell_pin); diff --git a/src/drt/src/pa/FlexPA_acc_point.cpp b/src/drt/src/pa/FlexPA_acc_point.cpp index a8e00b4386..b58a953af6 100644 --- a/src/drt/src/pa/FlexPA_acc_point.cpp +++ b/src/drt/src/pa/FlexPA_acc_point.cpp @@ -122,7 +122,14 @@ void FlexPA::genViaEnclosedCoords(std::map& coords, const auto rect_width = gtl::delta(rect, gtl::HORIZONTAL); const auto rect_height = gtl::delta(rect, gtl::VERTICAL); frVia via(via_def); - const odb::Rect box = via.getLayer1BBox(); + odb::Rect box; + if (via_def->getLayer1Num() == layer_num) { + box = via.getLayer1BBox(); + } else if (via_def->getLayer2Num() == layer_num) { + box = via.getLayer2BBox(); + } else { + return; + } const auto via_width = box.dx(); const auto via_height = box.dy(); if (via_width > rect_width || via_height > rect_height) { @@ -150,19 +157,39 @@ void FlexPA::genViaEnclosedCoords(std::map& coords, void FlexPA::genAPEnclosedBoundary(std::map& coords, const gtl::rectangle_data& rect, const frLayerNum layer_num, - const bool is_curr_layer_horz) + const bool is_curr_layer_horz, + const bool is_bterm) { - if (layer_num + 1 > getDesign()->getTech()->getTopLayerNum()) { - return; - } // hardcode first two single vias const int max_num_via_trial = 2; int cnt = 0; - for (auto& [tup, via] : layer_num_to_via_defs_[layer_num + 1][1]) { - genViaEnclosedCoords(coords, rect, via, layer_num, is_curr_layer_horz); - cnt++; - if (cnt >= max_num_via_trial) { - break; + + auto process_cut_layer = [&](int cut_layer_num, int& counter) { + if (layer_num_to_via_defs_.find(cut_layer_num) + == layer_num_to_via_defs_.end()) { + return; + } + for (auto& [tup, via] : layer_num_to_via_defs_[cut_layer_num][1]) { + genViaEnclosedCoords(coords, rect, via, layer_num, is_curr_layer_horz); + counter++; + if (counter >= max_num_via_trial) { + break; + } + } + }; + + if (layer_num + 1 <= getDesign()->getTech()->getTopLayerNum()) { + process_cut_layer(layer_num + 1, cnt); + } + + if (is_bterm) { + int down_via_cnt = 0; + const int bottom_layer = getDesign()->getTech()->getBottomLayerNum(); + for (int l = layer_num - 1; l >= layer_num - 3 && l >= bottom_layer; l--) { + process_cut_layer(l, down_via_cnt); + if (down_via_cnt >= max_num_via_trial) { + break; + } } } } @@ -174,7 +201,8 @@ void FlexPA::genAPCosted( const frLayerNum base_layer_num, const frLayerNum layer_num, const gtl::rectangle_data& rect, - const int offset) + const int offset, + const bool is_bterm) { auto layer = getDesign()->getTech()->getLayer(layer_num); const bool is_curr_layer_horz = layer->isHorizontal(); @@ -195,7 +223,8 @@ void FlexPA::genAPCosted( break; case (frAccessPointEnum::EncOpt): - genAPEnclosedBoundary(coords, rect, base_layer_num, is_curr_layer_horz); + genAPEnclosedBoundary( + coords, rect, base_layer_num, is_curr_layer_horz, is_bterm); break; case (frAccessPointEnum::NearbyGrid): @@ -234,9 +263,10 @@ void FlexPA::createSingleAccessPoint( } auto ap = std::make_unique(fpt, layer_num); - ap->setMultipleAccesses(frDirEnumPlanar, allow_planar); + bool local_allow_planar = allow_planar; + ap->setMultipleAccesses(frDirEnumPlanar, local_allow_planar); - if (allow_planar) { + if (local_allow_planar) { const auto lower_layer = getDesign()->getTech()->getLayer(layer_num); // rectonly forbid wrongway planar access // rightway on grid only forbid off track rightway planar access @@ -321,6 +351,27 @@ void FlexPA::createMultipleAccessPoints( auto layer = getDesign()->getTech()->getLayer(layer_num); bool allow_via = !isIOTerm(inst_term); bool allow_planar = true; + + if (layer->getLef58RectOnlyConstraint()) { + bool is_width_aligned = false; + const auto layer_width = layer->getWidth(); + if (layer->getDir() == dbTechLayerDir::HORIZONTAL) { + if (gtl::delta(rect, gtl::VERTICAL) == layer_width) { + is_width_aligned = true; + } + } else if (layer->getDir() == dbTechLayerDir::VERTICAL) { + if (gtl::delta(rect, gtl::HORIZONTAL) == layer_width) { + is_width_aligned = true; + } + } + + if (!is_width_aligned) { + allow_planar = false; + // Enable via access as fallback if planar is blocked + allow_via = true; + } + } + // only VIA_ACCESS_LAYERNUM layer can have via access if (isStdCellTerm(inst_term)) { if ((layer_num >= router_cfg_->VIAINPIN_BOTTOMLAYERNUM @@ -371,7 +422,8 @@ void FlexPA::genAPsFromRect(const gtl::rectangle_data& rect, std::map& y_coords, const frAccessPointEnum lower_type, const frAccessPointEnum upper_type, - const bool is_macro_cell_pin) + const bool is_macro_cell_pin, + const bool is_bterm) { if (OnlyAllowOnGridAccess(layer_num, is_macro_cell_pin) && upper_type != frAccessPointEnum::OnGrid) { @@ -436,7 +488,8 @@ void FlexPA::genAPsFromRect(const gtl::rectangle_data& rect, layer_num, second_layer_num, rect, - offset); + offset, + is_bterm); } } if (!use_center_line) { @@ -447,7 +500,9 @@ void FlexPA::genAPsFromRect(const gtl::rectangle_data& rect, layer1_track_coords, layer_num, layer_num, - rect); + rect, + 0, + is_bterm); } } } else { @@ -484,6 +539,7 @@ void FlexPA::genAPsFromLayerShapes( { // IO term is treated as the MacroCellPin as the top block bool is_macro_cell_pin = isMacroCellTerm(inst_term) || isIOTerm(inst_term); + bool is_bterm = (inst_term == nullptr); std::vector> maxrects; gtl::get_max_rectangles(maxrects, layer_shapes); @@ -497,7 +553,8 @@ void FlexPA::genAPsFromLayerShapes( y_coords, lower_type, upper_type, - is_macro_cell_pin); + is_macro_cell_pin, + is_bterm); layer_rect_to_coords[layer_num].push_back( {bbox_rect, {x_coords, y_coords}}); @@ -635,6 +692,7 @@ bool FlexPA::filterPlanarAccess( frInstTerm* inst_term) { const odb::Point begin_point = ap->getPoint(); + // skip viaonly access if (!ap->hasAccess(dir)) { return false; @@ -678,6 +736,7 @@ bool FlexPA::filterPlanarAccess( const bool no_drv = isPlanarViolationFree(ap, pin, ps.get(), inst_term, begin_point, layer); + ap->setAccess(dir, no_drv); return no_drv; @@ -886,14 +945,35 @@ void FlexPA::filterViaAccess( if (via_defs.empty()) { // no via map entry // hardcode first two single vias - for (auto& [tup, via_def] : layer_num_to_via_defs_[layer_num + 1][1]) { - if (inst_term && inst_term->isStubborn() - && avoid_via_defs_.contains(via_def)) { - continue; + // UP Vias + if (layer_num_to_via_defs_.find(layer_num + 1) + != layer_num_to_via_defs_.end()) { + for (auto& [tup, via_def] : layer_num_to_via_defs_[layer_num + 1][1]) { + if (inst_term && inst_term->isStubborn() + && avoid_via_defs_.contains(via_def)) { + continue; + } + via_defs.emplace_back(via_defs.size(), via_def); + if (via_defs.size() >= max_num_via_trial && !deep_search) { + break; + } } - via_defs.emplace_back(via_defs.size(), via_def); - if (via_defs.size() >= max_num_via_trial && !deep_search) { - break; + } + // DOWN Vias (Added) + if (!inst_term + || layer_num + 1 > getDesign()->getTech()->getTopLayerNum()) { + if (layer_num_to_via_defs_.find(layer_num - 1) + != layer_num_to_via_defs_.end()) { + for (auto& [tup, via_def] : layer_num_to_via_defs_[layer_num - 1][1]) { + if (inst_term && inst_term->isStubborn() + && avoid_via_defs_.contains(via_def)) { + continue; + } + via_defs.emplace_back(via_defs.size(), via_def); + if (via_defs.size() >= max_num_via_trial * 2 && !deep_search) { + break; + } + } } } } @@ -902,6 +982,7 @@ void FlexPA::filterViaAccess( for (auto& [idx, via_def] : via_defs) { auto via = std::make_unique(via_def, begin_point); const odb::Rect box = via->getLayer1BBox(); + if (inst_term && !deep_search) { odb::Rect boundary_bbox = inst_term->getInst()->getBoundaryBBox(); if (!boundary_bbox.contains(box)) { @@ -920,7 +1001,11 @@ void FlexPA::filterViaAccess( } if (checkViaPlanarAccess(ap, via.get(), pin, inst_term, layer_polys)) { ap->addViaDef(via_def); - ap->setAccess(frDirEnum::U); + if (via_def->getLayer1Num() == layer_num) { + ap->setAccess(frDirEnum::U); + } else { + ap->setAccess(frDirEnum::D); + } valid_via_count++; if (valid_via_count >= max_num_via_trial) { break; @@ -969,28 +1054,31 @@ bool FlexPA::checkDirectionalViaAccess( const std::vector>& layer_polys, frDirEnum dir) { - auto upper_layer = getTech()->getLayer(via->getViaDef()->getLayer2Num()); + frLayerNum target_layer_num; + if (via->getViaDef()->getLayer1Num() == ap->getLayerNum()) { + target_layer_num = via->getViaDef()->getLayer2Num(); + } else { + target_layer_num = via->getViaDef()->getLayer1Num(); + } + auto target_layer = getTech()->getLayer(target_layer_num); const bool vert_dir = (dir == frDirEnum::S || dir == frDirEnum::N); - const bool wrong_dir = (upper_layer->isHorizontal() && vert_dir) - || (upper_layer->isVertical() && !vert_dir); - auto style = upper_layer->getDefaultSegStyle(); + const bool wrong_dir = (target_layer->isHorizontal() && vert_dir) + || (target_layer->isVertical() && !vert_dir); + auto style = target_layer->getDefaultSegStyle(); if (wrong_dir) { - if (!router_cfg_->USENONPREFTRACKS || upper_layer->isUnidirectional()) { + if (!router_cfg_->USENONPREFTRACKS || target_layer->isUnidirectional()) { return false; } - style.setWidth(upper_layer->getWrongDirWidth()); + style.setWidth(target_layer->getWrongDirWidth()); } const odb::Point begin_point = ap->getPoint(); const bool is_block = inst_term && inst_term->getInst()->getMaster()->getMasterType().isBlock(); - const odb::Point end_point = genEndPoint(layer_polys, - begin_point, - via->getViaDef()->getLayer2Num(), - dir, - is_block); + const odb::Point end_point + = genEndPoint(layer_polys, begin_point, target_layer_num, dir, is_block); if (inst_term && inst_term->hasNet()) { via->addToNet(inst_term->getNet()); @@ -1006,7 +1094,7 @@ bool FlexPA::checkDirectionalViaAccess( ps->setPoints(begin_point, end_point); style.setBeginStyle(frcTruncateEndStyle, 0); } - ps->setLayerNum(upper_layer->getLayerNum()); + ps->setLayerNum(target_layer->getLayerNum()); ps->setStyle(style); if (inst_term && inst_term->hasNet()) { ps->addToNet(inst_term->getNet()); @@ -1073,7 +1161,7 @@ bool FlexPA::isViaViolationFree(frAccessPoint* ap, design_rule_checker.initPA1(); design_rule_checker.main(); - const bool no_drv = design_rule_checker.getMarkers().empty(); + bool no_drv = design_rule_checker.getMarkers().empty(); if (graphics_) { graphics_->setViaAP(ap, via, design_rule_checker.getMarkers()); @@ -1279,6 +1367,17 @@ bool FlexPA::genPinAccessCostBounded( if (is_std_cell_pin) { if (ap->getLayerNum() <= router_cfg_->VIA_ACCESS_LAYERNUM && !ap->hasAccess(frDirEnum::U)) { + if (inst_term) { + logger_->warn(DRT, + 323, + "Filtered AP due to no via access for std cell pin " + "{}/{} at ({}, {}) layer {}", + inst_term->getInst()->getName(), + inst_term->getTerm()->getName(), + ap->getPoint().x(), + ap->getPoint().y(), + ap->getLayerNum()); + } continue; } }