From a24b858dc890d51591d0a342ff61eccdb2a3b266 Mon Sep 17 00:00:00 2001 From: shuyulun01 <3190100230@zju.edu.cn> Date: Fri, 17 Apr 2026 23:21:41 +0800 Subject: [PATCH 1/5] support s110 and s55 --- src/database/data/design/db_layout/IdbLayer.h | 4 + .../manager/builder/lef_builder/lef_read.cpp | 3 + src/operation/iDRC/interface/DRCInterface.cpp | 58 +++-- .../ParallelRunLengthSpacingRule.hpp | 59 +++++ .../design_rule/SameLayerCutSpacingRule.hpp | 10 +- .../module/rule_validator/RuleValidator.cpp | 12 +- .../ParallelRunLengthSpacing.cpp | 205 +++++++++++------- .../rv_design_rule/SameLayerCutSpacing.cpp | 31 ++- 8 files changed, 278 insertions(+), 104 deletions(-) diff --git a/src/database/data/design/db_layout/IdbLayer.h b/src/database/data/design/db_layout/IdbLayer.h index 00239857a..7917b705f 100644 --- a/src/database/data/design/db_layout/IdbLayer.h +++ b/src/database/data/design/db_layout/IdbLayer.h @@ -556,9 +556,13 @@ class IdbLayerCutSpacing void set_adjacent_cuts(std::optional adj) { _adjacnet_cuts = adj; } [[nodiscard]] std::optional get_adjacent_cuts() const { return _adjacnet_cuts; } + void set_has_same_net(bool has_same_net) { _has_same_net = has_same_net; }; + [[nodiscard]] bool get_has_same_net() const { return _has_same_net; } + private: int32_t _spacing; std::optional _adjacnet_cuts; + bool _has_same_net; }; class IdbLayerCut : public IdbLayer diff --git a/src/database/manager/builder/lef_builder/lef_read.cpp b/src/database/manager/builder/lef_builder/lef_read.cpp index fb7365a05..4a516cefb 100644 --- a/src/database/manager/builder/lef_builder/lef_read.cpp +++ b/src/database/manager/builder/lef_builder/lef_read.cpp @@ -495,6 +495,7 @@ int LefRead::parse_layer_cut(lefiLayer* lef_layer, IdbLayerCut* layer_cut) double cut_within = lef_layer->spacingAdjacentWithin(i); spacing->set_adjacent_cuts(IdbLayerCutSpacing::AdjacentCuts(adj_cuts, transUnitDB(cut_within))); } + spacing->set_has_same_net(lef_layer->hasSpacingSamenet(i)); layer_cut->add_spacing(spacing); } @@ -670,6 +671,8 @@ int LefRead::parse_layer_routing(lefiLayer* lef_layer, IdbLayerRouting* layer_ro auto& spacing_notch = layer_routing->get_spacing_notchlength(); spacing_notch.set_notch_length(transUnitDB(lef_layer->spacingNotchLength(i))); spacing_notch.set_min_spacing(transUnitDB(lef_layer->spacing(i))); + // 如果有notchLength关键字,不能再算作Spacing规则 + continue; } spacing_list->add_spacing(layer_spacing); } diff --git a/src/operation/iDRC/interface/DRCInterface.cpp b/src/operation/iDRC/interface/DRCInterface.cpp index e82d3d7f7..74b9c918e 100644 --- a/src/operation/iDRC/interface/DRCInterface.cpp +++ b/src/operation/iDRC/interface/DRCInterface.cpp @@ -16,11 +16,15 @@ // *************************************************************************************** #include "DRCInterface.hpp" +#include #include "DataManager.hpp" #include "GDSPlotter.hpp" +#include "IdbEnum.h" #include "Monitor.hpp" +#include "ParallelRunLengthSpacingRule.hpp" #include "RuleValidator.hpp" +#include "SameLayerCutSpacingRule.hpp" #include "feature_manager.h" #include "idm.h" @@ -87,7 +91,7 @@ void DRCInterface::checkDef() } printSummary(type_violation_map); outputViolationJson(type_violation_map); - // outputViolationFile(type_violation_map); + outputViolationFile(type_violation_map); outputTofeature(type_violation_map); } @@ -601,15 +605,8 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa { ParallelRunLengthSpacingRule& parallel_run_length_spacing_rule = routing_layer.get_parallel_run_length_spacing_rule(); std::shared_ptr idb_spacing_table; - bool exist_spacing_table = false; if (idb_layer->get_spacing_table().get()->get_parallel().get() != nullptr && idb_layer->get_spacing_table().get()->is_parallel()) { idb_spacing_table = idb_layer->get_spacing_table()->get_parallel(); - exist_spacing_table = true; - } else if (idb_layer->get_spacing_list() != nullptr && !idb_layer->get_spacing_table().get()->is_parallel()) { - idb_spacing_table = idb_layer->get_spacing_table_from_spacing_list()->get_parallel(); - exist_spacing_table = true; - } - if (exist_spacing_table) { std::vector& width_list = parallel_run_length_spacing_rule.width_list; std::vector& parallel_length_list = parallel_run_length_spacing_rule.parallel_length_list; GridMap& width_parallel_length_map = parallel_run_length_spacing_rule.width_parallel_length_map; @@ -622,6 +619,28 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa width_parallel_length_map[x][y] = idb_spacing_table->get_spacing_table()[x][y]; } } + parallel_run_length_spacing_rule.has_spacing_table = true; + parallel_run_length_spacing_rule.print_spacing_table(); + exist_rule_set.insert(ViolationType::kParallelRunLengthSpacing); + } + + if (idb_layer->get_spacing_list() != nullptr) { + auto& spacing_list = parallel_run_length_spacing_rule.spacing_list; + for(auto& spacing_rule : idb_layer->get_spacing_list()->get_spacing_list()) { + LayerSpacingType spacing_type; + if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingDefault) { + spacing_type = LayerSpacingType::kSpacingDefault; + } else if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingRange) { + spacing_type = LayerSpacingType::kSpacingRange; + } else { + spacing_type = LayerSpacingType::kNone; + } + LayerSpacing spacing {spacing_type, spacing_rule->get_min_spacing(), spacing_rule->get_min_width(), spacing_rule->get_max_width()}; + spacing_list.push_back(spacing); + } + + parallel_run_length_spacing_rule.has_spacing_list = true; + parallel_run_length_spacing_rule.print_spacing_list(); exist_rule_set.insert(ViolationType::kParallelRunLengthSpacing); } } @@ -734,9 +753,17 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ { SameLayerCutSpacingRule& same_layer_cut_spacing_rule = cut_layer.get_same_layer_cut_spacing_rule(); if (!idb_layer->get_spacings().empty()) { - same_layer_cut_spacing_rule.curr_spacing = idb_layer->get_spacings().front()->get_spacing(); - same_layer_cut_spacing_rule.curr_prl = 0; - same_layer_cut_spacing_rule.curr_prl_spacing = idb_layer->get_spacings().front()->get_spacing(); + for (auto& cut_spacing : idb_layer->get_spacings()) { + SameLayerCutSpacing same_layer_cut_spacing; + same_layer_cut_spacing.curr_spacing = cut_spacing->get_spacing(); + same_layer_cut_spacing.curr_prl = -1; + same_layer_cut_spacing.curr_prl_spacing = -1; + same_layer_cut_spacing.has_same_net = cut_spacing->get_has_same_net(); + same_layer_cut_spacing_rule.spacings.push_back(same_layer_cut_spacing); + if (same_layer_cut_spacing.has_same_net) { + std::cout << "layer: " << cut_layer.get_layer_name() << " has sameNet\n"; + } + } exist_rule_set.insert(ViolationType::kSameLayerCutSpacing); } else if (!idb_layer->get_lef58_spacing_table().empty()) { idb::cutlayer::Lef58SpacingTable* spacing_table = nullptr; @@ -747,14 +774,13 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ spacing_table = spacing_table_ptr.get(); } if (spacing_table != nullptr) { + // NEXT 是否需要支持全部的规则,而不是第一条? idb::cutlayer::Lef58SpacingTable::CutSpacing cut_spacing = spacing_table->get_cutclass().get_cut_spacing(0, 0); int32_t curr_spacing = cut_spacing.get_cut_spacing1().value(); int32_t curr_prl = spacing_table->get_prl().value().get_prl(); int32_t curr_prl_spacing = cut_spacing.get_cut_spacing2().value(); - same_layer_cut_spacing_rule.curr_spacing = curr_spacing; - same_layer_cut_spacing_rule.curr_prl = curr_prl; - same_layer_cut_spacing_rule.curr_prl_spacing = curr_prl_spacing; + same_layer_cut_spacing_rule.spacings.push_back({curr_spacing, curr_prl, curr_prl_spacing, false}); exist_rule_set.insert(ViolationType::kSameLayerCutSpacing); } } @@ -862,6 +888,10 @@ std::vector DRCInterface::buildEnvShapeList() // instance obs for (idb::IdbLayerShape* obs_box : idb_instance->get_obs_box_list()) { for (idb::IdbRect* rect : obs_box->get_rect_list()) { + if (obs_box->get_layer() == nullptr) { + // DRCLOG.warn(Loc::current(), "The obs box layer is empty for instance ", idb_instance->get_name()); + continue; + } ids::Shape ids_shape; ids_shape.net_idx = -1; ids_shape.ll_x = rect->get_low_x(); diff --git a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp index 34113a3ae..5bb20d827 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp @@ -21,6 +21,23 @@ namespace idrc { +enum class LayerSpacingType : uint8_t +{ + kNone, + kSpacingDefault, + kSpacingRange, + //!-----tbd------------- + kSpacingRangeLenThreshold, + kMax +}; +struct LayerSpacing +{ + LayerSpacingType spacing_type; + int32_t min_spacing; + int32_t min_width; + int32_t max_width; +}; + class ParallelRunLengthSpacingRule { public: @@ -48,6 +65,48 @@ class ParallelRunLengthSpacingRule std::vector width_list; std::vector parallel_length_list; GridMap width_parallel_length_map; + bool has_spacing_table = false; + void print_spacing_table() { + std::cout << "#############spacing table###########\n"; + for (int32_t x = 0; x < width_parallel_length_map.get_x_size(); x++) { + for (int32_t y = 0; y < width_parallel_length_map.get_y_size(); y++) { + std::cout << width_parallel_length_map[x][y] << " "; + } + std::cout << "\n"; + } + } + + std::vector spacing_list; + bool has_spacing_list = false; + void print_spacing_list() { + std::cout << "#############spacing list###########\n"; + for (auto rule : spacing_list) { + std::cout << rule.min_spacing << " " << rule.min_width << " " < spacings; }; } // namespace idrc diff --git a/src/operation/iDRC/source/module/rule_validator/RuleValidator.cpp b/src/operation/iDRC/source/module/rule_validator/RuleValidator.cpp index 9d14b94ef..7d83271ae 100644 --- a/src/operation/iDRC/source/module/rule_validator/RuleValidator.cpp +++ b/src/operation/iDRC/source/module/rule_validator/RuleValidator.cpp @@ -19,7 +19,9 @@ #include "DRCHeader.hpp" #include "GDSPlotter.hpp" #include "Monitor.hpp" +#include "PlanarRect.hpp" #include "RVCluster.hpp" +#include "Utility.hpp" namespace idrc { @@ -545,7 +547,15 @@ void RuleValidator::prepareRVCluster(RVCluster& rv_cluster) } else { std::vector delta_overlap_list; delta_rect_rtree.query(bgi::intersects(gtl_rect), std::back_inserter(delta_overlap_list)); - max_rect_data.isEnv = delta_overlap_list.empty(); + max_rect_data.isEnv = true; + for (auto& delta_rect : delta_overlap_list) { + PlanarRect delta_planar_rect = DRCUTIL.convertToPlanarRect(delta_rect); + PlanarRect max_rect = DRCUTIL.convertToPlanarRect(max_rect_data.rect); + if (DRCUTIL.isOpenOverlap(delta_planar_rect, max_rect)) { + max_rect_data.isEnv = false; + break; + } + } } } is_polygon_env = is_polygon_env && max_rect_data.isEnv; diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp index ec787ecce..559081e15 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp @@ -27,122 +27,167 @@ void RuleValidator::verifyParallelRunLengthSpacing(RVCluster& rv_cluster) RoutingLayer& routing_layer = routing_layer_list[routing_layer_idx]; ParallelRunLengthSpacingRule& parallel_run_length_spacing_rule = routing_layer.get_parallel_run_length_spacing_rule(); std::map, std::map>> net_required_violation_rect_map; - std::vector> gtl_rect_id_pair_list; - std::vector violation_env_rect_list; + std::map, std::map>> env_net_required_violation_rect_map; for (auto& [net_idx, routing_net] : rv_layer_data.nets) { - if (net_idx == -1) { - continue; - } for (const MaxRectData& max_rect_data : rv_layer_data.getMaxRects(routing_net)) { PlanarRect rect = DRCUTIL.convertToPlanarRect(max_rect_data.rect); - if (max_rect_data.isEnv) { + if (net_idx == -1) { continue; } + bool has_spacing_table = parallel_run_length_spacing_rule.has_spacing_table; + bool has_spacing_list = parallel_run_length_spacing_rule.has_spacing_list; - gtl_rect_id_pair_list.clear(); - violation_env_rect_list.clear(); + std::vector> neighbor_rect_id_list; { - int32_t width_max_spacing = parallel_run_length_spacing_rule.getSpacing(rect.getWidth(), rect.getLength()); - PlanarRect check_rect = DRCUTIL.getEnlargedRect(rect, width_max_spacing); - rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(gtl_rect_id_pair_list)); - for (const auto& [gtl_rect, max_rect_id] : gtl_rect_id_pair_list) { - (void) max_rect_id; - violation_env_rect_list.push_back(DRCUTIL.convertToPlanarRect(gtl_rect)); - } + int32_t spacing_table_check = has_spacing_table ? parallel_run_length_spacing_rule.getMaxSpacing() : 0; + int32_t spacing_list_check = has_spacing_list ? parallel_run_length_spacing_rule.getSpacingMaxWidth() : 0; + int32_t check_spacing = std::max(spacing_table_check, spacing_list_check); + + PlanarRect check_rect = DRCUTIL.getEnlargedRect(rect, check_spacing); + rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(neighbor_rect_id_list)); } - for (const auto& [env_gtl_rect, env_max_rect_id] : gtl_rect_id_pair_list) { + + for (const auto& [gtl_rect, env_max_rect_id] : neighbor_rect_id_list) { + PlanarRect env_rect = DRCUTIL.convertToPlanarRect(gtl_rect); int32_t env_net_idx = rv_layer_data.getNetIdxByMaxRectId(env_max_rect_id); - PlanarRect env_rect = DRCUTIL.convertToPlanarRect(env_gtl_rect); if (DRCUTIL.isClosedOverlap(rect, env_rect)) { continue; } - // prl with overlaped shapes - int32_t prl = DRCUTIL.getParallelLength(rect, env_rect); - int32_t required_size = parallel_run_length_spacing_rule.getSpacing(std::max(rect.getWidth(), env_rect.getWidth()), prl); - int32_t spacing = DRCUTIL.getEuclideanDistance(env_rect, rect); - if (required_size <= spacing) { - continue; - } PlanarRect violation_rect = DRCUTIL.getSpacingRect(rect, env_rect); + bool is_prl_violation = false, is_spacing_violation = false; + int32_t real_prl_spacing = 0, real_spacing = 0; + // prl rules + if (has_spacing_table) { + int32_t prl = DRCUTIL.getParallelLength(rect, env_rect); + real_prl_spacing = parallel_run_length_spacing_rule.getSpacing(std::max(rect.getWidth(), env_rect.getWidth()), prl); + is_prl_violation = DRCUTIL.getEuclideanDistance(rect, env_rect) < real_prl_spacing; + } + + // spacing rules + if (has_spacing_list) { + real_spacing = parallel_run_length_spacing_rule.getSpacingWithWidth(std::max(rect.getWidth(), env_rect.getWidth())); + is_spacing_violation = DRCUTIL.getEuclideanDistance(rect, env_rect) < real_spacing; + } + + if (!is_prl_violation && !is_spacing_violation) { + continue; + } - if (prl > 0 || (prl < 0 && env_net_idx == net_idx)) { - GTLPolySetInt vioaltion_around_set; - for (const auto& [around_gtl_rect, around_max_rect_id] : gtl_rect_id_pair_list) { - (void) around_max_rect_id; - PlanarRect violation_env_rect = DRCUTIL.convertToPlanarRect(around_gtl_rect); - if (DRCUTIL.isOpenOverlap(violation_rect, violation_env_rect)) { - vioaltion_around_set += DRCUTIL.convertToGTLRectInt(violation_env_rect); + // sameNet + if (net_idx == env_net_idx) { + std::set orient_inside; + bool total_inside = false; + // for violation area = 0 + bool zero_area_inside = false; + GTLPolySetInt violation_ps; + violation_ps += DRCUTIL.convertToGTLRectInt(violation_rect); + for (const auto& [gtl_rect, max_rect_id] : neighbor_rect_id_list) { + PlanarRect violation_env_rect = DRCUTIL.convertToPlanarRect(gtl_rect); + int32_t violation_env_net_idx = rv_layer_data.getNetIdxByMaxRectId(max_rect_id); + if (violation_env_net_idx == net_idx) { + if (DRCUTIL.isOpenOverlap(violation_env_rect, violation_rect)) { + violation_ps -= gtl_rect; + } + if (gtl::empty(violation_ps)) { + total_inside = true; + } + if (DRCUTIL.isInside(violation_env_rect, violation_rect)) { + zero_area_inside = true; + } + + for (auto orient : {Orientation::kEast, Orientation::kWest, Orientation::kNorth, Orientation::kSouth}) { + if (!DRCUTIL.exist(orient_inside, orient) && DRCUTIL.isInside(violation_env_rect, violation_rect.getOrientEdge(orient))) { + orient_inside.insert(orient); + } + } } } - if (!gtl::empty(vioaltion_around_set)) { - GTLRectInt min_violation; - gtl::extents(min_violation, DRCUTIL.convertToGTLRectInt(violation_rect) - vioaltion_around_set); - violation_rect = DRCUTIL.convertToPlanarRect(min_violation); - } + bool hor = DRCUTIL.exist(orient_inside, Orientation::kWest) && DRCUTIL.exist(orient_inside, Orientation::kEast); + bool ver = DRCUTIL.exist(orient_inside, Orientation::kNorth) && DRCUTIL.exist(orient_inside, Orientation::kSouth); + if (violation_rect.getArea() == 0) { + if (zero_area_inside) { + continue; + } + } else if ((orient_inside.size() != 0 && !hor && !ver) || total_inside) { continue; + } else { + GTLRectInt violation_bbox; + violation_ps.extents(violation_bbox); + violation_rect = DRCUTIL.convertToPlanarRect(violation_bbox); } } - // exact prl - if (prl > 0) { - prl = DRCUTIL.getParallelLength(violation_rect, rect); - required_size = parallel_run_length_spacing_rule.getSpacing(std::max(rect.getWidth(), env_rect.getWidth()), prl); - if (required_size <= spacing) { - continue; + // diffNet + if (net_idx != env_net_idx && DRCUTIL.getParallelLength(rect, env_rect) > 0) { + bool total_inside = false; + GTLPolySetInt violation_ps; + violation_ps += DRCUTIL.convertToGTLRectInt(violation_rect); + for (const auto& [gtl_rect, max_rect_id] : neighbor_rect_id_list) { + PlanarRect violation_env_rect = DRCUTIL.convertToPlanarRect(gtl_rect); + if (DRCUTIL.isOpenOverlap(violation_env_rect, violation_rect)) { + violation_ps -= gtl_rect; + } + } + if (gtl::empty(violation_ps)) { + total_inside = true; + } + GTLRectInt violation_bbox; + violation_ps.extents(violation_bbox); + PlanarRect new_violation_rect = DRCUTIL.convertToPlanarRect(violation_bbox); + if (!DRCUTIL.isClosedOverlap(new_violation_rect, rect) || !DRCUTIL.isClosedOverlap(new_violation_rect, env_rect)) { + total_inside = true; } - } - bool is_zero_area = (violation_rect.getArea() == 0); - bool is_horizontal_inside = false, is_vertical_inside = false; - bool valid_violation = true; - if (DRCUTIL.isInside(rect, violation_rect)) { - continue; + if (total_inside) { + continue; + } } - for (PlanarRect& violation_env_rect : violation_env_rect_list) { - if (!DRCUTIL.isClosedOverlap(violation_env_rect, violation_rect)) { - continue; + if (max_rect_data.isEnv && rv_layer_data.getMaxRect(env_max_rect_id).isEnv) { + if (is_prl_violation) { + env_net_required_violation_rect_map[{net_idx, env_net_idx}][real_prl_spacing].push_back(violation_rect); } - if (violation_env_rect == env_rect || violation_env_rect == rect) { - continue; + if (is_spacing_violation) { + env_net_required_violation_rect_map[{net_idx, env_net_idx}][real_spacing].push_back(violation_rect); } - - if (is_zero_area) { - if (DRCUTIL.isInside(violation_env_rect, violation_rect) && DRCUTIL.isInside(violation_env_rect, violation_rect.getMidPoint(), false)) { - valid_violation = false; - break; - } - if (net_idx == env_net_idx && (DRCUTIL.isInside(violation_env_rect, violation_rect))) { - valid_violation = false; - break; - } - } else if (prl < 0 && env_net_idx == net_idx) { - if (!is_horizontal_inside - && (DRCUTIL.isInside(violation_env_rect, DRCUTIL.getRect(violation_rect.getOrientEdge(Orientation::kWest))) - || DRCUTIL.isInside(violation_env_rect, DRCUTIL.getRect(violation_rect.getOrientEdge(Orientation::kEast))))) { - is_horizontal_inside = true; - } - if (!is_vertical_inside - && (DRCUTIL.isInside(violation_env_rect, DRCUTIL.getRect(violation_rect.getOrientEdge(Orientation::kSouth))) - || DRCUTIL.isInside(violation_env_rect, DRCUTIL.getRect(violation_rect.getOrientEdge(Orientation::kNorth))))) { - is_vertical_inside = true; - } + } else { + if (is_prl_violation) { + net_required_violation_rect_map[{net_idx, env_net_idx}][real_prl_spacing].push_back(violation_rect); + } + if (is_spacing_violation) { + net_required_violation_rect_map[{net_idx, env_net_idx}][real_spacing].push_back(violation_rect); } } - if (!valid_violation) { - continue; + + } + + } + } + + std::map, std::map>> exclude_env; + for (auto& [violation_net_set, required_violation_rect_map] : net_required_violation_rect_map) { + for (auto& [required_size, violation_rect_list] : required_violation_rect_map) { + for (PlanarRect& violation_rect : violation_rect_list) { + auto& env_violations = env_net_required_violation_rect_map[violation_net_set][required_size]; + bool is_env_inside = false; + for (auto& env_violation : env_violations) { + bool closed_inside = (violation_rect.getXSpan() == env_violation.getXSpan()) || (violation_rect.getYSpan() == env_violation.getYSpan()); + if (DRCUTIL.isInside(env_violation, violation_rect) && closed_inside) { + is_env_inside = true; + break; + } } - if (!is_zero_area && is_horizontal_inside && is_vertical_inside) { + if (is_env_inside) { continue; } - net_required_violation_rect_map[{net_idx, env_net_idx}][required_size].push_back(violation_rect); + exclude_env[violation_net_set][required_size].push_back(violation_rect); } } } - std::map rect_computed; - for (auto& [violation_net_set, required_violation_rect_map] : net_required_violation_rect_map) { + + for (auto& [violation_net_set, required_violation_rect_map] : exclude_env) { for (auto& [required_size, violation_rect_list] : required_violation_rect_map) { for (PlanarRect& violation_rect : violation_rect_list) { bool is_inside = false; diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp index ef6453c4e..29175c1bf 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp @@ -14,6 +14,7 @@ // // See the Mulan PSL v2 for more details. // *************************************************************************************** +#include "PlanarRect.hpp" #include "RuleValidator.hpp" namespace idrc { @@ -36,9 +37,21 @@ void RuleValidator::verifySameLayerCutSpacing(RVCluster& rv_cluster) } CutLayer& cut_layer = cut_layer_list[cut_layer_idx]; SameLayerCutSpacingRule& same_layer_cut_spacing_rule = cut_layer.get_same_layer_cut_spacing_rule(); - int32_t curr_spacing = same_layer_cut_spacing_rule.curr_spacing; - int32_t curr_prl_spacing = same_layer_cut_spacing_rule.curr_prl_spacing; - int32_t curr_prl = -1 * same_layer_cut_spacing_rule.curr_prl; + bool has_same_net = false; + int32_t curr_same_net_spacing = -1; + int32_t curr_spacing = -1; + int32_t curr_prl_spacing = -1; + int32_t curr_prl = -1; + for (auto& spacing_rule : same_layer_cut_spacing_rule.spacings) { + if (spacing_rule.has_same_net) { + has_same_net = true; + curr_same_net_spacing = spacing_rule.curr_spacing; + } else { + curr_spacing = spacing_rule.curr_spacing; + } + curr_prl = -1 * spacing_rule.curr_prl; + curr_prl_spacing =spacing_rule.curr_prl_spacing; + } for (const CutData& cut_data : cut_layer_data.getCuts()) { GTLRectInt cut_gtl_rect = cut_data.rect; @@ -56,14 +69,20 @@ void RuleValidator::verifySameLayerCutSpacing(RVCluster& rv_cluster) } for (const CutData& overlap_cut_data : overlap_cut_list) { int32_t env_net_idx = overlap_cut_data.net_idx; + int32_t net_spacing = curr_spacing; PlanarRect env_rect = DRCUTIL.convertToPlanarRect(overlap_cut_data.rect); + PlanarRect violation_rect = DRCUTIL.getSpacingRect(cut_rect, env_rect); + if ((env_net_idx == net_idx) && has_same_net) { + net_spacing = curr_same_net_spacing; + } // ignore cutShort if (DRCUTIL.isClosedOverlap(cut_rect, env_rect)) { continue; } bool use_prl_spacing = false, use_spaing = false; use_prl_spacing = DRCUTIL.isOpenOverlap(checking_region_horizontal, env_rect) || DRCUTIL.isOpenOverlap(checking_region_vertical, env_rect); - use_spaing = DRCUTIL.getEuclideanDistance(cut_rect, env_rect) < curr_spacing; + use_prl_spacing &= (curr_prl_spacing != -1); + use_spaing = DRCUTIL.getEuclideanDistance(cut_rect, env_rect) < net_spacing; if (!use_prl_spacing && !use_spaing) { continue; } @@ -72,8 +91,8 @@ void RuleValidator::verifySameLayerCutSpacing(RVCluster& rv_cluster) violation.set_is_routing(true); violation.set_violation_net_set({net_idx, env_net_idx}); violation.set_layer_idx(routing_layer_idx); - violation.set_rect(DRCUTIL.getSpacingRect(cut_rect, env_rect)); - violation.set_required_size(use_prl_spacing ? curr_prl_spacing : curr_spacing); + violation.set_rect(violation_rect); + violation.set_required_size(use_prl_spacing ? curr_prl_spacing : net_spacing); layer_violations.push_back(std::move(violation)); } } From 9c3b4f64157b0a5e24314e037be9a84de67e2697 Mon Sep 17 00:00:00 2001 From: shuyulun01 <3190100230@zju.edu.cn> Date: Mon, 20 Apr 2026 19:08:24 +0800 Subject: [PATCH 2/5] iDRC: routing layer Spacing EndOfLine support --- src/database/data/design/IdbEnum.h | 1 + src/database/data/design/db_layout/IdbLayer.h | 20 ++++++++++++++++ .../design/db_layout/IdbLayer_routing.cpp | 6 +++++ .../manager/builder/lef_builder/lef_read.cpp | 11 +++++++++ src/operation/iDRC/interface/DRCInterface.cpp | 23 +++++++++++++++++++ .../ParallelRunLengthSpacingRule.hpp | 1 + .../rv_design_rule/EndOfLineSpacing.cpp | 2 +- 7 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/database/data/design/IdbEnum.h b/src/database/data/design/IdbEnum.h index 3d3746112..0e252c79c 100644 --- a/src/database/data/design/IdbEnum.h +++ b/src/database/data/design/IdbEnum.h @@ -388,6 +388,7 @@ enum class IdbLayerSpacingType : uint8_t kSpacingDefault, kSpacingRange, kSpacingRangeLenThreshold, + kSpacingEndOfLine, //!-----tbd------------- kMax }; diff --git a/src/database/data/design/db_layout/IdbLayer.h b/src/database/data/design/db_layout/IdbLayer.h index 7917b705f..9e61fc61c 100644 --- a/src/database/data/design/db_layout/IdbLayer.h +++ b/src/database/data/design/db_layout/IdbLayer.h @@ -110,12 +110,24 @@ class IdbLayerSpacing const int32_t get_min_spacing() const { return _min_spacing; } const int32_t get_min_width() const { return _min_width; } const int32_t get_max_width() const { return _max_width; } + const int32_t get_eol_width() const { return _eol_width; } + const int32_t get_eol_within() const { return _eol_within; } + const bool get_has_parallel_edge() const { return _has_parallel_edge; } + const int32_t get_par_space() const { return _par_space; } + const int32_t get_par_within() const { return _par_within; } + const bool get_has_two_edges() const { return _has_two_edges; } // setter void set_spacing_type(IdbLayerSpacingType spacing_type) { _spacing_type = spacing_type; } void set_min_spacing(int32_t min_spacing) { _min_spacing = min_spacing; } void set_min_width(int32_t min_width) { _min_width = min_width; } void set_max_width(int32_t max_width) { _max_width = max_width; } + void set_eol_width(int32_t eol_width) { _eol_width = eol_width; } + void set_eol_within(int32_t eol_within) { _eol_within = eol_within; } + void set_has_parallel_edge(bool has_parallel_edge) { _has_parallel_edge = has_parallel_edge; } + void set_par_space(int32_t par_space) { _par_space = par_space; } + void set_par_within(int32_t par_within) { _par_within = par_within; } + void set_has_two_edges(bool has_two_edges) { _has_two_edges = has_two_edges; } // operator bool isDefault() { return _spacing_type == IdbLayerSpacingType::kSpacingDefault ? true : false; } @@ -126,6 +138,14 @@ class IdbLayerSpacing int32_t _min_spacing; int32_t _min_width; int32_t _max_width; + + // end of line + int32_t _eol_width; + int32_t _eol_within; + bool _has_parallel_edge; + int32_t _par_space; + int32_t _par_within; + bool _has_two_edges; }; class IdbLayerSpacingList diff --git a/src/database/data/design/db_layout/IdbLayer_routing.cpp b/src/database/data/design/db_layout/IdbLayer_routing.cpp index 9df2d52f0..509922512 100644 --- a/src/database/data/design/db_layout/IdbLayer_routing.cpp +++ b/src/database/data/design/db_layout/IdbLayer_routing.cpp @@ -72,6 +72,12 @@ IdbLayerSpacing::IdbLayerSpacing() _min_spacing = -1; _min_width = -1; _max_width = -1; + _eol_width = -1; + _eol_within = -1; + _has_parallel_edge = false; + _par_space = -1; + _par_within = -1; + _has_two_edges = false; } IdbLayerSpacing::~IdbLayerSpacing() { diff --git a/src/database/manager/builder/lef_builder/lef_read.cpp b/src/database/manager/builder/lef_builder/lef_read.cpp index 4a516cefb..fc6cf70d6 100644 --- a/src/database/manager/builder/lef_builder/lef_read.cpp +++ b/src/database/manager/builder/lef_builder/lef_read.cpp @@ -674,6 +674,17 @@ int LefRead::parse_layer_routing(lefiLayer* lef_layer, IdbLayerRouting* layer_ro // 如果有notchLength关键字,不能再算作Spacing规则 continue; } + if (lef_layer->hasSpacingEndOfLine(i)) { + layer_spacing->set_spacing_type(IdbLayerSpacingType::kSpacingEndOfLine); + layer_spacing->set_eol_width(transUnitDB(lef_layer->spacingEolWidth(i))); + layer_spacing->set_eol_within(transUnitDB(lef_layer->spacingEolWithin(i))); + layer_spacing->set_has_parallel_edge(lef_layer->hasSpacingParellelEdge(i)); + if (layer_spacing->get_has_parallel_edge()) { + layer_spacing->set_par_space(transUnitDB(lef_layer->spacingParSpace(i))); + layer_spacing->set_par_within(transUnitDB(lef_layer->spacingParWithin(i))); + layer_spacing->set_has_two_edges(lef_layer->hasSpacingTwoEdges(i)); + } + } spacing_list->add_spacing(layer_spacing); } } diff --git a/src/operation/iDRC/interface/DRCInterface.cpp b/src/operation/iDRC/interface/DRCInterface.cpp index 74b9c918e..3590f3fc0 100644 --- a/src/operation/iDRC/interface/DRCInterface.cpp +++ b/src/operation/iDRC/interface/DRCInterface.cpp @@ -498,6 +498,27 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa } exist_rule_set.insert(ViolationType::kEndOfLineSpacing); } + + if (idb_layer->get_spacing_list() != nullptr) { + for (auto& spacing_rule : idb_layer->get_spacing_list()->get_spacing_list()) { + EndOfLineSpacingRule end_of_line_spacing_rule; + if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingEndOfLine) { + end_of_line_spacing_rule.eol_spacing = spacing_rule->get_min_spacing(); + end_of_line_spacing_rule.eol_width = spacing_rule->get_eol_width(); + end_of_line_spacing_rule.eol_within = spacing_rule->get_eol_within(); + end_of_line_spacing_rule.has_par = spacing_rule->get_has_parallel_edge(); + end_of_line_spacing_rule.par_spacing = spacing_rule->get_par_space(); + end_of_line_spacing_rule.par_within = spacing_rule->get_par_within(); + end_of_line_spacing_rule.has_two_edges = spacing_rule->get_has_parallel_edge() && spacing_rule->get_has_two_edges(); + end_of_line_spacing_rule_list.push_back(end_of_line_spacing_rule); + exist_rule_set.insert(ViolationType::kEndOfLineSpacing); + } + } + std::cout << "############# end of line ###########\n"; + for (auto rule : end_of_line_spacing_rule_list) { + std::cout << rule.eol_spacing << " " << rule.has_ete << " " << rule.ete_spacing <<" " << rule.has_par << " " << rule.has_two_edges << "\n"; + } + } } // MaximumWidthRule { @@ -632,6 +653,8 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa spacing_type = LayerSpacingType::kSpacingDefault; } else if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingRange) { spacing_type = LayerSpacingType::kSpacingRange; + } else if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingEndOfLine) { + continue; } else { spacing_type = LayerSpacingType::kNone; } diff --git a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp index 5bb20d827..43abbecf5 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp @@ -28,6 +28,7 @@ enum class LayerSpacingType : uint8_t kSpacingRange, //!-----tbd------------- kSpacingRangeLenThreshold, + kSpacingEOL, kMax }; struct LayerSpacing diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/EndOfLineSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/EndOfLineSpacing.cpp index 5e25d0908..a1922b121 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/EndOfLineSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/EndOfLineSpacing.cpp @@ -523,7 +523,7 @@ void RuleValidator::verifyEndOfLineSpacing(RVCluster& rv_cluster) if (boundary_idx >= 0) { const BoundaryData& env_boundary = merged_layer_data.getBoundary(boundary_idx); if (boundary_idx >= 0 && boundary_idx < static_cast(is_eol_boundary.size()) && is_eol_boundary[boundary_idx]) { - if (env_boundary.edge_length < eol_rule.eol_width) { + if (env_boundary.edge_length < eol_rule.eol_width && eol_rule.has_ete) { is_ete = true; } } From 504d17ac572e7d9c60676e5bb350cbe61de869bb Mon Sep 17 00:00:00 2001 From: shuyulun01 <3190100230@zju.edu.cn> Date: Mon, 20 Apr 2026 22:07:57 +0800 Subject: [PATCH 3/5] iDRC: cut layer AdjacentCutSpacing support --- src/operation/iDRC/interface/DRCInterface.cpp | 24 ++- .../source/data_manager/advance/CutLayer.hpp | 3 + .../design_rule/AdjacentCutSpacingRule.hpp | 4 + .../rv_design_rule/AdjacentCutSpacing.cpp | 139 +++++++----------- 4 files changed, 79 insertions(+), 91 deletions(-) diff --git a/src/operation/iDRC/interface/DRCInterface.cpp b/src/operation/iDRC/interface/DRCInterface.cpp index 3590f3fc0..773f3eeea 100644 --- a/src/operation/iDRC/interface/DRCInterface.cpp +++ b/src/operation/iDRC/interface/DRCInterface.cpp @@ -18,6 +18,7 @@ #include "DRCInterface.hpp" #include +#include "AdjacentCutSpacingRule.hpp" #include "DataManager.hpp" #include "GDSPlotter.hpp" #include "IdbEnum.h" @@ -677,6 +678,23 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ { exist_rule_set.insert(ViolationType::kCutShort); } + // AdjacentCutSpacingRule + { + AdjacentCutSpacingRule& adj_cut_spacing_rule = cut_layer.get_adjacent_cut_rule(); + if (!idb_layer->get_spacings().empty()) { + for (auto& cut_spacing : idb_layer->get_spacings()) { + if (cut_spacing->get_adjacent_cuts().has_value()) { + adj_cut_spacing_rule.cut_spacing = cut_spacing->get_spacing(); + adj_cut_spacing_rule.adjacnet_cuts = cut_spacing->get_adjacent_cuts()->get_adjacent_cuts(); + adj_cut_spacing_rule.cut_within = cut_spacing->get_adjacent_cuts()->get_cut_within(); + exist_rule_set.insert(ViolationType::kAdjacentCutSpacing); + std::cout << " adj cut: " << adj_cut_spacing_rule.adjacnet_cuts << " " << adj_cut_spacing_rule.cut_within << "\n"; + // only one ADJACENTCUTS statement per cut layer + continue; + } + } + } + } // CutEOLSpacingRule { CutEOLSpacingRule& cut_eol_spacing_rule = cut_layer.get_cut_eol_spacing_rule(); @@ -777,15 +795,15 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ SameLayerCutSpacingRule& same_layer_cut_spacing_rule = cut_layer.get_same_layer_cut_spacing_rule(); if (!idb_layer->get_spacings().empty()) { for (auto& cut_spacing : idb_layer->get_spacings()) { + if (cut_spacing->get_adjacent_cuts().has_value()) { + continue; + } SameLayerCutSpacing same_layer_cut_spacing; same_layer_cut_spacing.curr_spacing = cut_spacing->get_spacing(); same_layer_cut_spacing.curr_prl = -1; same_layer_cut_spacing.curr_prl_spacing = -1; same_layer_cut_spacing.has_same_net = cut_spacing->get_has_same_net(); same_layer_cut_spacing_rule.spacings.push_back(same_layer_cut_spacing); - if (same_layer_cut_spacing.has_same_net) { - std::cout << "layer: " << cut_layer.get_layer_name() << " has sameNet\n"; - } } exist_rule_set.insert(ViolationType::kSameLayerCutSpacing); } else if (!idb_layer->get_lef58_spacing_table().empty()) { diff --git a/src/operation/iDRC/source/data_manager/advance/CutLayer.hpp b/src/operation/iDRC/source/data_manager/advance/CutLayer.hpp index 81579493e..dd390b5ae 100644 --- a/src/operation/iDRC/source/data_manager/advance/CutLayer.hpp +++ b/src/operation/iDRC/source/data_manager/advance/CutLayer.hpp @@ -16,6 +16,7 @@ // *************************************************************************************** #pragma once +#include "AdjacentCutSpacingRule.hpp" #include "CutEOLSpacingRule.hpp" #include "DRCHeader.hpp" #include "DifferentLayerCutSpacingRule.hpp" @@ -35,6 +36,7 @@ class CutLayer int32_t get_layer_idx() const { return _layer_idx; } int32_t get_layer_order() const { return _layer_order; } std::string& get_layer_name() { return _layer_name; } + AdjacentCutSpacingRule& get_adjacent_cut_rule() { return _adjacent_cut_rule; } CutEOLSpacingRule& get_cut_eol_spacing_rule() { return _cut_eol_spacing_rule; } DifferentLayerCutSpacingRule& get_different_layer_cut_spacing_rule() { return _different_layer_cut_spacing_rule; } std::vector& get_enclosure_edge_rule_list() { return _enclosure_edge_rule_list; } @@ -49,6 +51,7 @@ class CutLayer int32_t _layer_idx = -1; int32_t _layer_order = -1; std::string _layer_name; + AdjacentCutSpacingRule _adjacent_cut_rule; CutEOLSpacingRule _cut_eol_spacing_rule; DifferentLayerCutSpacingRule _different_layer_cut_spacing_rule; std::vector _enclosure_edge_rule_list; diff --git a/src/operation/iDRC/source/data_manager/design_rule/AdjacentCutSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/AdjacentCutSpacingRule.hpp index e50c60dee..3c1da825e 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/AdjacentCutSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/AdjacentCutSpacingRule.hpp @@ -25,6 +25,10 @@ class AdjacentCutSpacingRule public: AdjacentCutSpacingRule() = default; ~AdjacentCutSpacingRule() = default; + + int32_t cut_spacing; + int32_t adjacnet_cuts; + int32_t cut_within; }; } // namespace idrc diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp index 6c4ddd6e1..c39d19409 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp @@ -20,117 +20,80 @@ namespace idrc { void RuleValidator::verifyAdjacentCutSpacing(RVCluster& rv_cluster) { -#if 0 - /* - 规则: SPACING 0.155 ADJACENTCUTS 3 WITHIN 0.200 ; - */ - struct AdjacentCutSpacingRule // 这是cut spacing的子规则 - { - int32_t cut_spacing = -1; - int32_t adjacent_cuts = -1; - int32_t within = -1; - }; - std::map layer_adjacent_cut_spacing_rule; - for (int32_t i = 1; i <= 4; i++) { - AdjacentCutSpacingRule rule = {310, 3, 400}; - layer_adjacent_cut_spacing_rule[i] = rule; // via2-via5 - } std::vector& cut_layer_list = DRCDM.getDatabase().get_cut_layer_list(); std::map>& cut_to_adjacent_routing_map = DRCDM.getDatabase().get_cut_to_adjacent_routing_map(); + const auto& layer_data = rv_cluster.get_layer_data(); - std::map>> cut_net_rect_map; - std::map, bgi::quadratic<16>>> cut_bg_rtree_map; - for (DRCShape* drc_shape : rv_cluster.get_drc_env_shape_list()) { - if (drc_shape->get_is_routing()) { - continue; - } - cut_net_rect_map[drc_shape->get_layer_idx()][drc_shape->get_net_idx()].push_back(drc_shape->get_rect()); - cut_bg_rtree_map[drc_shape->get_layer_idx()].insert(std::make_pair(DRCUTIL.convertToBGRectInt(drc_shape->get_rect()), drc_shape->get_net_idx())); - } - for (DRCShape* drc_shape : rv_cluster.get_drc_result_shape_list()) { - if (drc_shape->get_is_routing()) { + for (const auto& [cut_layer_idx, cut_layer_data] : layer_data) { + if (cut_layer_data.cut_pool.empty()) { continue; } - cut_net_rect_map[drc_shape->get_layer_idx()][drc_shape->get_net_idx()].push_back(drc_shape->get_rect()); - cut_bg_rtree_map[drc_shape->get_layer_idx()].insert(std::make_pair(DRCUTIL.convertToBGRectInt(drc_shape->get_rect()), drc_shape->get_net_idx())); - } - for (auto& [cut_layer_idx, net_rect_map] : cut_net_rect_map) { + int32_t routing_layer_idx = -1; { std::vector& routing_layer_idx_list = cut_to_adjacent_routing_map[cut_layer_idx]; routing_layer_idx = *std::min_element(routing_layer_idx_list.begin(), routing_layer_idx_list.end()); } - if (!DRCUTIL.exist(layer_adjacent_cut_spacing_rule, cut_layer_idx)) { - continue; - } - AdjacentCutSpacingRule& curr_rule = layer_adjacent_cut_spacing_rule[cut_layer_idx]; - int32_t cut_spacing = curr_rule.cut_spacing; - int32_t adjacent_cuts = curr_rule.adjacent_cuts; - int32_t within = curr_rule.within; - for (auto& [net_idx, rect_list] : net_rect_map) { - for (PlanarRect& rect : rect_list) { - std::vector> bg_rect_net_pair_list; - { - PlanarRect check_rect = DRCUTIL.getEnlargedRect(rect, within); - cut_bg_rtree_map[cut_layer_idx].query(bgi::intersects(DRCUTIL.convertToBGRectInt(check_rect)), std::back_inserter(bg_rect_net_pair_list)); + CutLayer& cut_layer = cut_layer_list[cut_layer_idx]; + + AdjacentCutSpacingRule& adj_cut_rule = cut_layer.get_adjacent_cut_rule(); + for (const CutData& cut_data : cut_layer_data.getCuts()) { + GTLRectInt cut_gtl_rect = cut_data.rect; + PlanarRect cut_rect = DRCUTIL.convertToPlanarRect(cut_gtl_rect); + int32_t net_idx = cut_data.net_idx; + + std::vector neighbor_cut_list; + { + PlanarRect check_rect = DRCUTIL.getEnlargedRect(cut_rect, adj_cut_rule.cut_within); + cut_layer_data.queryCuts(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(neighbor_cut_list)); + } + + int32_t adjacent_cut_count = 0; + bool has_violation = false; + int32_t cur_remote_spacing = -1; + int32_t cur_remote_env_net = -1; + std::set> seen_neighboor_rects; + + for (const CutData& neighbor_cut_data : neighbor_cut_list) { + int32_t env_net_idx = neighbor_cut_data.net_idx; + PlanarRect env_rect = DRCUTIL.convertToPlanarRect(neighbor_cut_data.rect); + if (cut_rect == env_rect) { + continue; } - int32_t adjacent_cut_count = 0; - bool is_inside_spacing = false; - std::vector> env_cut_rect_list; - for (auto& [bg_env_rect, env_net_idx] : bg_rect_net_pair_list) { - PlanarRect env_rect = DRCUTIL.convertToPlanarRect(bg_env_rect); - if (env_rect == rect) { - continue; // 忽略自己 - } - if (DRCUTIL.getEuclideanDistance(rect, env_rect) >= within) { - continue; // 忽略不在within范围内的 - } - if (DRCUTIL.getEuclideanDistance(rect, env_rect) < cut_spacing) { - is_inside_spacing = true; // 在spacing范围内 + + int32_t distance = DRCUTIL.getEuclideanDistance(cut_rect, env_rect); + if (distance < adj_cut_rule.cut_within) { + auto nb_rect_key = std::make_tuple(env_rect.get_ll_x(), env_rect.get_ll_y(), env_rect.get_ur_x(), env_rect.get_ur_y()); + if (!seen_neighboor_rects.insert(nb_rect_key).second) { + continue; } - env_cut_rect_list.push_back(std::make_pair(env_net_idx, env_rect)); adjacent_cut_count++; + if (distance > cur_remote_spacing && env_net_idx != -1) { + cur_remote_spacing = distance; + cur_remote_env_net = env_net_idx; + } } - if (adjacent_cut_count < adjacent_cuts) { - continue; // 忽略不满足adjacent_cuts的 - } - if (is_inside_spacing == false) { - continue; + if (distance < adj_cut_rule.cut_spacing) { + has_violation = true; } - sort(env_cut_rect_list.begin(), env_cut_rect_list.end(), [&](const std::pair& a, const std::pair& b) { - SortStatus sort_status = SortStatus::kEqual; - double a_dis = DRCUTIL.getEuclideanDistance(rect, a.second); - double b_dis = DRCUTIL.getEuclideanDistance(rect, b.second); - // EuclideanDistance大的优先 - if (sort_status == SortStatus::kEqual) { - if (a_dis > b_dis) { - sort_status = SortStatus::kTrue; - } else if (a_dis < b_dis) { - sort_status = SortStatus::kFalse; - } else { - sort_status = SortStatus::kEqual; - } - } - if (sort_status == SortStatus::kTrue) { - return true; - } else if (sort_status == SortStatus::kFalse) { - return false; - } - return false; - }); - int32_t env_idx = env_cut_rect_list.front().first; + } + if (net_idx == -1 && cur_remote_env_net == -1) { + continue; + } + if (has_violation && (adjacent_cut_count >= adj_cut_rule.adjacnet_cuts)) { Violation violation; violation.set_violation_type(ViolationType::kAdjacentCutSpacing); violation.set_is_routing(true); - violation.set_violation_net_set({net_idx, env_idx}); + violation.set_violation_net_set({net_idx, cur_remote_env_net}); violation.set_layer_idx(routing_layer_idx); - violation.set_rect(rect); - violation.set_required_size(cut_spacing); + violation.set_rect(cut_rect); + violation.set_required_size(adj_cut_rule.cut_spacing); rv_cluster.get_violation_list().push_back(violation); } + } + } -#endif } } // namespace idrc From 8ed814d13d690f0486e727b46f86c7c1d8c46e19 Mon Sep 17 00:00:00 2001 From: shuyulun01 <3190100230@zju.edu.cn> Date: Wed, 22 Apr 2026 01:30:12 +0800 Subject: [PATCH 4/5] iDRC: routing layer ispd19 dataset CornerSpacing rule support --- src/database/data/design/db_layout/IdbLayer.h | 6 + .../IdbRoutingLayerLef58Property.h | 45 ++ .../lef58_property/routinglayer_property.h | 25 +- .../routinglayer_property_parser.h | 24 +- .../lef58_property/test/test_routinglayer.cc | 37 + .../property_parser/routinglayer_parser.cpp | 33 +- .../property_parser/routinglayer_parser.h | 1 + src/operation/iDRC/interface/DRCInterface.cpp | 30 +- .../data_manager/advance/RoutingLayer.hpp | 3 + .../design_rule/CornerSpacingRule.hpp | 44 ++ .../ParallelRunLengthSpacingRule.hpp | 15 - .../rv_design_rule/CornerSpacing.cpp | 659 +++++++++++++----- .../iDRC/source/toolkit/utility/Utility.hpp | 64 +- 13 files changed, 769 insertions(+), 217 deletions(-) create mode 100644 src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp diff --git a/src/database/data/design/db_layout/IdbLayer.h b/src/database/data/design/db_layout/IdbLayer.h index 9e61fc61c..ef6e84713 100644 --- a/src/database/data/design/db_layout/IdbLayer.h +++ b/src/database/data/design/db_layout/IdbLayer.h @@ -363,6 +363,7 @@ class IdbLayerRouting : public IdbLayer std::vector>& get_lef58_spacing_eol_list() { return _lef58_spacing_eol_list; }; std::vector>& get_lef58_area() { return _lef58_area; } std::shared_ptr get_lef58_corner_fill_spacing() { return _lef58_corner_fill_spacing; } + std::vector>& get_lef58_corner_spacing_list() { return _lef58_corner_spacing_list; } std::vector>& get_lef58_minimum_cut() { return _lef58_minimum_cut; } std::vector>& get_lef58_min_step() { return _lef58_min_steps; } std::shared_ptr get_lef58_spacing_notchlength() { return _lef58_spacing_notchlength; } @@ -412,6 +413,10 @@ class IdbLayerRouting : public IdbLayer { _lef58_corner_fill_spacing = std::move(cornerfill_spacing); } + void add_lef58_corner_spacing(std::shared_ptr corner_spacing) + { + _lef58_corner_spacing_list.emplace_back(std::move(corner_spacing)); + } void add_lef58_minimum_cut(std::shared_ptr minimum_cut) { _lef58_minimum_cut.push_back(std::move(minimum_cut)); @@ -463,6 +468,7 @@ class IdbLayerRouting : public IdbLayer std::vector> _lef58_spacing_eol_list; std::vector> _lef58_area; std::shared_ptr _lef58_corner_fill_spacing; + std::vector> _lef58_corner_spacing_list; std::vector> _lef58_minimum_cut; std::vector> _lef58_min_steps; std::shared_ptr _lef58_spacing_notchlength; diff --git a/src/database/data/design/db_property/IdbRoutingLayerLef58Property.h b/src/database/data/design/db_property/IdbRoutingLayerLef58Property.h index 1ad9496e3..35868043d 100644 --- a/src/database/data/design/db_property/IdbRoutingLayerLef58Property.h +++ b/src/database/data/design/db_property/IdbRoutingLayerLef58Property.h @@ -101,6 +101,51 @@ class Lef58CornerFillSpacing int32_t _eol_width; }; +// LEF58_CORNERSPACING +class Lef58CornerSpacing +{ + public: + enum class CornerType + { + kNone, + kConvexCorner, + kConcaveCorner + }; + + class WidthSpacing + { + public: + WidthSpacing() = default; + WidthSpacing(int32_t width, int32_t spacing) : _width(width), _spacing(spacing) {} + + [[nodiscard]] int32_t get_width() const { return _width; } + [[nodiscard]] int32_t get_spacing() const { return _spacing; } + void set_width(int32_t width) { _width = width; } + void set_spacing(int32_t spacing) { _spacing = spacing; } + + private: + int32_t _width; + int32_t _spacing; + }; + + [[nodiscard]] CornerType get_corner_type() const { return _corner_type; } + [[nodiscard]] std::optional get_except_eol() const { return _except_eol; } + [[nodiscard]] const std::vector& get_width_spacing_list() const { return _width_spacing_list; } + + void set_corner_type(CornerType corner_type) { _corner_type = corner_type; } + void set_except_eol(int32_t except_eol) { _except_eol = except_eol; } + template + void add_width_spacing(Args&&... args) + { + _width_spacing_list.emplace_back(std::forward(args)...); + } + + private: + CornerType _corner_type = CornerType::kNone; + std::optional _except_eol; + std::vector _width_spacing_list; +}; + // LEF58_MINIMUMCUT class Lef58MinimumCut { diff --git a/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property.h b/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property.h index 2a07c489d..50201b80f 100644 --- a/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property.h +++ b/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property.h @@ -233,6 +233,25 @@ struct lef58_spacingtable_jogtojog std::vector _width; }; +////////////////////////////////// +// LEF58_CORNERSPACING // +////////////////////////////////// + +struct lef58_cornerspacing_width +{ + double _width; + double _spacing; +}; + +struct lef58_cornerspacing +{ + std::string _corner_type; + std::optional _except_eol; + std::vector _width_spacings; +}; + + + } // namespace idb::routinglayer_property BOOST_FUSION_ADAPT_STRUCT(idb::routinglayer_property::double_pair, (double, first)(double, second)) @@ -322,4 +341,8 @@ BOOST_FUSION_ADAPT_STRUCT(idb::routinglayer_property::lef58_spacingtable_jogtojo _width_short_jog_spacing)) BOOST_FUSION_ADAPT_STRUCT(idb::routinglayer_property::lef58_spacingtable_jogtojog, (double, _jog2jog_spacing)(double, _jog_width)(double, _short_jog_spacing)( - std::vector, _width)) \ No newline at end of file + std::vector, _width)) +BOOST_FUSION_ADAPT_STRUCT(idb::routinglayer_property::lef58_cornerspacing_width, (double, _width)(double, _spacing)) +BOOST_FUSION_ADAPT_STRUCT(idb::routinglayer_property::lef58_cornerspacing, + (std::string, _corner_type)(std::optional, _except_eol)( + std::vector, _width_spacings)) diff --git a/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property_parser.h b/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property_parser.h index cc38715a9..e3725f6e6 100644 --- a/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property_parser.h +++ b/src/database/manager/builder/lef_builder/property_parser/lef58_property/routinglayer_property_parser.h @@ -26,6 +26,9 @@ namespace idb::routinglayer_property { template bool parse_lef58_conerfillspacing(Iterator beg, Iterator end, lef58_cornerfillspacing& spacing); + template + bool parse_lef58_cornerspacing(Iterator beg, Iterator end, std::vector& spacings); + template bool parse_lef58_minimumcut(Iterator beg, Iterator end, std::vector& cuts); @@ -72,6 +75,25 @@ namespace idb::routinglayer_property { return true; } + template + bool parse_lef58_cornerspacing(Iterator beg, Iterator end, std::vector& spacings) { + const static qi::rule width_spacing_rule = + lit("WIDTH") >> double_ >> lit("SPACING") >> double_; + const static qi::rule corner_spacing_rule = + lit("CORNERSPACING") + >> (qi::string("CONVEXCORNER") | qi::string("CONCAVECORNER")) + >> -(lit("EXCEPTEOL") >> double_) + >> +width_spacing_rule + >> lit(";"); + + bool ok = qi::phrase_parse(beg, end, +corner_spacing_rule, space, spacings); + if (!ok || beg != end) { + std::cout << "Parse \"" << std::string(beg, end) << "\" failed" << std::endl; + return false; + } + return true; + } + template bool parse_lef58_minimumcut(Iterator beg, Iterator end, std::vector& cuts){ const static qi::rule value_string = lexeme[+(char_ - char_(" ;\n"))]; @@ -221,4 +243,4 @@ namespace idb::routinglayer_property { } return true; } -} // namespace idb::routinglayer_property \ No newline at end of file +} // namespace idb::routinglayer_property diff --git a/src/database/manager/builder/lef_builder/property_parser/lef58_property/test/test_routinglayer.cc b/src/database/manager/builder/lef_builder/property_parser/lef58_property/test/test_routinglayer.cc index 5e9ddbf3c..730808141 100644 --- a/src/database/manager/builder/lef_builder/property_parser/lef58_property/test/test_routinglayer.cc +++ b/src/database/manager/builder/lef_builder/property_parser/lef58_property/test/test_routinglayer.cc @@ -90,6 +90,43 @@ TEST(RoutingLayerTest, LEF58CORNERFILLSPACING) { EXPECT_EQ(spacing._eol_width, 0.06); } +TEST(RoutingLayerTest, LEF58CORNERSPACINGMultipleRules) { + std::vector spacings; + const std::string str = R"( + CORNERSPACING CONVEXCORNER EXCEPTEOL 0.08 + WIDTH 0.00 SPACING 0.10 + WIDTH 0.20 SPACING 0.20 + WIDTH 0.50 SPACING 0.30 ; + CORNERSPACING CONCAVECORNER + WIDTH 0.00 SPACING 0.12 + WIDTH 0.18 SPACING 0.22 ;)"; + + bool ok = parse_lef58_cornerspacing(str.begin(), str.end(), spacings); + EXPECT_TRUE(ok); + ASSERT_EQ(spacings.size(), 2); + + const auto& convex_spacing = spacings[0]; + EXPECT_EQ(convex_spacing._corner_type, "CONVEXCORNER"); + EXPECT_TRUE(convex_spacing._except_eol.has_value()); + EXPECT_EQ(convex_spacing._except_eol.value(), 0.08); + EXPECT_EQ(convex_spacing._width_spacings.size(), 3); + EXPECT_EQ(convex_spacing._width_spacings[0]._width, 0.00); + EXPECT_EQ(convex_spacing._width_spacings[0]._spacing, 0.10); + EXPECT_EQ(convex_spacing._width_spacings[1]._width, 0.20); + EXPECT_EQ(convex_spacing._width_spacings[1]._spacing, 0.20); + EXPECT_EQ(convex_spacing._width_spacings[2]._width, 0.50); + EXPECT_EQ(convex_spacing._width_spacings[2]._spacing, 0.30); + + const auto& concave_spacing = spacings[1]; + EXPECT_EQ(concave_spacing._corner_type, "CONCAVECORNER"); + EXPECT_FALSE(concave_spacing._except_eol.has_value()); + EXPECT_EQ(concave_spacing._width_spacings.size(), 2); + EXPECT_EQ(concave_spacing._width_spacings[0]._width, 0.00); + EXPECT_EQ(concave_spacing._width_spacings[0]._spacing, 0.12); + EXPECT_EQ(concave_spacing._width_spacings[1]._width, 0.18); + EXPECT_EQ(concave_spacing._width_spacings[1]._spacing, 0.22); +} + TEST(RoutingLayerTest, LEF58MINIMUNCUT) { std::vector cuts; const std::string str = R"( diff --git a/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.cpp b/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.cpp index 98a9dd359..7f6829d6d 100644 --- a/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.cpp +++ b/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.cpp @@ -32,6 +32,9 @@ bool RoutingLayerParser::parse(const std::string& name, const std::string& value if (name == "LEF58_CORNERFILLSPACING") { return parse_lef58_conerfillspacing(value, data); } + if (name == "LEF58_CORNERSPACING") { + return parse_lef58_cornerspacing(value, data); + } if (name == "LEF58_MINIMUMCUT") { return parse_lef58_minimuncut(value, data); } @@ -95,6 +98,34 @@ bool RoutingLayerParser::parse_lef58_conerfillspacing(const std::string& value, cornerfill_spacing->set_eol_width(transUnitDB(cornerspacing._eol_width)); return true; } +bool RoutingLayerParser::parse_lef58_cornerspacing(const std::string& value, IdbLayerRouting* data) +{ + std::vector cornerspacings; + bool parse_ok = routinglayer_property::parse_lef58_cornerspacing(value.begin(), value.end(), cornerspacings); + if (not parse_ok) { + return false; + } + + for (const auto& cornerspacing : cornerspacings) { + auto corner_spacing = std::make_shared(); + data->add_lef58_corner_spacing(corner_spacing); + + if (cornerspacing._corner_type == "CONVEXCORNER") { + corner_spacing->set_corner_type(routinglayer::Lef58CornerSpacing::CornerType::kConvexCorner); + } else if (cornerspacing._corner_type == "CONCAVECORNER") { + corner_spacing->set_corner_type(routinglayer::Lef58CornerSpacing::CornerType::kConcaveCorner); + } + + if (cornerspacing._except_eol.has_value()) { + corner_spacing->set_except_eol(transUnitDB(cornerspacing._except_eol.value())); + } + + for (const auto& width_spacing : cornerspacing._width_spacings) { + corner_spacing->add_width_spacing(transUnitDB(width_spacing._width), transUnitDB(width_spacing._spacing)); + } + } + return true; +} bool RoutingLayerParser::parse_lef58_minimuncut(const std::string& value, IdbLayerRouting* data) { std::vector minimuncuts; @@ -303,4 +334,4 @@ bool RoutingLayerParser::parse_lef58_spacingtable(const std::string& value, IdbL return false; } -} // namespace idb \ No newline at end of file +} // namespace idb diff --git a/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.h b/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.h index 892fa72ba..27d3dc0e9 100644 --- a/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.h +++ b/src/database/manager/builder/lef_builder/property_parser/routinglayer_parser.h @@ -29,6 +29,7 @@ class RoutingLayerParser : public PropertyBaseParser private: bool parse_lef58_area(const std::string& value, IdbLayerRouting* data); bool parse_lef58_conerfillspacing(const std::string& value, IdbLayerRouting* data); + bool parse_lef58_cornerspacing(const std::string& value, IdbLayerRouting* data); bool parse_lef58_minimuncut(const std::string& value, IdbLayerRouting* data); bool parse_lef58_minstep(const std::string& value, IdbLayerRouting* data); bool parse_lef58_spacing(const std::string& value, IdbLayerRouting* data); diff --git a/src/operation/iDRC/interface/DRCInterface.cpp b/src/operation/iDRC/interface/DRCInterface.cpp index 773f3eeea..d6ffe0b04 100644 --- a/src/operation/iDRC/interface/DRCInterface.cpp +++ b/src/operation/iDRC/interface/DRCInterface.cpp @@ -16,7 +16,6 @@ // *************************************************************************************** #include "DRCInterface.hpp" -#include #include "AdjacentCutSpacingRule.hpp" #include "DataManager.hpp" @@ -456,6 +455,28 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa exist_rule_set.insert(ViolationType::kCornerFillSpacing); } } + // CornerSpacingRule + { + std::vector& corner_spacing_rule_list = routing_layer.get_corner_spacing_rule_list(); + if (!idb_layer->get_lef58_corner_spacing_list().empty()) { + for (const std::shared_ptr& idb_corner_spacing : idb_layer->get_lef58_corner_spacing_list()) { + CornerSpacingRule corner_spacing_rule; + corner_spacing_rule.has_convex_corner + = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConvexCorner; + corner_spacing_rule.has_concave_corner + = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConcaveCorner; + corner_spacing_rule.has_except_eol = idb_corner_spacing->get_except_eol().has_value(); + if (idb_corner_spacing->get_except_eol().has_value()) { + corner_spacing_rule.except_eol = idb_corner_spacing->get_except_eol().value(); + } + for (const auto& width_spacing : idb_corner_spacing->get_width_spacing_list()) { + corner_spacing_rule.width_spacing_list.emplace_back(width_spacing.get_width(), width_spacing.get_spacing()); + } + corner_spacing_rule_list.push_back(std::move(corner_spacing_rule)); + } + exist_rule_set.insert(ViolationType::kCornerSpacing); + } + } // EndOfLineSpacingRule { std::vector& end_of_line_spacing_rule_list = routing_layer.get_end_of_line_spacing_rule_list(); @@ -515,10 +536,6 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa exist_rule_set.insert(ViolationType::kEndOfLineSpacing); } } - std::cout << "############# end of line ###########\n"; - for (auto rule : end_of_line_spacing_rule_list) { - std::cout << rule.eol_spacing << " " << rule.has_ete << " " << rule.ete_spacing <<" " << rule.has_par << " " << rule.has_two_edges << "\n"; - } } } // MaximumWidthRule @@ -642,7 +659,6 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa } } parallel_run_length_spacing_rule.has_spacing_table = true; - parallel_run_length_spacing_rule.print_spacing_table(); exist_rule_set.insert(ViolationType::kParallelRunLengthSpacing); } @@ -664,7 +680,6 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa } parallel_run_length_spacing_rule.has_spacing_list = true; - parallel_run_length_spacing_rule.print_spacing_list(); exist_rule_set.insert(ViolationType::kParallelRunLengthSpacing); } } @@ -688,7 +703,6 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ adj_cut_spacing_rule.adjacnet_cuts = cut_spacing->get_adjacent_cuts()->get_adjacent_cuts(); adj_cut_spacing_rule.cut_within = cut_spacing->get_adjacent_cuts()->get_cut_within(); exist_rule_set.insert(ViolationType::kAdjacentCutSpacing); - std::cout << " adj cut: " << adj_cut_spacing_rule.adjacnet_cuts << " " << adj_cut_spacing_rule.cut_within << "\n"; // only one ADJACENTCUTS statement per cut layer continue; } diff --git a/src/operation/iDRC/source/data_manager/advance/RoutingLayer.hpp b/src/operation/iDRC/source/data_manager/advance/RoutingLayer.hpp index 977af3242..7b749abba 100644 --- a/src/operation/iDRC/source/data_manager/advance/RoutingLayer.hpp +++ b/src/operation/iDRC/source/data_manager/advance/RoutingLayer.hpp @@ -17,6 +17,7 @@ #pragma once #include "CornerFillSpacingRule.hpp" +#include "CornerSpacingRule.hpp" #include "DRCHeader.hpp" #include "EndOfLineSpacingRule.hpp" #include "Logger.hpp" @@ -45,6 +46,7 @@ class RoutingLayer Direction& get_prefer_direction() { return _prefer_direction; } int32_t get_pitch() const { return _pitch; } CornerFillSpacingRule& get_corner_fill_spacing_rule() { return _corner_fill_spacing_rule; } + std::vector& get_corner_spacing_rule_list() { return _corner_spacing_rule_list; } std::vector& get_end_of_line_spacing_rule_list() { return _end_of_line_spacing_rule_list; } MaximumWidthRule& get_maximum_width_rule() { return _maximum_width_rule; } MinHoleRule& get_min_hole_rule() { return _min_hole_rule; } @@ -71,6 +73,7 @@ class RoutingLayer Direction _prefer_direction = Direction::kNone; int32_t _pitch = -1; CornerFillSpacingRule _corner_fill_spacing_rule; + std::vector _corner_spacing_rule_list; std::vector _end_of_line_spacing_rule_list; MaximumWidthRule _maximum_width_rule; MinHoleRule _min_hole_rule; diff --git a/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp new file mode 100644 index 000000000..9bf89a61e --- /dev/null +++ b/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp @@ -0,0 +1,44 @@ +// *************************************************************************************** +// Copyright (c) 2023-2025 Peng Cheng Laboratory +// Copyright (c) 2023-2025 Institute of Computing Technology, Chinese Academy of Sciences +// Copyright (c) 2023-2025 Beijing Institute of Open Source Chip +// +// iEDA is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// +// See the Mulan PSL v2 for more details. +// *************************************************************************************** +#pragma once + +#include "DRCHeader.hpp" + +namespace idrc { + +class CornerSpacingRule +{ + public: + CornerSpacingRule() = default; + ~CornerSpacingRule() = default; + int32_t get_width_spacing(int32_t width) { + for (int32_t i = width_spacing_list.size() - 1; i >= 0; i--) { + if (width > width_spacing_list[i].first) { + return width_spacing_list[i].second; + } + } + return width_spacing_list[0].second; + } + + bool has_convex_corner = false; + bool has_concave_corner = false; + bool has_except_eol = false; + int32_t except_eol = -1; + std::vector> width_spacing_list; +}; + +} // namespace idrc diff --git a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp index 43abbecf5..f316d5ec5 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp @@ -67,24 +67,9 @@ class ParallelRunLengthSpacingRule std::vector parallel_length_list; GridMap width_parallel_length_map; bool has_spacing_table = false; - void print_spacing_table() { - std::cout << "#############spacing table###########\n"; - for (int32_t x = 0; x < width_parallel_length_map.get_x_size(); x++) { - for (int32_t y = 0; y < width_parallel_length_map.get_y_size(); y++) { - std::cout << width_parallel_length_map[x][y] << " "; - } - std::cout << "\n"; - } - } std::vector spacing_list; bool has_spacing_list = false; - void print_spacing_list() { - std::cout << "#############spacing list###########\n"; - for (auto rule : spacing_list) { - std::cout << rule.min_spacing << " " << rule.min_width << " " <> width_spacing_list; - }; - std::map layer_corner_spacing_rule; // M2-M7 - for (int32_t i = 1; i <= 6; i++) { - CornerSpacingRule rule = {true, true, 160, {{0, 200}, {400, 400}, {1000, 600}}}; - layer_corner_spacing_rule[i] = rule; // M2-M7 - } -/////////// -#if 1 // 数据结构定义 - struct PolyInfo - { - int32_t coord_size = -1; - std::vector coord_list; - std::vector convex_corner_list; - std::vector> edge_list; - std::vector edge_length_list; - std::set eol_edge_idx_set; - GTLHolePolyInt gtl_hole_poly; - int32_t poly_info_idx = -1; - }; -#endif std::vector& routing_layer_list = DRCDM.getDatabase().get_routing_layer_list(); - std::map>& routing_to_adjacent_cut_map = DRCDM.getDatabase().get_routing_to_adjacent_cut_map(); - - std::map>> routing_net_poly_info_map; - { - std::map> routing_net_gtl_poly_set_map; - for (DRCShape* drc_shape : rv_cluster.get_drc_env_shape_list()) { - if (drc_shape->get_is_routing()) { - routing_net_gtl_poly_set_map[drc_shape->get_layer_idx()][drc_shape->get_net_idx()] += DRCUTIL.convertToGTLRectInt(drc_shape->get_rect()); - } - } - for (DRCShape* drc_shape : rv_cluster.get_drc_result_shape_list()) { - if (drc_shape->get_is_routing()) { - routing_net_gtl_poly_set_map[drc_shape->get_layer_idx()][drc_shape->get_net_idx()] += DRCUTIL.convertToGTLRectInt(drc_shape->get_rect()); - } - } - for (auto& [routing_layer_idx, net_gtl_poly_set_map] : routing_net_gtl_poly_set_map) { - for (auto& [net_idx, gtl_poly_set] : net_gtl_poly_set_map) { - std::vector gtl_hole_poly_list; - gtl_poly_set.get(gtl_hole_poly_list); - for (GTLHolePolyInt& gtl_hole_poly : gtl_hole_poly_list) { - int32_t coord_size = static_cast(gtl_hole_poly.size()); - if (coord_size < 4) { + const auto& layer_data = rv_cluster.get_layer_data(); + + auto collect_exempted_eol_edges = [&](const auto& curr_layer_data, int32_t eol_width, + std::set& exempted_eol_boundary_ids) { + for (const auto& net_entry : curr_layer_data.nets) { + const RVRoutingNet& routing_net = net_entry.second; + for (const PolygonData& polygon_data : curr_layer_data.getPolygons(routing_net)) { + std::vector visited_ring_boundary(static_cast(polygon_data.boundary_count), false); + for (const BoundaryData& seed_boundary : curr_layer_data.getBoundaries(polygon_data)) { + int32_t seed_boundary_id = curr_layer_data.getBoundaryId(seed_boundary); + int32_t seed_local_idx = seed_boundary_id - polygon_data.boundary_begin; + if (visited_ring_boundary[seed_local_idx]) { continue; } - std::vector coord_list; - for (auto iter = gtl_hole_poly.begin(); iter != gtl_hole_poly.end(); iter++) { - coord_list.push_back(DRCUTIL.convertToPlanarCoord(*iter)); - } - std::vector convex_corner_list; - std::vector> edge_list; - std::vector edge_length_list; - for (int32_t i = 0; i < coord_size; i++) { - PlanarCoord& pre_coord = coord_list[getIdx(i - 1, coord_size)]; - PlanarCoord& curr_coord = coord_list[i]; - PlanarCoord& post_coord = coord_list[getIdx(i + 1, coord_size)]; - convex_corner_list.push_back(DRCUTIL.isConvexCorner(DRCUTIL.getRotation(gtl_hole_poly), pre_coord, curr_coord, post_coord)); - edge_list.push_back(Segment(pre_coord, curr_coord)); - edge_length_list.push_back(DRCUTIL.getManhattanDistance(pre_coord, curr_coord)); - } - std::set eol_edge_idx_set; - for (int32_t i = 0; i < coord_size; i++) { - if (convex_corner_list[getIdx(i - 1, coord_size)] && convex_corner_list[i]) { - eol_edge_idx_set.insert(i); + + int32_t curr_boundary_id = seed_boundary_id; + do { + int32_t local_idx = curr_boundary_id - polygon_data.boundary_begin; + if (local_idx < 0 || polygon_data.boundary_count <= local_idx || visited_ring_boundary[local_idx]) { + break; } - } - routing_net_poly_info_map[routing_layer_idx][net_idx].emplace_back(coord_size, coord_list, convex_corner_list, edge_list, edge_length_list, - eol_edge_idx_set, gtl_hole_poly); + visited_ring_boundary[local_idx] = true; + + const BoundaryData& curr_boundary = curr_layer_data.getBoundary(curr_boundary_id); + const BoundaryData& prev_boundary = curr_layer_data.getPrevBoundary(curr_boundary_id); + bool is_curr_eol_boundary = prev_boundary.isConvex && curr_boundary.isConvex; + bool is_exempted = curr_boundary.edge_length < eol_width && is_curr_eol_boundary; + if (is_exempted) { + exempted_eol_boundary_ids.insert(curr_boundary_id); + } + curr_boundary_id = curr_boundary.next_boundary_id; + } while (curr_boundary_id != seed_boundary_id); } } } + }; + + auto build_outside_query_rect = [](const Corner& corner, int32_t spacing) { + Orientation outer_orient1 = DRCUTIL.getOppositeOrientation(corner.orient1); + Orientation outer_orient2 = DRCUTIL.getOppositeOrientation(corner.orient2); + + int32_t ll_x_minus_offset = 0; + int32_t ll_y_minus_offset = 0; + int32_t ur_x_add_offset = 0; + int32_t ur_y_add_offset = 0; + for (Orientation orient : {outer_orient1, outer_orient2}) { + if (orient == Orientation::kWest) { + ll_x_minus_offset = spacing; + } else if (orient == Orientation::kSouth) { + ll_y_minus_offset = spacing; + } else if (orient == Orientation::kEast) { + ur_x_add_offset = spacing; + } else if (orient == Orientation::kNorth) { + ur_y_add_offset = spacing; + } + } + return DRCUTIL.getEnlargedRect(corner.point, ll_x_minus_offset, ll_y_minus_offset, ur_x_add_offset, ur_y_add_offset); + }; + + auto queryNetIdxByRect = [](const RVLayerData& rv_layer_data, const PlanarRect& query_rect) -> int32_t { + std::vector> rect_max_rect_pair_list; + rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(query_rect), std::back_inserter(rect_max_rect_pair_list)); + return rect_max_rect_pair_list.empty() ? -1 : rv_layer_data.getNetIdxByMaxRectId(rect_max_rect_pair_list.front().second); + }; + + std::map layer_merged_polyset_map; + for (const auto& [routing_layer_idx, rv_layer_data] : layer_data) { + for (const auto& net_entry : rv_layer_data.nets) { + const RVRoutingNet& routing_net = net_entry.second; + layer_merged_polyset_map[routing_layer_idx] += routing_net.polyset; + } } - std::map>, bgi::quadratic<16>>> routing_bg_rtree_map; - { - for (auto& [routing_layer_idx, net_poly_info_map] : routing_net_poly_info_map) { - for (auto& [net_idx, poly_info_list] : net_poly_info_map) { - for (int32_t i = 0; i < static_cast(poly_info_list.size()); i++) { - std::vector gtl_rect_list; - gtl::get_max_rectangles(gtl_rect_list, poly_info_list[i].gtl_hole_poly); - for (GTLRectInt& gtl_rect : gtl_rect_list) { - routing_bg_rtree_map[routing_layer_idx].insert(std::make_pair(DRCUTIL.convertToBGRectInt(gtl_rect), std::make_pair(net_idx, i))); - } - poly_info_list[i].poly_info_idx = i; + + std::map merged_layer_data_map; + auto append_boundary_edges = [this](RVLayerData& rv_layer_data, GTLHolePolyInt& check_hole_poly, bool is_hole, int32_t polygon_id, + std::vector>& boundary_rtree_inputs) { + int32_t coord_size = static_cast(check_hole_poly.size()); + std::vector coord_list; + coord_list.reserve(coord_size); + for (auto iter = check_hole_poly.begin(); iter != check_hole_poly.end(); ++iter) { + coord_list.push_back(DRCUTIL.convertToPlanarCoord(*iter)); + } + while (coord_list.size() > 1 && coord_list.front() == coord_list.back()) { + coord_list.pop_back(); + } + coord_size = static_cast(coord_list.size()); + if (coord_size < 2) { + return; + } + + Rotation rotation = DRCUTIL.getRotation(check_hole_poly); + auto get_boundary_orient = [is_hole, rotation](const PlanarCoord& begin_coord, const PlanarCoord& end_coord) { + auto rotate_left = [](Orientation orient) { + switch (orient) { + case Orientation::kEast: + return Orientation::kNorth; + case Orientation::kNorth: + return Orientation::kWest; + case Orientation::kWest: + return Orientation::kSouth; + case Orientation::kSouth: + return Orientation::kEast; + default: + return Orientation::kNone; } + }; + auto rotate_right = [](Orientation orient) { + switch (orient) { + case Orientation::kEast: + return Orientation::kSouth; + case Orientation::kSouth: + return Orientation::kWest; + case Orientation::kWest: + return Orientation::kNorth; + case Orientation::kNorth: + return Orientation::kEast; + default: + return Orientation::kNone; + } + }; + + Orientation travel_orient = DRCUTIL.getOrientation(begin_coord, end_coord); + bool metal_on_left = (rotation == Rotation::kCounterclockwise); + if (is_hole) { + metal_on_left = !metal_on_left; + } + return metal_on_left ? rotate_right(travel_orient) : rotate_left(travel_orient); + }; + + std::vector convex_corner_list(coord_size, false); + if (coord_size >= 3) { + for (int32_t i = 0; i < coord_size; i++) { + PlanarCoord& pre_coord = coord_list[getIdx(i - 1, coord_size)]; + PlanarCoord& curr_coord = coord_list[i]; + PlanarCoord& post_coord = coord_list[getIdx(i + 1, coord_size)]; + convex_corner_list[i] = is_hole ? DRCUTIL.isConcaveCorner(rotation, pre_coord, curr_coord, post_coord) + : DRCUTIL.isConvexCorner(rotation, pre_coord, curr_coord, post_coord); + } + } + + std::vector ring_boundary_ids; + ring_boundary_ids.reserve(coord_size); + for (int32_t i = 0; i < coord_size; i++) { + PlanarCoord& pre_coord = coord_list[getIdx(i - 1, coord_size)]; + PlanarCoord& curr_coord = coord_list[i]; + if (pre_coord == curr_coord) { + continue; + } + + BoundaryData boundary_data; + boundary_data.edge = DRCUTIL.convertToGTLRectInt(DRCUTIL.getRect(pre_coord, curr_coord)); + boundary_data.begin_coord = pre_coord; + boundary_data.end_coord = curr_coord; + boundary_data.orient = get_boundary_orient(pre_coord, curr_coord); + boundary_data.polygon_id = polygon_id; + boundary_data.edge_length = DRCUTIL.getManhattanDistance(pre_coord, curr_coord); + boundary_data.isConvex = convex_corner_list[i]; + boundary_data.isHole = is_hole; + + rv_layer_data.boundary_pool.push_back(boundary_data); + int32_t boundary_id = static_cast(rv_layer_data.boundary_pool.size()) - 1; + ring_boundary_ids.push_back(boundary_id); + boundary_rtree_inputs.push_back({boundary_data.edge, boundary_id}); + } + + int32_t ring_size = static_cast(ring_boundary_ids.size()); + if (ring_size < 2) { + return; + } + for (int32_t i = 0; i < ring_size; i++) { + BoundaryData& boundary_data = rv_layer_data.boundary_pool[ring_boundary_ids[i]]; + boundary_data.prev_boundary_id = ring_boundary_ids[getIdx(i - 1, ring_size)]; + boundary_data.next_boundary_id = ring_boundary_ids[getIdx(i + 1, ring_size)]; + } + }; + + auto build_layer_component_data = [&](RVLayerData& merged_layer_data, const GTLPolySetInt& merged_layer_polyset) { + merged_layer_data.nets.clear(); + merged_layer_data.polygon_pool.clear(); + merged_layer_data.max_rect_pool.clear(); + merged_layer_data.boundary_pool.clear(); + + std::vector> rect_rtree_inputs; + std::vector> boundary_rtree_inputs; + std::vector gtl_hole_poly_list; + merged_layer_polyset.get(gtl_hole_poly_list); + merged_layer_data.polygon_pool.reserve(gtl_hole_poly_list.size()); + + for (int32_t component_idx = 0; component_idx < static_cast(gtl_hole_poly_list.size()); ++component_idx) { + GTLHolePolyInt& gtl_hole_poly = gtl_hole_poly_list[component_idx]; + GTLPolySetInt component_polyset; + component_polyset += gtl_hole_poly; + + RVRoutingNet& routing_net = merged_layer_data.nets[component_idx]; + routing_net.polyset = component_polyset; + routing_net.polygon_begin = static_cast(merged_layer_data.polygon_pool.size()); + routing_net.max_rect_begin = static_cast(merged_layer_data.max_rect_pool.size()); + routing_net.boundary_begin = static_cast(merged_layer_data.boundary_pool.size()); + + int32_t polygon_id = static_cast(merged_layer_data.polygon_pool.size()); + merged_layer_data.polygon_pool.push_back( + {component_idx, static_cast(merged_layer_data.max_rect_pool.size()), 0, static_cast(merged_layer_data.boundary_pool.size()), 0}); + PolygonData& polygon_data = merged_layer_data.polygon_pool.back(); + + std::vector gtl_rect_list; + gtl::get_max_rectangles(gtl_rect_list, gtl_hole_poly); + merged_layer_data.max_rect_pool.reserve(merged_layer_data.max_rect_pool.size() + gtl_rect_list.size()); + for (GTLRectInt& gtl_rect : gtl_rect_list) { + MaxRectData max_rect_data; + max_rect_data.rect = gtl_rect; + max_rect_data.polygon_id = polygon_id; + + merged_layer_data.max_rect_pool.push_back(max_rect_data); + int32_t max_rect_id = static_cast(merged_layer_data.max_rect_pool.size()) - 1; + rect_rtree_inputs.push_back({gtl_rect, max_rect_id}); + } + polygon_data.max_rect_count = static_cast(merged_layer_data.max_rect_pool.size()) - polygon_data.max_rect_begin; + + append_boundary_edges(merged_layer_data, gtl_hole_poly, false, polygon_id, boundary_rtree_inputs); + for (auto iter = gtl_hole_poly.begin_holes(); iter != gtl_hole_poly.end_holes(); ++iter) { + GTLPolyInt gtl_poly = *iter; + GTLHolePolyInt hole_poly; + hole_poly.set(gtl_poly.begin(), gtl_poly.end()); + append_boundary_edges(merged_layer_data, hole_poly, true, polygon_id, boundary_rtree_inputs); } + polygon_data.boundary_count = static_cast(merged_layer_data.boundary_pool.size()) - polygon_data.boundary_begin; + + routing_net.polygon_count = static_cast(merged_layer_data.polygon_pool.size()) - routing_net.polygon_begin; + routing_net.max_rect_count = static_cast(merged_layer_data.max_rect_pool.size()) - routing_net.max_rect_begin; + routing_net.boundary_count = static_cast(merged_layer_data.boundary_pool.size()) - routing_net.boundary_begin; } + + merged_layer_data.rect_rtrees = decltype(merged_layer_data.rect_rtrees)(rect_rtree_inputs); + merged_layer_data.boundary_rtrees = decltype(merged_layer_data.boundary_rtrees)(boundary_rtree_inputs); + }; + + for (const auto& [routing_layer_idx, merged_layer_polyset] : layer_merged_polyset_map) { + build_layer_component_data(merged_layer_data_map[routing_layer_idx], merged_layer_polyset); } - for (auto& [routing_layer_idx, net_poly_info_map] : routing_net_poly_info_map) { - if (DRCUTIL.exist(layer_corner_spacing_rule, routing_layer_idx) == false) { - continue; // skip layer without corner spacing rule + for (auto& [routing_layer_idx, rv_layer_data] : layer_data) { + auto merged_layer_it = merged_layer_data_map.find(routing_layer_idx); + if (merged_layer_it == merged_layer_data_map.end()) { + continue; } - CornerSpacingRule& curr_rule = layer_corner_spacing_rule[routing_layer_idx]; - for (auto& [net_idx, poly_info_list] : net_poly_info_map) { - for (PolyInfo& poly_info : poly_info_list) { - int32_t& coord_size = poly_info.coord_size; - std::vector& coord_list = poly_info.coord_list; - std::vector gtl_rect_list; - gtl::get_max_rectangles(gtl_rect_list, poly_info.gtl_hole_poly); - std::vector rect_list; - std::set eol_edge_idx_set = poly_info.eol_edge_idx_set; - for (GTLRectInt& gtl_rect : gtl_rect_list) { - rect_list.push_back(DRCUTIL.convertToPlanarRect(gtl_rect)); + RVLayerData& merged_layer_data = merged_layer_it->second; + RoutingLayer& routing_layer = routing_layer_list[routing_layer_idx]; + std::vector& corner_spacing_rule_list = routing_layer.get_corner_spacing_rule_list(); + std::vector violations; + std::vector check_corners; + + for (auto& corner_spacing_rule : corner_spacing_rule_list) { + if (corner_spacing_rule.has_convex_corner) { + // build exempted eol + std::set exempted_eol_boundary_ids; + if (corner_spacing_rule.has_except_eol) { + collect_exempted_eol_edges(rv_layer_data, corner_spacing_rule.except_eol, exempted_eol_boundary_ids); } - for (int32_t eol_idx = 0; eol_idx < poly_info.convex_corner_list.size(); eol_idx++) { - if (!poly_info.convex_corner_list[eol_idx]) { - continue; // skip non-convex corner - } - if(curr_rule.has_except_eol){ - int32_t eol_width = curr_rule.eolwidth; - int32_t post_eol_idx = getIdx(eol_idx + 1, coord_size); - if((DRCUTIL.exist(eol_edge_idx_set, eol_idx) && poly_info.edge_length_list[eol_idx] < eol_width) || - (DRCUTIL.exist(eol_edge_idx_set, post_eol_idx) && poly_info.edge_length_list[post_eol_idx] < eol_width)) { - continue; // skip if the adjacent edges are shorter than the eol width - } - } - PlanarCoord eol_coord = coord_list[eol_idx]; - PlanarCoord pre_coord = coord_list[getIdx(eol_idx - 1, coord_size)]; - PlanarCoord post_coord = coord_list[getIdx(eol_idx + 1, coord_size)]; - PlanarRect corner_rect = DRCUTIL.getBoundingBox({pre_coord, eol_coord, post_coord}); - Orientation pre_orientation = DRCUTIL.getOrientation(pre_coord, eol_coord); - Orientation post_orientation = DRCUTIL.getOrientation(eol_coord, post_coord); - int32_t max_width = 0; - for (PlanarRect& rect : rect_list) { - if (DRCUTIL.isInside(rect, eol_coord)) { - max_width = std::max(max_width, rect.getWidth()); - } - } - int32_t required_spacing = 0; - for (auto& [width, spacing] : curr_rule.width_spacing_list) { - if (max_width > width) { - required_spacing = spacing; + + // build dubious corner + check_corners.clear(); + std::set> seen_corner_keys; + for (const auto& [net_idx, routing_net] : rv_layer_data.nets) { + for (const PolygonData& polygon_data : rv_layer_data.getPolygons(routing_net)) { + int32_t polygon_id = rv_layer_data.getPolygonId(polygon_data); + std::vector visited_ring_boundary(static_cast(polygon_data.boundary_count), false); + for (const BoundaryData& seed_boundary : rv_layer_data.getBoundaries(polygon_data)) { + if (seed_boundary.isHole) { + continue; + } + int32_t seed_boundary_id = rv_layer_data.getBoundaryId(seed_boundary); + int32_t seed_local_idx = seed_boundary_id - polygon_data.boundary_begin; + if (visited_ring_boundary[seed_local_idx]) { + continue; + } + + std::vector ring_boundary_ids; + int32_t curr_boundary_id = seed_boundary_id; + do { + int32_t local_idx = curr_boundary_id - polygon_data.boundary_begin; + if (local_idx < 0 || polygon_data.boundary_count <= local_idx || visited_ring_boundary[local_idx]) { + break; + } + visited_ring_boundary[local_idx] = true; + ring_boundary_ids.push_back(curr_boundary_id); + curr_boundary_id = rv_layer_data.getBoundary(curr_boundary_id).next_boundary_id; + } while (curr_boundary_id != seed_boundary_id); + + int32_t coord_size = static_cast(ring_boundary_ids.size()); + if (coord_size < 3) { + continue; + } + + std::vector convex_corner_list; + convex_corner_list.reserve(coord_size); + for (int32_t ring_boundary_id : ring_boundary_ids) { + convex_corner_list.push_back(rv_layer_data.getBoundary(ring_boundary_id).isConvex); + } + + for (int32_t i = 0; i < coord_size; i++) { + if (!convex_corner_list[i]) { + continue; + } + + int32_t boundary_id = ring_boundary_ids[i]; + int32_t next_boundary_id = ring_boundary_ids[(i + 1) % coord_size]; + const BoundaryData& curr_boundary = rv_layer_data.getBoundary(boundary_id); + const BoundaryData& next_boundary = rv_layer_data.getBoundary(next_boundary_id); + + PlanarCoord corner_point = curr_boundary.end_coord; + Orientation orient1 = DRCUTIL.getOrientation(corner_point, curr_boundary.begin_coord); + Orientation orient2 = DRCUTIL.getOrientation(corner_point, next_boundary.end_coord); + + std::vector> rect_hits; + rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(PlanarRect(corner_point, corner_point)), std::back_inserter(rect_hits)); + for (const auto& [gtl_rect, max_rect_id] : rect_hits) { + const MaxRectData& max_rect_data = rv_layer_data.getMaxRect(max_rect_id); + if (max_rect_data.polygon_id != polygon_id) { + continue; + } + + PlanarRect max_rect = DRCUTIL.convertToPlanarRect(gtl_rect); + Orientation rect_orient1 = Orientation::kNone; + Orientation rect_orient2 = Orientation::kNone; + if (!DRCUTIL.getCornerOrientsInRect(max_rect, corner_point, rect_orient1, rect_orient2)) { + continue; + } + if (!((orient1 == rect_orient1 && orient2 == rect_orient2) || (orient1 == rect_orient2 && orient2 == rect_orient1))) { + continue; + } + + int32_t width = max_rect.getWidth(); + auto corner_key = std::make_tuple(corner_point.get_x(), corner_point.get_y(), width, static_cast(orient1), + static_cast(orient2), polygon_id); + if (!seen_corner_keys.insert(corner_key).second) { + continue; + } + check_corners.push_back({corner_point, width, orient1, orient2, net_idx, polygon_id, boundary_id, next_boundary_id}); + } + } } } - PlanarRect check_rect; - if (pre_orientation == Orientation::kNorth && post_orientation == Orientation::kWest) { - check_rect = DRCUTIL.getEnlargedRect(eol_coord, 0, 0, required_spacing, required_spacing); - } else if (pre_orientation == Orientation::kWest && post_orientation == Orientation::kSouth) { - check_rect = DRCUTIL.getEnlargedRect(eol_coord, required_spacing, 0, 0, required_spacing); - } else if (pre_orientation == Orientation::kSouth && post_orientation == Orientation::kEast) { - check_rect = DRCUTIL.getEnlargedRect(eol_coord, required_spacing, required_spacing, 0, 0); - } else if (pre_orientation == Orientation::kEast && post_orientation == Orientation::kNorth) { - check_rect = DRCUTIL.getEnlargedRect(eol_coord, 0, required_spacing, required_spacing, 0); - } else { - DRCLOG.error(Loc::current(), "Unrecognized orientation!"); + } + + // exempt eol boundary edge corner + if (!exempted_eol_boundary_ids.empty()) { + check_corners.erase( + std::remove_if(check_corners.begin(), check_corners.end(), [&](const Corner& corner) { + return DRCUTIL.exist(exempted_eol_boundary_ids, corner.boundary_id) + || DRCUTIL.exist(exempted_eol_boundary_ids, corner.next_boundary_id); + }), + check_corners.end()); + } + + // query corner rect towards outside + for (auto& check_corner : check_corners) { + int32_t spacing = corner_spacing_rule.get_width_spacing(check_corner.width); + if (spacing <= 0) { + continue; } + const BoundaryData& curr_boundary = rv_layer_data.getBoundary(check_corner.boundary_id); + const BoundaryData& next_boundary = rv_layer_data.getBoundary(check_corner.next_boundary_id); + PlanarRect corner_rect = DRCUTIL.getRect(curr_boundary.begin_coord, next_boundary.end_coord); + PlanarRect check_rect = build_outside_query_rect(check_corner, spacing); + + std::vector> boundary_hits; + merged_layer_data.queryBoundaries(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(boundary_hits)); - std::map> env_net_poly_info_idx_map; - { - std::vector>> bg_rect_net_pair_list; - routing_bg_rtree_map[routing_layer_idx].query(bgi::intersects(DRCUTIL.convertToBGRectInt(check_rect)), std::back_inserter(bg_rect_net_pair_list)); - for (auto& [bg_env_rect, net_poly_info_idx_pair] : bg_rect_net_pair_list) { - env_net_poly_info_idx_map[net_poly_info_idx_pair.first].insert(net_poly_info_idx_pair.second); + for (const auto& [gtl_rect, boundary_id] : boundary_hits) { + const BoundaryData& env_boundary = merged_layer_data.getBoundary(boundary_id); + if (env_boundary.orient != check_corner.orient1 && env_boundary.orient != check_corner.orient2) { + continue; } - } - std::map orientation_map = {{Orientation::kEast, Orientation::kWest}, - {Orientation::kWest, Orientation::kEast}, - {Orientation::kSouth, Orientation::kNorth}, - {Orientation::kNorth, Orientation::kSouth}}; - for (auto& [env_net_idx, env_poly_info_idx_set] : env_net_poly_info_idx_map) { - for (int32_t env_poly_info_idx : env_poly_info_idx_set) { - PolyInfo& env_poly_info = net_poly_info_map[env_net_idx][env_poly_info_idx]; - - for (int32_t env_eol_idx = 0; env_eol_idx < env_poly_info.convex_corner_list.size(); env_eol_idx++) { - if (!env_poly_info.convex_corner_list[env_eol_idx]) { - continue; // skip non-convex corner - } - PlanarCoord env_eol_coord = env_poly_info.coord_list[env_eol_idx]; - PlanarCoord env_pre_coord = env_poly_info.coord_list[getIdx(env_eol_idx - 1, env_poly_info.coord_size)]; - PlanarCoord env_post_coord = env_poly_info.coord_list[getIdx(env_eol_idx + 1, env_poly_info.coord_size)]; - if(DRCUTIL.isInside(check_rect, env_eol_coord) == false ) { - continue; + PlanarRect env_edge_rect = DRCUTIL.convertToPlanarRect(gtl_rect); + PlanarRect env_prl_rect = env_edge_rect; + bool has_positive_prl = false; + { + const PolygonData& env_polygon = merged_layer_data.getPolygon(env_boundary.polygon_id); + Segment env_boundary_seg(env_boundary.begin_coord, env_boundary.end_coord); + std::vector env_prl_rect_list; + for (const MaxRectData& env_max_rect : merged_layer_data.getMaxRects(env_polygon)) { + PlanarRect candidate_rect = DRCUTIL.convertToPlanarRect(env_max_rect.rect); + if (DRCUTIL.getTouchedEdgeOrient(candidate_rect, env_boundary_seg) != env_boundary.orient) { + continue; } - if (!(orientation_map[pre_orientation] == DRCUTIL.getOrientation(env_pre_coord, env_eol_coord) - && orientation_map[post_orientation] == DRCUTIL.getOrientation(env_eol_coord, env_post_coord))) { - continue; // skip if the orientation is not matched + env_prl_rect_list.push_back(candidate_rect); + if (DRCUTIL.getParallelLength(corner_rect, candidate_rect) > 0) { + has_positive_prl = true; } - int32_t x_spacing = std::abs(env_eol_coord.get_x() - eol_coord.get_x()); - int32_t y_spacing = std::abs(env_eol_coord.get_y() - eol_coord.get_y()); - int32_t MAXXY_spacing = std::max(x_spacing, y_spacing); - if (MAXXY_spacing >= required_spacing || MAXXY_spacing == 0) { - continue; // skip if the spacing is not satisfied + } + if (!env_prl_rect_list.empty()) { + env_prl_rect = env_prl_rect_list.front(); + } else if (DRCUTIL.getParallelLength(corner_rect, env_edge_rect) > 0) { + has_positive_prl = true; + } + } + + if (!DRCUTIL.isOpenOverlap(check_rect, env_edge_rect) || has_positive_prl) { + continue; + } + PlanarRect violation_rect = DRCUTIL.getSpacingRect(corner_rect, env_edge_rect); + if(violation_rect.getArea() != 0) { + std::vector> overlap_rect_hits; + merged_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(violation_rect), std::back_inserter(overlap_rect_hits)); + GTLPolySetInt violation_ps; + violation_ps += DRCUTIL.convertToGTLRectInt(violation_rect); + for (const auto& [overlap_gtl_rect, overlap_max_rect_id] : overlap_rect_hits) { + (void) overlap_max_rect_id; + PlanarRect overlap_rect = DRCUTIL.convertToPlanarRect(overlap_gtl_rect); + if (DRCUTIL.isOpenOverlap(violation_rect, overlap_rect)) { + violation_ps -= overlap_gtl_rect; } + } - PlanarRect violation_rect = DRCUTIL.getBoundingBox({eol_coord, env_eol_coord}); - Violation violation; - violation.set_violation_type(ViolationType::kCornerSpacing); - violation.set_required_size(required_spacing); - violation.set_is_routing(true); - violation.set_violation_net_set({net_idx, env_net_idx}); - violation.set_layer_idx(routing_layer_idx); - violation.set_rect(violation_rect); - rv_cluster.get_violation_list().push_back(violation); + if (gtl::empty(violation_ps)) { + continue; } + + std::vector remain_violation_poly_list; + violation_ps.get(remain_violation_poly_list); + if (remain_violation_poly_list.size() != 1) { + continue; + } + + GTLRectInt remain_violation_bbox; + violation_ps.extents(remain_violation_bbox); + if (!(DRCUTIL.convertToPlanarRect(remain_violation_bbox) == violation_rect)) { + continue; + } + } + int32_t env_net_idx = queryNetIdxByRect(rv_layer_data, env_edge_rect); + + Violation violation; + violation.set_violation_type(ViolationType::kCornerSpacing); + violation.set_required_size(spacing); + violation.set_is_routing(true); + violation.set_violation_net_set({check_corner.net_idx, env_net_idx}); + violation.set_layer_idx(routing_layer_idx); + violation.set_rect(violation_rect); + violations.push_back(std::move(violation)); + } + } + } + } + + + // postprocess, build final violations + { + if (violations.size() > 1) { + std::sort(violations.begin(), violations.end(), [](const Violation& a, const Violation& b) { + const auto& ra = a.get_rect(); + const auto& rb = b.get_rect(); + if (ra.get_ll_x() != rb.get_ll_x()) + return ra.get_ll_x() < rb.get_ll_x(); + if (ra.get_ur_x() != rb.get_ur_x()) + return ra.get_ur_x() > rb.get_ur_x(); + if (ra.get_ll_y() != rb.get_ll_y()) + return ra.get_ll_y() < rb.get_ll_y(); + return ra.get_ur_y() > rb.get_ur_y(); + }); + + std::vector results; + results.reserve(violations.size()); + + std::vector active_set; + + for (const auto& v : violations) { + bool is_redundant = false; + const auto& cur_r = v.get_rect(); + + active_set.erase( + std::remove_if(active_set.begin(), active_set.end(), [&](const Violation* p) { return p->get_rect().get_ur_x() < cur_r.get_ll_x(); }), + active_set.end()); + + for (const auto* p_active : active_set) { + if (DRCUTIL.isInside(p_active->get_rect(), cur_r)) { + is_redundant = true; + break; } } + + if (!is_redundant) { + results.push_back(v); + active_set.push_back(&results.back()); + } } + violations = std::move(results); } + + rv_cluster.get_violation_list().insert(rv_cluster.get_violation_list().end(), std::make_move_iterator(violations.begin()), + std::make_move_iterator(violations.end())); } + } -#endif } - } // namespace idrc diff --git a/src/operation/iDRC/source/toolkit/utility/Utility.hpp b/src/operation/iDRC/source/toolkit/utility/Utility.hpp index e247e71b5..fabd117b6 100644 --- a/src/operation/iDRC/source/toolkit/utility/Utility.hpp +++ b/src/operation/iDRC/source/toolkit/utility/Utility.hpp @@ -190,6 +190,34 @@ class Utility return orientation_list; } + // 获取 rect 某个角点向内部的两个方向 + static bool getCornerOrientsInRect(const PlanarRect& rect, const PlanarCoord& corner_point, Orientation& orient1, Orientation& orient2) + { + int32_t x = corner_point.get_x(); + int32_t y = corner_point.get_y(); + if (x == rect.get_ll_x() && y == rect.get_ll_y()) { + orient1 = Orientation::kEast; + orient2 = Orientation::kNorth; + return true; + } + if (x == rect.get_ur_x() && y == rect.get_ur_y()) { + orient1 = Orientation::kWest; + orient2 = Orientation::kSouth; + return true; + } + if (x == rect.get_ll_x() && y == rect.get_ur_y()) { + orient1 = Orientation::kEast; + orient2 = Orientation::kSouth; + return true; + } + if (x == rect.get_ur_x() && y == rect.get_ll_y()) { + orient1 = Orientation::kWest; + orient2 = Orientation::kNorth; + return true; + } + return false; + } + static Direction getOppositeDirection(Direction direction) { if (direction == Direction::kHorizontal) { @@ -886,15 +914,21 @@ class Utility static PlanarRect getRect(Segment segment) { return getRect(segment.get_first(), segment.get_second()); } // 三个点的叉乘 - static int32_t crossProduct(Rotation rotation, PlanarCoord& first_coord, PlanarCoord& second_coord, PlanarCoord& third_coord) + static int64_t crossProduct(Rotation rotation, PlanarCoord& first_coord, PlanarCoord& second_coord, PlanarCoord& third_coord) { - int32_t cross_product = 0; + // Use 64-bit arithmetic here because large layout coordinates can make the + // area term exceed int32_t and flip the sign, which breaks convex/concave checks. + int64_t cross_product = 0; if (rotation == Rotation::kClockwise) { - cross_product = ((second_coord.get_x() - first_coord.get_x()) * (third_coord.get_y() - first_coord.get_y()) - - (second_coord.get_y() - first_coord.get_y()) * (third_coord.get_x() - first_coord.get_x())); + cross_product = (static_cast(second_coord.get_x()) - first_coord.get_x()) + * (static_cast(third_coord.get_y()) - first_coord.get_y()) + - (static_cast(second_coord.get_y()) - first_coord.get_y()) + * (static_cast(third_coord.get_x()) - first_coord.get_x()); } else if (rotation == Rotation::kCounterclockwise) { - cross_product = ((second_coord.get_x() - third_coord.get_x()) * (first_coord.get_y() - third_coord.get_y()) - - (second_coord.get_y() - third_coord.get_y()) * (first_coord.get_x() - third_coord.get_x())); + cross_product = (static_cast(second_coord.get_x()) - third_coord.get_x()) + * (static_cast(first_coord.get_y()) - third_coord.get_y()) + - (static_cast(second_coord.get_y()) - third_coord.get_y()) + * (static_cast(first_coord.get_x()) - third_coord.get_x()); } else { DRCLOG.error(Loc::current(), "The rotation is error!"); } @@ -1543,6 +1577,24 @@ class Utility return string; } + static std::string getBooleanName(bool value) { return value ? "true" : "false"; } + + template + static std::string getStringList(const std::vector& value_list, const std::string& delimiter = ", ", + const std::string& prefix = "[", const std::string& suffix = "]") + { + std::stringstream oss; + oss << prefix; + for (size_t i = 0; i < value_list.size(); ++i) { + if (i > 0) { + oss << delimiter; + } + oss << value_list[i]; + } + oss << suffix; + return oss.str(); + } + template static void pushStream(Stream* stream, T t, Args... args) { From d8440e04b8f350e882f1dea1e38a9c032397b490 Mon Sep 17 00:00:00 2001 From: shuyulun01 <3190100230@zju.edu.cn> Date: Wed, 22 Apr 2026 17:44:35 +0800 Subject: [PATCH 5/5] iDRC: format folder --- src/operation/iDRC/interface/DRCInterface.cpp | 12 +++++----- .../design_rule/CornerSpacingRule.hpp | 3 ++- .../ParallelRunLengthSpacingRule.hpp | 6 +++-- .../design_rule/SameLayerCutSpacingRule.hpp | 3 ++- .../rv_design_rule/AdjacentCutSpacing.cpp | 2 -- .../rv_design_rule/CornerSpacing.cpp | 22 +++++++++---------- .../ParallelRunLengthSpacing.cpp | 12 +++++----- .../rv_design_rule/SameLayerCutSpacing.cpp | 6 ++--- .../iDRC/source/toolkit/utility/Utility.hpp | 16 +++++--------- 9 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/operation/iDRC/interface/DRCInterface.cpp b/src/operation/iDRC/interface/DRCInterface.cpp index d6ffe0b04..3132eac75 100644 --- a/src/operation/iDRC/interface/DRCInterface.cpp +++ b/src/operation/iDRC/interface/DRCInterface.cpp @@ -461,10 +461,8 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa if (!idb_layer->get_lef58_corner_spacing_list().empty()) { for (const std::shared_ptr& idb_corner_spacing : idb_layer->get_lef58_corner_spacing_list()) { CornerSpacingRule corner_spacing_rule; - corner_spacing_rule.has_convex_corner - = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConvexCorner; - corner_spacing_rule.has_concave_corner - = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConcaveCorner; + corner_spacing_rule.has_convex_corner = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConvexCorner; + corner_spacing_rule.has_concave_corner = idb_corner_spacing->get_corner_type() == idb::routinglayer::Lef58CornerSpacing::CornerType::kConcaveCorner; corner_spacing_rule.has_except_eol = idb_corner_spacing->get_except_eol().has_value(); if (idb_corner_spacing->get_except_eol().has_value()) { corner_spacing_rule.except_eol = idb_corner_spacing->get_except_eol().value(); @@ -664,7 +662,7 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa if (idb_layer->get_spacing_list() != nullptr) { auto& spacing_list = parallel_run_length_spacing_rule.spacing_list; - for(auto& spacing_rule : idb_layer->get_spacing_list()->get_spacing_list()) { + for (auto& spacing_rule : idb_layer->get_spacing_list()->get_spacing_list()) { LayerSpacingType spacing_type; if (spacing_rule->get_spacing_type() == idb::IdbLayerSpacingType::kSpacingDefault) { spacing_type = LayerSpacingType::kSpacingDefault; @@ -675,7 +673,7 @@ void DRCInterface::wrapRoutingDesignRule(RoutingLayer& routing_layer, idb::IdbLa } else { spacing_type = LayerSpacingType::kNone; } - LayerSpacing spacing {spacing_type, spacing_rule->get_min_spacing(), spacing_rule->get_min_width(), spacing_rule->get_max_width()}; + LayerSpacing spacing{spacing_type, spacing_rule->get_min_spacing(), spacing_rule->get_min_width(), spacing_rule->get_max_width()}; spacing_list.push_back(spacing); } @@ -707,7 +705,7 @@ void DRCInterface::wrapCutDesignRule(CutLayer& cut_layer, idb::IdbLayerCut* idb_ continue; } } - } + } } // CutEOLSpacingRule { diff --git a/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp index 9bf89a61e..c17f399da 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/CornerSpacingRule.hpp @@ -25,7 +25,8 @@ class CornerSpacingRule public: CornerSpacingRule() = default; ~CornerSpacingRule() = default; - int32_t get_width_spacing(int32_t width) { + int32_t get_width_spacing(int32_t width) + { for (int32_t i = width_spacing_list.size() - 1; i >= 0; i--) { if (width > width_spacing_list[i].first) { return width_spacing_list[i].second; diff --git a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp index f316d5ec5..23dddbeac 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/ParallelRunLengthSpacingRule.hpp @@ -71,7 +71,8 @@ class ParallelRunLengthSpacingRule std::vector spacing_list; bool has_spacing_list = false; - int32_t getSpacingWithWidth(int32_t width) { + int32_t getSpacingWithWidth(int32_t width) + { int32_t spacing = -1; int32_t default_spacing = -1; for (auto& layerSpacing : spacing_list) { @@ -86,7 +87,8 @@ class ParallelRunLengthSpacingRule return spacing == -1 ? default_spacing : spacing; } - int32_t getSpacingMaxWidth() { + int32_t getSpacingMaxWidth() + { int32_t spacing = -1; for (auto& layerSpacing : spacing_list) { spacing = std::max(spacing, layerSpacing.min_spacing); diff --git a/src/operation/iDRC/source/data_manager/design_rule/SameLayerCutSpacingRule.hpp b/src/operation/iDRC/source/data_manager/design_rule/SameLayerCutSpacingRule.hpp index 6d5a37453..4c2bbc13c 100644 --- a/src/operation/iDRC/source/data_manager/design_rule/SameLayerCutSpacingRule.hpp +++ b/src/operation/iDRC/source/data_manager/design_rule/SameLayerCutSpacingRule.hpp @@ -19,7 +19,8 @@ #include "DRCHeader.hpp" namespace idrc { -struct SameLayerCutSpacing { +struct SameLayerCutSpacing +{ int32_t curr_spacing = -1; int32_t curr_prl = -1; int32_t curr_prl_spacing = -1; diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp index c39d19409..d96604e0f 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/AdjacentCutSpacing.cpp @@ -90,9 +90,7 @@ void RuleValidator::verifyAdjacentCutSpacing(RVCluster& rv_cluster) violation.set_required_size(adj_cut_rule.cut_spacing); rv_cluster.get_violation_list().push_back(violation); } - } - } } diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/CornerSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/CornerSpacing.cpp index 1111b5f37..996682caf 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/CornerSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/CornerSpacing.cpp @@ -17,7 +17,8 @@ #include "RuleValidator.hpp" namespace idrc { -struct Corner { +struct Corner +{ PlanarCoord point; int32_t width; Orientation orient1; @@ -33,8 +34,7 @@ void RuleValidator::verifyCornerSpacing(RVCluster& rv_cluster) std::vector& routing_layer_list = DRCDM.getDatabase().get_routing_layer_list(); const auto& layer_data = rv_cluster.get_layer_data(); - auto collect_exempted_eol_edges = [&](const auto& curr_layer_data, int32_t eol_width, - std::set& exempted_eol_boundary_ids) { + auto collect_exempted_eol_edges = [&](const auto& curr_layer_data, int32_t eol_width, std::set& exempted_eol_boundary_ids) { for (const auto& net_entry : curr_layer_data.nets) { const RVRoutingNet& routing_net = net_entry.second; for (const PolygonData& polygon_data : curr_layer_data.getPolygons(routing_net)) { @@ -377,12 +377,12 @@ void RuleValidator::verifyCornerSpacing(RVCluster& rv_cluster) // exempt eol boundary edge corner if (!exempted_eol_boundary_ids.empty()) { - check_corners.erase( - std::remove_if(check_corners.begin(), check_corners.end(), [&](const Corner& corner) { - return DRCUTIL.exist(exempted_eol_boundary_ids, corner.boundary_id) - || DRCUTIL.exist(exempted_eol_boundary_ids, corner.next_boundary_id); - }), - check_corners.end()); + check_corners.erase(std::remove_if(check_corners.begin(), check_corners.end(), + [&](const Corner& corner) { + return DRCUTIL.exist(exempted_eol_boundary_ids, corner.boundary_id) + || DRCUTIL.exist(exempted_eol_boundary_ids, corner.next_boundary_id); + }), + check_corners.end()); } // query corner rect towards outside @@ -432,7 +432,7 @@ void RuleValidator::verifyCornerSpacing(RVCluster& rv_cluster) continue; } PlanarRect violation_rect = DRCUTIL.getSpacingRect(corner_rect, env_edge_rect); - if(violation_rect.getArea() != 0) { + if (violation_rect.getArea() != 0) { std::vector> overlap_rect_hits; merged_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(violation_rect), std::back_inserter(overlap_rect_hits)); GTLPolySetInt violation_ps; @@ -476,7 +476,6 @@ void RuleValidator::verifyCornerSpacing(RVCluster& rv_cluster) } } - // postprocess, build final violations { if (violations.size() > 1) { @@ -523,7 +522,6 @@ void RuleValidator::verifyCornerSpacing(RVCluster& rv_cluster) rv_cluster.get_violation_list().insert(rv_cluster.get_violation_list().end(), std::make_move_iterator(violations.begin()), std::make_move_iterator(violations.end())); } - } } } // namespace idrc diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp index 559081e15..ba43c73d9 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/ParallelRunLengthSpacing.cpp @@ -40,11 +40,11 @@ void RuleValidator::verifyParallelRunLengthSpacing(RVCluster& rv_cluster) std::vector> neighbor_rect_id_list; { int32_t spacing_table_check = has_spacing_table ? parallel_run_length_spacing_rule.getMaxSpacing() : 0; - int32_t spacing_list_check = has_spacing_list ? parallel_run_length_spacing_rule.getSpacingMaxWidth() : 0; + int32_t spacing_list_check = has_spacing_list ? parallel_run_length_spacing_rule.getSpacingMaxWidth() : 0; int32_t check_spacing = std::max(spacing_table_check, spacing_list_check); - + PlanarRect check_rect = DRCUTIL.getEnlargedRect(rect, check_spacing); - rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(neighbor_rect_id_list)); + rv_layer_data.queryMaxRects(DRCUTIL.convertToGTLRectInt(check_rect), std::back_inserter(neighbor_rect_id_list)); } for (const auto& [gtl_rect, env_max_rect_id] : neighbor_rect_id_list) { @@ -95,7 +95,7 @@ void RuleValidator::verifyParallelRunLengthSpacing(RVCluster& rv_cluster) if (DRCUTIL.isInside(violation_env_rect, violation_rect)) { zero_area_inside = true; } - + for (auto orient : {Orientation::kEast, Orientation::kWest, Orientation::kNorth, Orientation::kSouth}) { if (!DRCUTIL.exist(orient_inside, orient) && DRCUTIL.isInside(violation_env_rect, violation_rect.getOrientEdge(orient))) { orient_inside.insert(orient); @@ -160,11 +160,9 @@ void RuleValidator::verifyParallelRunLengthSpacing(RVCluster& rv_cluster) net_required_violation_rect_map[{net_idx, env_net_idx}][real_spacing].push_back(violation_rect); } } - } - } - } + } std::map, std::map>> exclude_env; for (auto& [violation_net_set, required_violation_rect_map] : net_required_violation_rect_map) { diff --git a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp index 29175c1bf..756f298e6 100644 --- a/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp +++ b/src/operation/iDRC/source/module/rule_validator/rv_design_rule/SameLayerCutSpacing.cpp @@ -50,7 +50,7 @@ void RuleValidator::verifySameLayerCutSpacing(RVCluster& rv_cluster) curr_spacing = spacing_rule.curr_spacing; } curr_prl = -1 * spacing_rule.curr_prl; - curr_prl_spacing =spacing_rule.curr_prl_spacing; + curr_prl_spacing = spacing_rule.curr_prl_spacing; } for (const CutData& cut_data : cut_layer_data.getCuts()) { @@ -72,8 +72,8 @@ void RuleValidator::verifySameLayerCutSpacing(RVCluster& rv_cluster) int32_t net_spacing = curr_spacing; PlanarRect env_rect = DRCUTIL.convertToPlanarRect(overlap_cut_data.rect); PlanarRect violation_rect = DRCUTIL.getSpacingRect(cut_rect, env_rect); - if ((env_net_idx == net_idx) && has_same_net) { - net_spacing = curr_same_net_spacing; + if ((env_net_idx == net_idx) && has_same_net) { + net_spacing = curr_same_net_spacing; } // ignore cutShort if (DRCUTIL.isClosedOverlap(cut_rect, env_rect)) { diff --git a/src/operation/iDRC/source/toolkit/utility/Utility.hpp b/src/operation/iDRC/source/toolkit/utility/Utility.hpp index fabd117b6..af3fd6804 100644 --- a/src/operation/iDRC/source/toolkit/utility/Utility.hpp +++ b/src/operation/iDRC/source/toolkit/utility/Utility.hpp @@ -920,15 +920,11 @@ class Utility // area term exceed int32_t and flip the sign, which breaks convex/concave checks. int64_t cross_product = 0; if (rotation == Rotation::kClockwise) { - cross_product = (static_cast(second_coord.get_x()) - first_coord.get_x()) - * (static_cast(third_coord.get_y()) - first_coord.get_y()) - - (static_cast(second_coord.get_y()) - first_coord.get_y()) - * (static_cast(third_coord.get_x()) - first_coord.get_x()); + cross_product = (static_cast(second_coord.get_x()) - first_coord.get_x()) * (static_cast(third_coord.get_y()) - first_coord.get_y()) + - (static_cast(second_coord.get_y()) - first_coord.get_y()) * (static_cast(third_coord.get_x()) - first_coord.get_x()); } else if (rotation == Rotation::kCounterclockwise) { - cross_product = (static_cast(second_coord.get_x()) - third_coord.get_x()) - * (static_cast(first_coord.get_y()) - third_coord.get_y()) - - (static_cast(second_coord.get_y()) - third_coord.get_y()) - * (static_cast(first_coord.get_x()) - third_coord.get_x()); + cross_product = (static_cast(second_coord.get_x()) - third_coord.get_x()) * (static_cast(first_coord.get_y()) - third_coord.get_y()) + - (static_cast(second_coord.get_y()) - third_coord.get_y()) * (static_cast(first_coord.get_x()) - third_coord.get_x()); } else { DRCLOG.error(Loc::current(), "The rotation is error!"); } @@ -1580,8 +1576,8 @@ class Utility static std::string getBooleanName(bool value) { return value ? "true" : "false"; } template - static std::string getStringList(const std::vector& value_list, const std::string& delimiter = ", ", - const std::string& prefix = "[", const std::string& suffix = "]") + static std::string getStringList(const std::vector& value_list, const std::string& delimiter = ", ", const std::string& prefix = "[", + const std::string& suffix = "]") { std::stringstream oss; oss << prefix;