update idrc

This commit is contained in:
ZhishengZeng 2025-03-13 18:06:24 +08:00
parent 585f2ab504
commit 1d86c0425f
335 changed files with 3519 additions and 32378 deletions

View File

@ -22,8 +22,8 @@ set(CMAKE_VERBOSE_MAKEFILE OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -Werror=return-type")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O2 -Wall -g2 -ggdb -Werror=return-type")
# set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb -Werror=return-type")
set(CMAKE_BUILD_TYPE "Release")
option(BUILD_STATIC_LIB "Build static library (default ON)" ON)
option(BUILD_PYTHON "Build Python bindings (default OFF)" OFF)

View File

@ -50,3 +50,4 @@ using BGMultiLineDBL = bg::model::multi_linestring<BGLineDBL>;
using BGRectDBL = bg::model::box<BGPointDBL>;
using BGPolyDBL = bg::model::polygon<BGPointDBL>;
using BGMultiPolyDBL = bg::model::multi_polygon<BGPolyDBL>;

View File

@ -1,141 +0,0 @@
// ***************************************************************************************
// 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 <string>
namespace idrc {
enum class ViolationEnumType
{
kNone,
kArea,
kAreaEnclosed,
kShort,
kDefaultSpacing,
kPRLSpacing,
kJogToJog,
kEOL,
kWidth,
kMinStep,
kNotch,
kConnectivity,
kCornerFill,
// CUT violation
kCutShort,
kCutSpacing,
kCutWidth,
kCutArraySpacing,
kCutEnclosure,
kMax,
};
#define NET_ID_ENVIRONMENT -1
#define NET_ID_PDN -3
#define NET_ID_VDD -4
#define NET_ID_VSS -5
#define NET_ID_OBS -6
struct GetViolationTypeName
{
std::string operator()(const ViolationEnumType& type) const
{
switch (type) {
case ViolationEnumType::kArea:
return "Minimum Area";
case ViolationEnumType::kAreaEnclosed:
return "MinHole";
case ViolationEnumType::kShort:
return "Metal Short";
case ViolationEnumType::kDefaultSpacing:
return "Default Spacing";
case ViolationEnumType::kPRLSpacing:
return "ParallelRunLength Spacing";
case ViolationEnumType::kJogToJog:
return "JogToJog Spacing";
case ViolationEnumType::kEOL:
return "EndOfLine Spacing";
case ViolationEnumType::kWidth:
return "Wire Width";
case ViolationEnumType::kMinStep:
return "MinStep";
case ViolationEnumType::kNotch:
return "Notch Spacing";
case ViolationEnumType::kCornerFill:
return "Corner Fill Spacing";
// CUT violation
case ViolationEnumType::kCutShort:
return "Cut Short";
case ViolationEnumType::kCutSpacing:
return "Same Layer Cut Spacing";
case ViolationEnumType::kCutWidth:
return "CutWidth";
case ViolationEnumType::kCutArraySpacing:
return "CutArraySpacing";
case ViolationEnumType::kCutEnclosure:
return "CutEnclosure";
default:
return "None";
}
}
};
struct GetViolationType
{
ViolationEnumType operator()(const std::string& type_name) const
{
if (type_name == "Minimum Area") {
return ViolationEnumType::kArea;
} else if (type_name == "MinHole") {
return ViolationEnumType::kAreaEnclosed;
} else if (type_name == "Metal Short") {
return ViolationEnumType::kShort;
} else if (type_name == "Default Spacing") {
return ViolationEnumType::kDefaultSpacing;
} else if (type_name == "ParallelRunLength Spacing") {
return ViolationEnumType::kPRLSpacing;
} else if (type_name == "JogToJog Spacing") {
return ViolationEnumType::kJogToJog;
} else if (type_name == "EndOfLine Spacing") {
return ViolationEnumType::kEOL;
} else if (type_name == "Wire Width") {
return ViolationEnumType::kWidth;
} else if (type_name == "MinStep") {
return ViolationEnumType::kMinStep;
} else if (type_name == "Notch Spacing") {
return ViolationEnumType::kNotch;
} else if (type_name == "Corner Fill Spacing") {
return ViolationEnumType::kCornerFill;
}
// CUT violation
else if (type_name == "Cut Short") {
return ViolationEnumType::kCutShort;
} else if (type_name == "Same Layer Cut Spacing") {
return ViolationEnumType::kCutSpacing;
} else if (type_name == "CutWidth") {
return ViolationEnumType::kCutWidth;
} else if (type_name == "CutArraySpacing") {
return ViolationEnumType::kCutArraySpacing;
} else if (type_name == "CutEnclosure") {
return ViolationEnumType::kCutEnclosure;
} else {
return ViolationEnumType::kNone;
}
}
};
} // namespace idrc

View File

@ -17,8 +17,10 @@
#pragma once
#include <map>
#include <set>
#include <string>
#include <vector>
namespace ieda {
class Log;
class Str;
@ -99,89 +101,16 @@ class TileGrid;
namespace ids {
struct Segment
struct Violation
{
int first_x;
int first_y;
std::string first_layer_name;
int second_x;
int second_y;
std::string second_layer_name;
};
enum class PhysicalNodeType
{
kNone = 0,
kWire = 1,
kVia = 2
};
struct Wire
{
int first_x;
int first_y;
int second_x;
int second_y;
std::string layer_name;
};
struct Via
{
std::string via_name;
int x;
int y;
};
struct PhysicalNode
{
PhysicalNodeType type;
Wire wire;
Via via;
};
enum class AccessPointType
{
kNone = 0,
kPrefTrackGrid = 1,
kCurrTrackGrid = 2,
kCurrTrackCenter = 3,
kCurrShapeCenter = 4
};
struct AccessPoint
{
int x;
int y;
std::string layer_name;
AccessPointType type;
std::vector<std::string> via_name_list;
};
struct CellMaster
{
std::string cell_master_name;
std::map<std::string, std::vector<ids::AccessPoint>> pin_name_pa_list;
};
struct DRCTask
{
idrc::RegionQuery* region_query;
std::vector<idrc::DrcRect*> drc_rect_list;
};
struct DRCRect
{
int32_t so_id = -1; // Distinguish self and others
int32_t lb_x = -1;
int32_t lb_y = -1;
int32_t rt_x = -1;
int32_t rt_y = -1;
std::string layer_name;
bool is_artificial = false;
std::string violation_type = "";
int32_t ll_x = -1;
int32_t ll_y = -1;
int32_t ur_x = -1;
int32_t ur_y = -1;
std::string layer_name = "";
std::set<int32_t> violation_net_set;
int32_t required_size = 0;
};
} // namespace ids

View File

@ -187,7 +187,7 @@ target_link_libraries(iGUI Qt5${QT_VERSION_MAJOR}::Widgets Qt5${QT_VERSION_MAJOR
# target_link_libraries(iGUI idrc_api file_manager_cts file_manager_drc file_manager_placement tool_api_ipl OpenMP::OpenMP_CXX)
target_link_libraries(iGUI
file_manager_cts
file_manager_drc
# file_manager_drc
file_manager_placement
tool_api_ipl
idrc_pro_violation

View File

@ -1,23 +1,18 @@
AUX_SOURCE_DIRECTORY(./ TCL_IDRC_SRC)
add_library(tcl_idrc
${TCL_IDRC_SRC}
${HOME_INTERFACE}/tcl/tcl_idrc/src/tcl_check_def.cpp
${HOME_INTERFACE}/tcl/tcl_idrc/src/tcl_destroy_drc.cpp
${HOME_INTERFACE}/tcl/tcl_idrc/src/tcl_init_drc.cpp
)
target_link_libraries(tcl_idrc
PUBLIC
tool_manager
tcl
shell-cmd
str
tcl_util
# idrc_api
tool_api_idrc
idrc_pro_api
${LIBPROFILER_LIBRARY}
PRIVATE
idrc_interface
)
target_include_directories(tcl_idrc
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
${HOME_INTERFACE}/tcl/tcl_idrc/include
)

View File

@ -16,45 +16,50 @@
// ***************************************************************************************
#pragma once
#include "IdbRoutingLayerLef58Property.h"
#include "rule_basic.h"
#include "rule_condition_map.h"
#include "tcl_util.h"
namespace idrc {
namespace tcl {
class ConditionRuleArea : public ConditionRule
class TclCheckDef : public TclCmd
{
public:
ConditionRuleArea(RuleType type, int min_area) : ConditionRule(type, min_area) {}
~ConditionRuleArea() {}
explicit TclCheckDef(const char* cmd_name);
~TclCheckDef() override = default;
int get_min_area() { return get_value(); }
unsigned check() override { return 1; };
unsigned exec() override;
private:
std::vector<std::pair<std::string, ValueType>> _config_list;
};
class ConditionRuleAreaLef58 : public ConditionRule
class TclDestroyDRC : public TclCmd
{
public:
ConditionRuleAreaLef58(RuleType type, int min_area, idb::routinglayer::Lef58Area* area_rule)
: ConditionRule(type, min_area), _area_rule(area_rule)
{
}
~ConditionRuleAreaLef58() {}
explicit TclDestroyDRC(const char* cmd_name);
~TclDestroyDRC() override = default;
idb::routinglayer::Lef58Area* get_rule() { return _area_rule; }
unsigned check() override { return 1; };
unsigned exec() override;
private:
idb::routinglayer::Lef58Area* _area_rule;
std::vector<std::pair<std::string, ValueType>> _config_list;
};
class RulesMapArea : public RulesConditionMap
class TclInitDRC : public TclCmd
{
public:
RulesMapArea(RuleType type) : RulesConditionMap(type) {}
~RulesMapArea() {}
explicit TclInitDRC(const char* cmd_name);
~TclInitDRC() override = default;
unsigned check() override { return 1; };
unsigned exec() override;
private:
std::vector<std::pair<std::string, ValueType>> _config_list;
};
} // namespace idrc
} // namespace tcl

View File

@ -14,13 +14,20 @@
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#pragma once
#include "rule_condition_edge.h"
#include "tcl_drc.h"
#include <algorithm>
using namespace ieda;
#include "rule_basic.h"
namespace tcl {
namespace idrc {
int registerCmdDRC()
{
registerTclCmd(TclCheckDef, "check_def");
registerTclCmd(TclDestroyDRC, "destroy_drc");
registerTclCmd(TclInitDRC, "init_drc");
return EXIT_SUCCESS;
}
} // namespace idrc
} // namespace tcl

View File

@ -14,41 +14,27 @@
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#pragma once
#include <set>
namespace idrc {
#include "DRCInterface.hpp"
#include "flow_config.h"
#include "tcl_drc.h"
#include "tcl_util.h"
#include "usage/usage.hh"
enum class DrcCheckerType
namespace tcl {
TclCheckDef::TclCheckDef(const char* cmd_name) : TclCmd(cmd_name)
{
kNone,
kDef,
kRT,
kMax
};
}
enum class DrcStratagyType
unsigned TclCheckDef::exec()
{
kNone = 0,
kCheckFast,
kCheckComplete,
kMax
};
if (!check()) {
return 0;
}
DRCI.checkDef();
return 1;
}
enum class LayoutType
{
kNone,
kRouting,
kCut,
kMax
};
enum class DrcDirection
{
kNone,
kUp,
kDown,
kLeft,
kRight
};
} // namespace idrc
} // namespace tcl

View File

@ -14,11 +14,23 @@
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#include "DRCInterface.hpp"
#include "tcl_drc.h"
#include "tcl_util.h"
#include "rule_condition_area.h"
namespace tcl {
#include "rule_basic.h"
TclDestroyDRC::TclDestroyDRC(const char* cmd_name) : TclCmd(cmd_name)
{
}
namespace idrc {
unsigned TclDestroyDRC::exec()
{
if (!check()) {
return 0;
}
DRCI.destroyDRC();
return 1;
}
} // namespace idrc
} // namespace tcl

View File

@ -14,20 +14,28 @@
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#pragma once
#include "condition_manager.h"
#include "rule_base.h"
#include "tech_rules.h"
#include "DRCInterface.hpp"
#include "tcl_drc.h"
#include "tcl_util.h"
namespace idrc {
namespace tcl {
class RuleSpacing : public RuleBase
// public
TclInitDRC::TclInitDRC(const char* cmd_name) : TclCmd(cmd_name)
{
public:
RuleSpacing(DrcConditionManager* condition_manager) : RuleBase(condition_manager) {}
~RuleSpacing() {}
private:
};
}
} // namespace idrc
unsigned TclInitDRC::exec()
{
if (!check()) {
return 0;
}
DRCI.initDRC();
return 1;
}
// private
} // namespace tcl

View File

@ -1,96 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
// #include "DRC.h"
#include "idrc_api.h"
#include "tcl_drc.h"
#include "tcl_util.h"
#ifdef USE_PROFILER
#include <gperftools/profiler.h>
#endif
namespace tcl {
// public
TclDrcCheckDef::TclDrcCheckDef(const char* cmd_name) : TclCmd(cmd_name)
{
// addOptionForJSON();
addOptionForTCL();
}
unsigned TclDrcCheckDef::exec()
{
if (!check()) {
return 0;
}
idrc::DrcApi drc_api;
drc_api.init();
auto violations = drc_api.checkDef();
for (auto& [enum_type, violation_list] : violations) {
std::cout << idrc::GetViolationTypeName()(enum_type) << ": " << violation_list.size() << std::endl;
}
return 1;
}
// private
// void TclDrcCheckDef::addOptionForJSON()
// {
// TclUtil::addOption(this, "-config", ValueType::kString);
// }
void TclDrcCheckDef::addOptionForTCL()
{
TclUtil::addOption(this, "-def_path", ValueType::kString);
}
// bool TclDrcCheckDef::initConfigMapByJSON(std::map<std::string, std::any>& config_map)
// {
// TclOption* config_file_path_option = getOptionOrArg("-config");
// if (!config_file_path_option->is_set_val()) {
// return false;
// }
// std::ifstream& config_file = TclUtil::getInputFileStream(config_file_path_option->getStringVal());
// nlohmann::json json;
// // read a JSON file
// config_file >> json;
// json = json["PM"];
// TclUtil::updateConfigMap(json, config_map, "-log_verbose", ValueType::kInt);
// TclUtil::updateConfigMap(json, config_map, "-ban_pa_generate_layer_list", ValueType::kStringList);
// TclUtil::updateConfigMap(json, config_map, "-only_via_access_layer_list", ValueType::kStringList);
// TclUtil::updateConfigMap(json, config_map, "-temp_directory_path", ValueType::kString);
// TclUtil::closeFileStream(config_file);
// return true;
// }
bool TclDrcCheckDef::initConfigMapByTCL(std::map<std::string, std::any>& config_map)
{
std::any config_value = TclUtil::getValue(this, "-def_path", ValueType::kString);
if (config_value.has_value()) {
config_map.insert(std::make_pair("-def_path", config_value));
}
return true;
}
} // namespace tcl

View File

@ -1,126 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "tcl_drc.h"
#include "tool_manager.h"
namespace tcl {
CmdDRCAutoRun::CmdDRCAutoRun(const char* cmd_name) : TclCmd(cmd_name)
{
auto* file_name_option = new TclStringOption(TCL_CONFIG, 1, nullptr);
auto* file_path_option = new TclStringOption(TCL_PATH, 1, nullptr);
addOption(file_name_option);
addOption(file_path_option);
}
unsigned CmdDRCAutoRun::check()
{
TclOption* file_name_option = getOptionOrArg(TCL_CONFIG);
TclOption* file_path_option = getOptionOrArg(TCL_PATH);
LOG_FATAL_IF(!file_name_option);
LOG_FATAL_IF(!file_path_option);
return 1;
}
unsigned CmdDRCAutoRun::exec()
{
if (!check()) {
return 0;
}
TclOption* option = getOptionOrArg(TCL_CONFIG);
auto data_config = option->getStringVal();
TclOption* path_option = getOptionOrArg(TCL_PATH);
auto data_path = path_option->getStringVal();
if (iplf::tmInst->autoRunDRC(data_config, data_path)) {
std::cout << "iDRC run successfully." << std::endl;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdDRCSaveDetailFile::CmdDRCSaveDetailFile(const char* cmd_name) : TclCmd(cmd_name)
{
auto* file_path_option = new TclStringOption(TCL_PATH, 1, nullptr);
addOption(file_path_option);
}
unsigned CmdDRCSaveDetailFile::check()
{
TclOption* file_path_option = getOptionOrArg(TCL_PATH);
LOG_FATAL_IF(!file_path_option);
return 1;
}
unsigned CmdDRCSaveDetailFile::exec()
{
if (!check()) {
return 0;
}
TclOption* path_option = getOptionOrArg(TCL_PATH);
auto data_path = path_option->getStringVal();
if (iplf::tmInst->saveDrcDetailToFile(data_path)) {
std::cout << "iDRC save detail drc to file success. path = " << data_path << std::endl;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdDRCReadDetailFile::CmdDRCReadDetailFile(const char* cmd_name) : TclCmd(cmd_name)
{
auto* file_path_option = new TclStringOption(TCL_PATH, 1, nullptr);
addOption(file_path_option);
}
unsigned CmdDRCReadDetailFile::check()
{
TclOption* file_path_option = getOptionOrArg(TCL_PATH);
LOG_FATAL_IF(!file_path_option);
return 1;
}
unsigned CmdDRCReadDetailFile::exec()
{
if (!check()) {
return 0;
}
TclOption* path_option = getOptionOrArg(TCL_PATH);
auto data_path = path_option->getStringVal();
if (iplf::tmInst->readDrcDetailFromFile(data_path)) {
std::cout << "iDRC read detail file successfully." << std::endl;
}
return 1;
}
} // namespace tcl

View File

@ -1,177 +0,0 @@
// ***************************************************************************************
// 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
/**
* @File Name: tcl_placer.h
* @Brief :
* @Author : Yell (12112088@qq.com)
* @Version : 1.0
* @Creat Date : 2022-05-08
*
* @last change :zhangmz 2022-12-1
*
*/
#include <any>
#include <iostream>
#include <map>
#include <string>
// #include "DrcAPI.hpp"
#include "ScriptEngine.hh"
#include "idrc_api.h"
#include "tcl_definition.h"
using ieda::TclCmd;
using ieda::TclOption;
using ieda::TclStringOption;
namespace tcl {
class CmdDRCAutoRun : public TclCmd
{
public:
explicit CmdDRCAutoRun(const char* cmd_name);
~CmdDRCAutoRun() override = default;
unsigned check() override;
unsigned exec() override;
private:
// private function
// private data
};
class TclInitDrcAPI : public TclCmd
{
public:
explicit TclInitDrcAPI(const char* cmd_name) : TclCmd(cmd_name) {};
~TclInitDrcAPI() override = default;
unsigned check() { return 1; };
unsigned exec() override
{
if (!check()) {
return 0;
}
// idrc::DrcAPIInst.initDRC();
idrc::DrcApi drc_api;
drc_api.init();
return 1;
};
private:
// private function
// private data
};
class TclDrcCheckDef : public TclCmd
{
public:
explicit TclDrcCheckDef(const char* cmd_name);
~TclDrcCheckDef() override = default;
unsigned check() { return 1; };
unsigned exec() override;
private:
// private function
bool initConfigMapByTCL(std::map<std::string, std::any>& config_map);
void addOptionForTCL();
// private data
};
class TclDestroyDrcAPI : public TclCmd
{
public:
explicit TclDestroyDrcAPI(const char* cmd_name) : TclCmd(cmd_name) {};
~TclDestroyDrcAPI() override = default;
unsigned check() { return 1; };
unsigned exec() override
{
if (!check()) {
return 0;
}
idrc::DrcApi drc_api;
drc_api.exit();
return 1;
};
// private data
};
class TclDrcCheckNet : public TclCmd
{
public:
explicit TclDrcCheckNet(const char* cmd_name);
~TclDrcCheckNet() override = default;
unsigned check() override;
unsigned exec() override;
private:
// private function
// private data
};
class TclDrcCheckAllNet : public TclCmd
{
public:
explicit TclDrcCheckAllNet(const char* cmd_name);
~TclDrcCheckAllNet() override = default;
unsigned check() override;
unsigned exec() override;
private:
// private function
// private data
};
class CmdDRCSaveDetailFile : public TclCmd
{
public:
explicit CmdDRCSaveDetailFile(const char* cmd_name);
~CmdDRCSaveDetailFile() override = default;
unsigned check() override;
unsigned exec() override;
private:
// private function
// private data
};
class CmdDRCReadDetailFile : public TclCmd
{
public:
explicit CmdDRCReadDetailFile(const char* cmd_name);
~CmdDRCReadDetailFile() override = default;
unsigned check() override;
unsigned exec() override;
private:
// private function
// private data
};
} // namespace tcl

View File

@ -1,72 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "idm.h"
#include "tcl_drc.h"
namespace tcl {
TclDrcCheckNet::TclDrcCheckNet(const char* cmd_name) : TclCmd(cmd_name)
{
auto* file_name_option = new TclStringOption(TCL_NAME, 1, nullptr);
addOption(file_name_option);
}
unsigned TclDrcCheckNet::check()
{
TclOption* file_name_option = getOptionOrArg(TCL_NAME);
LOG_FATAL_IF(!file_name_option);
return 1;
}
unsigned TclDrcCheckNet::exec()
{
if (!check()) {
return 0;
}
TclOption* option = getOptionOrArg(TCL_NAME);
if (option != nullptr) {
std::string net_name = option->getStringVal();
dmInst->isNetConnected(net_name);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TclDrcCheckAllNet::TclDrcCheckAllNet(const char* cmd_name) : TclCmd(cmd_name)
{
}
unsigned TclDrcCheckAllNet::check()
{
return 1;
}
unsigned TclDrcCheckAllNet::exec()
{
if (!check()) {
return 0;
}
auto result = dmInst->isAllNetConnected();
return 1;
}
} // namespace tcl

View File

@ -1,50 +0,0 @@
// ***************************************************************************************
// 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
/**
* @File Name: tcl_register.h
* @Brief :
* @Author : Yell (12112088@qq.com)
* @Version : 1.0
* @Creat Date : 2022-04-15
*
*/
#include "ScriptEngine.hh"
#include "UserShell.hh"
#include "tcl_drc.h"
using namespace ieda;
namespace tcl {
int registerCmdDRC()
{
registerTclCmd(CmdDRCAutoRun, "run_drc");
registerTclCmd(CmdDRCSaveDetailFile, "save_drc");
registerTclCmd(CmdDRCReadDetailFile, "read_drc");
registerTclCmd(TclDrcCheckDef, "drc_check_def");
registerTclCmd(TclInitDrcAPI, "init_drc_api");
registerTclCmd(TclDestroyDrcAPI, "destroy_drc_api");
registerTclCmd(TclDrcCheckNet, "check_net");
registerTclCmd(TclDrcCheckAllNet, "check_all_net");
return EXIT_SUCCESS;
}
} // namespace tcl

View File

@ -44,6 +44,9 @@ TclInitRT::TclInitRT(const char* cmd_name) : TclCmd(cmd_name)
unsigned TclInitRT::exec()
{
if (!check()) {
return 0;
}
std::map<std::string, std::any> config_map = TclUtil::getConfigMap(this, _config_list);
RTI.initRT(config_map);
return 1;

View File

@ -33,7 +33,7 @@
#include "tcl_flow.h"
#include "tcl_register_config.h"
#include "tcl_register_cts.h"
#include "tcl_register_drc.h"
#include "tcl_register_idrc.h"
#include "tcl_register_eco.h"
#include "tcl_register_eval.h"
#include "tcl_register_feature.h"

View File

@ -1,5 +1,4 @@
# add_subdirectory(iDRC)
add_subdirectory(iDRCPro)
add_subdirectory(iDRC)
add_subdirectory(iECO)
add_subdirectory(iFP)
add_subdirectory(iIR)

View File

@ -0,0 +1,51 @@
# ***************************************************************************************
# 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.
# ***************************************************************************************
---
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 160
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
DerivePointerAlignment: false
SpaceAfterCStyleCast: true
Standard: c++20

View File

@ -1,19 +1,44 @@
include(${HOME_CMAKE}/operation/idb.cmake)
include(${HOME_CMAKE}/operation/iplf.cmake)
message(STATUS "")
message(STATUS "############## DRC: STADRC CMAKE ##############")
include(cmake/external_lib.cmake)
include(cmake/idrc_api_external_lib.cmake)
############################ cmake flag ############################
add_subdirectory(api)
add_subdirectory(source)
# add_subdirectory(test)
set(CMAKE_CXX_STANDARD 20)
# ADD_COMPILE_OPTIONS("-Wconversion")
# ADD_COMPILE_OPTIONS("-fsanitize=address")
# LINK_LIBRARIES("-fsanitize=address")
# ADD_EXECUTABLE(run_drc ${IDRC_TESTS}/run_drc.cpp)
# TARGET_LINK_LIBRARIES(run_drc DRC)
############################ debug interface ############################
# ADD_EXECUTABLE(conflict_graph ${IDRC_TESTS}/conflict_graph.cpp)
# TARGET_LINK_LIBRARIES(conflict_graph DRC)
# set(DEBUG_IDRC_INTERFACE ON)
# add_executable(test_boost ${IDRC_TESTS}/test_boost.cpp)
# target_link_libraries(test_boost DRC)
############################ debug source data_manager ############################
# set(DEBUG_IDRC_DATA_MANAGER ON)
############################ debug source module ############################
# set(DEBUG_IDRC_MODULE ON)
############################ debug source utility ############################
# set(DEBUG_IDRC_LOGGER ON)
# set(DEBUG_IDRC_MONITOR ON)
# set(DEBUG_IDRC_UTILITY ON)
############################ setting path ############################
set(HOME_IDRC ${HOME_OPERATION}/iDRC)
set(IDRC_INTERFACE ${HOME_IDRC}/interface)
set(IDRC_SOURCE ${HOME_IDRC}/source)
############################ cmake subdirectory ############################
add_subdirectory(${IDRC_INTERFACE})
add_subdirectory(${IDRC_SOURCE})
########################################################
message(STATUS "############## DRC: END CMAKE ##############\n")

View File

@ -1,86 +0,0 @@
# iDRC 功能文档
## 一、概述
iDRC是iEDA工具链中的设计规则检查工具目前支持28nm工艺下各Metal层与Cut层的设计规则检查。主要实现的设计规则检查包括短路违规检查、金属最小间距检查、最小宽度检查、最小面积检查、孔洞面积检查、最小步长MinStep检查、通孔包围Enclosure相关检查、金属最小线端EOL间隔检查、金属最小凹槽Notch间隔检查、金属最小Jog间隔检查、金属最小CornerFill间隔检查、Cut层最小间隔相关检查。
## 二、支持的检查类型
### Shape类型规则
实现针对非Spacing类型规则的检查主要包括MinStep、Width、Area、Enclosure相关规则的检查
| 检查类型 | 介绍 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 最小步长MinStep规则 | 该规则要求金属线外边缘不可以有超过 TechFile 限定个数的边长小于TechFile规定值的连续边如图1.1所示 |
| 通孔包围Enclosure规则 | 通孔包围规则规定了某一个Cut上下层的金属包围与Cut边缘的最小距离超过这些距离会发生Enclosure违例如图1.2所示 |
| 最小宽度规则 | 最小宽度规则是用于约束版图中导体图形的内边间距(Distance of interior facing edge)如图1.3(a)所示它规定了导体图形的内边间距不得小于TechFile规定的最小宽度参数值包括导体的长度导体的宽度导体的内对角宽度如下图1.3中(b),(c),(d)所示。 |
| 最小面积规则 |最小面积规则规定了各个工艺层的导体面积不能小于TechFile中指定的最小面积参参数值如下图1.4左图中的Area示意 |
| 最小孔洞面积规则 | 最小包围面积规定了由导体环绕包围形成的孔洞面积不能小于TechFile指定的最小面积参数值如下图1.4右图中的Enclosed Area示意。 |
<div align=center> <img src="doc/md/图片/minstep.png" style="zoom:80%;" />
图1.1 最小步长规则对应的检查对象
<div align=center> <img src="doc/md/图片/enclosure.png" style="zoom:60%;" />
图1.2 通孔包围规则对应的检查对象
<div align=center> <img src="doc/md/图片/图片1.3.png" style="zoom:60%;" />
图1.3 导体图形的内边间距(最小宽度规则对应的检查对象)
<div align=center> <img src="doc/md/图片/图片1.4.png" style="zoom:50%;" />
图1.4 左图为导体图形的面积(最小面积规则对应的检查对象)
右图为导体图形包围形成的孔洞面积(最小包围面积规则对应的检查对象)
### Spacing类型规则
| 名词 | 名词解释 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 短路违规 | 当所属不同线网的导体几何图形产生任何形式的交叠,都会产生短路,比如,所属不同线网的线段(Wire)所属不同线网的Pin和通孔Via线网图形和障碍物Block它们之间的触碰都是不允许的都被视为短路违规如下图1.5所示。 |
| 金属最小间距规则 | 最小间距规则可以理解为版图中导体图形间的外边间距(Distance of exterior facing edge)不得小于TechFile中规定的当前工艺层的最小间距参数值,导体间的外边间距如下图1.2(a)所示间距规则包括检查导体间X方向的间距Y方向间距与角间距如图1.6所示。 |
| 金属最小线端EOL间隔规则 | 该规则要求在TechFile中要求的金属线末端的区域内不可以有其他的金属线与该区域产生交叠区域的可能大小受到线端边EOL的邻接边长度、附近是否有通孔以及相邻金属线等因素影响如图1.7所示。 |
| 金属最小凹槽Notch间隔规则 | 该规则要求在符合TechFile规定条件的由金属线形成凹槽区域中凹槽的底部长度不得小于规定值如图1.8所示。 |
| 金属最小Jog间隔规则 | 该规则要求在一个较宽金属线与其邻近的Parallel Run Length长度符合 TechFile要求的金属线之间存在的某些特定的金属之间的间隔要求如图1.9所示。 |
| 金属最小CornerFill间隔规则 | 该规则要求在金属线外边缘存在符合TechFile要求的拐角处缺口型区域时在该缺口处虚拟出一块金属检查该虚拟出的金属与其他金属的间隔如图1.10所示。 |
| Cut最小间隔规则 | 该规则要求同一Cut层中的任何两个Cut之间的间隔不能小于规定值,Cut层的Spacing计算虽然一般默认为edge-to-edge的欧式距离但有些情况下会因为规则中的某些字段而发生改变某些情况下会以两者在X、Y方向上的最大投影长度来代替欧式距离来计算Spacing如图1.11所示。 |
<div align=center> <img src="doc/md/图片/图片1.1.png" style="zoom:80%;" />
图1.5 短路违规情况
<div align=center> <img src="doc/md/图片/图1.2.png" style="zoom:80%;" />
图1.6 导体图形外边间距示意图(最小间距规则对应检查对象)
<div align=center> <img src="doc/md/图片/EOL.png" style="zoom:80%;" />
图1.7 金属最小线端EOL间隔规则对应的检查对象
<div align=center> <img src="doc/md/图片/notch.png" style="zoom:80%;" />
图1.8 金属最小凹槽Notch间隔规则对应的检查对象
<div align=center> <img src="doc/md/图片/jog.png" style="zoom:50%;" />
图1.9 金属最小Jog间隔规则对应的检查对象
<div align=center> <img src="doc/md/图片/corner_fill.png" style="zoom:50%;" />
图1.10 金属最小CornerFill间隔规则对应的检查对象
<div align=center> <img src="doc/md/图片/cut_spacing.png" style="zoom:100%;" />
图1.11 Cut最小间隔规则对应的检查对象
## 设计需求和目标
> *描述需求和目标。*
* **iDRC需要支持读入DEF文件进行设计规则检查** 在EDA工具链中DEF文件在衔接不同工具间流程和数据交换过程中扮演着一个重要角色作为一个DRC工具应该支持读入DEF文件进行DRC检查的应用场景。 iDRC通过iDB读入DEF文件和相关LEF文件获得版图的图形信息和工艺规则信息基于DEF与LEF的数据信息实现支持28nm工艺规则的各类型检查。
* **iDRC需要支持与iRT交互的设计规则检查模式** 设计规则检查结果对于绕线工具iRT而言是一个重要的的评估基于设计规则检查结果iRT可以对绕线结果进行优化迭代所以iDRC应该提供与iRT的交互接口iDRC应该支持从iRT绕线结果进行设计规则检查并把检查结果反馈给iRT的运转流程。
## 检查结果报告
iDRC提供全局报告与详细报告两种形式的报告文件全局报告文件以文本形式给出包含各类规则的违例个数详细报告文件包含了每个违例的详细信息违例的标注框标注出违例在版图上的具体位置、违例的类型、层信息等支持使用可视化界面读取查看。

View File

@ -1,27 +0,0 @@
add_library(idrc_api
DrcAPI.cpp
)
target_include_directories(idrc_api
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${HOME_OPERATION}/iDRC/source
${HOME_OPERATION}/iDRC/source/data/basic
)
target_link_libraries(idrc_api
PUBLIC
idrc_db
PRIVATE
idrc_config
idrc_src
idrc_api_external_lib
idrc_multi_pattern
idrc_region_query
idrc_shape_check
idrc_spacing_check
idrc_spot_parser
)

View File

@ -1,983 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DrcAPI.hpp"
#include "CornerFillSpacingCheck.hpp"
#include "CutEolSpacingCheck.hpp"
#include "CutSpacingCheck.hpp"
#include "DrcIDBWrapper.h"
#include "EOLSpacingCheck.hpp"
#include "EnclosedAreaCheck.h"
#include "EnclosureCheck.hpp"
#include "JogSpacingCheck.hpp"
#include "MinStepCheck.hpp"
#include "NotchSpacingCheck.hpp"
#include "RoutingAreaCheck.h"
#include "RoutingSpacingCheck.h"
#include "RoutingWidthCheck.h"
#include "idm.h"
using namespace std;
namespace idrc {
DrcAPI* DrcAPI::_drc_api_instance = nullptr;
void DrcAPI::destroyInst()
{
if (_drc_api_instance != nullptr) {
delete _drc_api_instance;
_drc_api_instance = nullptr;
}
}
// function
void DrcAPI::initDRC()
{
delete _tech;
_tech = new Tech();
if (dmInst->get_idb_builder()) {
_idb_wrapper = new DrcIDBWrapper(_tech, dmInst->get_idb_builder());
_idb_wrapper->wrapTech();
} else {
std::cout << "Error: idb builder is null" << std::endl;
exit(1);
}
}
RegionQuery* DrcAPI::init()
{
RegionQuery* region_query = new RegionQuery(_tech);
return region_query;
}
void DrcAPI::destroy(RegionQuery* region_query)
{
}
std::map<std::string, int> DrcAPI::getCheckResult()
{
runDrc();
return DrcInst.getDrcResult();
}
void DrcAPI::runDrc()
{
DrcInst.initDRC();
DrcInst.initCheckModule();
DrcInst.run();
}
std::map<std::string, std::vector<DrcViolationSpot*>> DrcAPI::getDetailCheckResult()
{
// DrcInst.initDRC();
// DrcInst.initCheckModule();
// DrcInst.run();
return DrcInst.getDrcDetailResult();
}
std::map<std::string, int> DrcAPI::getCheckResult(RegionQuery* region_query)
{
RoutingSpacingCheck* routing_spacing_check = new RoutingSpacingCheck(_tech, region_query);
EOLSpacingCheck* eol_spacing_check = new EOLSpacingCheck(_tech, region_query);
NotchSpacingCheck* notch_spacing_check = new NotchSpacingCheck(_tech, region_query);
RoutingWidthCheck* width_check = new RoutingWidthCheck(_tech, region_query);
MinStepCheck* min_step_check = new MinStepCheck(_tech, region_query);
RoutingAreaCheck* area_check = new RoutingAreaCheck(_tech, region_query);
CornerFillSpacingCheck* corner_fill_spacing_check = new CornerFillSpacingCheck(_tech, region_query);
CutSpacingCheck* cut_spacing_check = new CutSpacingCheck(_tech, region_query);
CutEolSpacingCheck* cut_eol_spacing_check = new CutEolSpacingCheck(_tech, region_query);
EnclosureCheck* enclosure_check = new EnclosureCheck(_tech, region_query);
// EnclosedAreaCheck* enclosed_area_check = new EnclosedAreaCheck(_tech, region_query);
auto routing_rect_set = region_query->getRoutingRectSet();
auto cut_rect_set = region_query->getCutRectSet();
for (auto routing_rect : routing_rect_set) {
routing_spacing_check->check(routing_rect);
width_check->check(routing_rect);
}
for (auto cut_rect : cut_rect_set) {
cut_eol_spacing_check->check(cut_rect);
cut_spacing_check->check(cut_rect);
enclosure_check->check(cut_rect);
}
auto layer_id_and_net_id_to_polys_map = region_query->getRegionPolysMap();
for (auto& [layer_id, net_id_to_polys_map] : layer_id_and_net_id_to_polys_map) {
for (auto [net_id, polys_set] : net_id_to_polys_map) {
for (auto& poly : polys_set) {
eol_spacing_check->check(poly);
notch_spacing_check->check(poly);
min_step_check->check(poly);
area_check->check(poly);
corner_fill_spacing_check->check(poly);
}
}
}
std::map<std::string, int> viotype_to_nums_map;
region_query->getRegionReport(viotype_to_nums_map);
return viotype_to_nums_map;
}
// void DrcAPI::add(std::vector<ids::DRCTask> task_list)
// {
// for (auto& [region_query, drc_rect_list] : task_list) {
// std::set<DrcPoly*> intersect_poly_set;
// // Get all polygons intersecting with this set of rectangles.
// region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
// // Delete all polygons that intersect with this group of rectangles
// region_query->deleteIntersectPoly(intersect_poly_set);
// DrcPoly* new_poly = region_query->rebuildPoly_add(intersect_poly_set, drc_rect_list);
// if (new_poly) {
// region_query->addPoly(new_poly);
// }
// for (auto& drc_rect : drc_rect_list) {
// region_query->addDrcRect(drc_rect, _tech);
// }
// }
// }
void DrcAPI::add(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list)
{
std::vector<DrcRect*>& region_rect_list = region_query->getRegionRectList();
region_rect_list.insert(region_rect_list.end(), drc_rect_list.begin(), drc_rect_list.end());
std::set<DrcPoly*> intersect_poly_set;
// Get all polygons that intersect with this group of rectangles
region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
// Delete all polygons that intersect with this group of rectangles
region_query->deleteIntersectPoly(intersect_poly_set);
// DrcPoly* new_poly = region_query->rebuildPoly_add(intersect_poly_set, drc_rect_list);
// if (new_poly) {
// region_query->addPoly(new_poly);
// }
// for (auto& drc_rect : drc_rect_list) {
// region_query->addDrcRect(drc_rect, _tech);
// }
auto new_poly_list = region_query->rebuildPoly_add_list(intersect_poly_set, drc_rect_list);
for (auto new_poly : new_poly_list) {
if (new_poly) {
region_query->addPoly(new_poly);
}
for (auto& drc_rect : drc_rect_list) {
region_query->addDrcRect(drc_rect, _tech);
}
}
}
// void DrcAPI::mergeRectToPoly(DrcRect* check_rect, RegionQuery* region_query, DrcPoly* poly)
// {
// std::vector<std::pair<RTreeBox, DrcRect*>> query_result;
// int layer_id = check_rect->get_layer_id();
// region_query->queryInRoutingLayer(layer_id, DRCUtil::getRTreeBox(check_rect), query_result);
// }
bool DrcAPI::checkSpacing_rect(DrcRect* check_rect, RegionQuery* region_query)
{
RoutingSpacingCheck* routing_spacing_check = new RoutingSpacingCheck(_tech, region_query);
if (!routing_spacing_check->check(check_rect)) {
delete routing_spacing_check;
return false;
}
std::set<DrcPoly*> intersect_poly_set;
std::vector<DrcRect*> drc_rect_list;
drc_rect_list.push_back(check_rect);
region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
DrcPoly* poly = region_query->rebuildPoly_add(intersect_poly_set, drc_rect_list);
/// 无法构建成 1 个poly无法检测暂时忽略处理
if (poly == nullptr) {
return true;
}
// 给poly build edge
region_query->addPolyEdge_NotAddToRegion(poly);
EOLSpacingCheck* eol_spacing_check = new EOLSpacingCheck(_tech, region_query);
if (!eol_spacing_check->check(poly)) {
delete eol_spacing_check;
return false;
}
CornerFillSpacingCheck* corner_fill_check = new CornerFillSpacingCheck(_tech, region_query);
if (!corner_fill_check->check(poly)) {
delete corner_fill_check;
return false;
}
delete routing_spacing_check;
delete eol_spacing_check;
delete corner_fill_check;
return true;
}
bool DrcAPI::checkSpacing(RegionQuery* region_query, DrcRect* check_rect)
{
std::vector<std::pair<RTreeBox, DrcRect*>> rect_query_result;
std::vector<std::pair<RTreeSegment, DrcEdge*>> edge_query_result;
int layer_id = check_rect->get_layer_id();
region_query->queryEdgeInRoutingLayer(layer_id, DRCUtil::getRTreeBox(check_rect), edge_query_result);
region_query->queryInRoutingLayer(layer_id, DRCUtil::getRTreeBox(check_rect), rect_query_result);
std::map<void*, std::map<ScopeType, std::vector<DrcRect*>>> max_scope_query_result;
region_query->queryInMaxScope(layer_id, DRCUtil::getRTreeBox(check_rect), max_scope_query_result);
std::map<void*, std::map<ScopeType, std::vector<DrcRect*>>> min_scope_query_result;
region_query->queryInMinScope(layer_id, DRCUtil::getRTreeBox(check_rect), min_scope_query_result);
// Exclude intersections with poly. Directly query edges and rectangles from rect, remove those belonging to the same net. For different nets, report a short circuit violation. Then, remove these edges and rectangles from min and max.
for (auto [rtree_seg, edge] : edge_query_result) {
min_scope_query_result.erase(edge);
max_scope_query_result.erase(edge);
if (edge->get_owner_polygon()->getNetId() != check_rect->get_net_id()) {
return false;
}
}
for (auto [rtree_box, rect] : rect_query_result) {
min_scope_query_result.erase(rect);
max_scope_query_result.erase(rect);
if (rect->get_net_id() != check_rect->get_net_id()) {
return false;
}
}
bool intersect_with_min_scope = !min_scope_query_result.empty();
bool intersect_with_max_scope = !max_scope_query_result.empty();
if (intersect_with_min_scope) {
return false;
} else if (intersect_with_max_scope) {
for (auto [target, scope_type_set] : max_scope_query_result) {
if (scope_type_set.contains(ScopeType::EOL)) {
EOLSpacingCheck* eol_spacing_check = new EOLSpacingCheck(_tech, region_query);
if (!eol_spacing_check->check(target, check_rect)) {
delete eol_spacing_check;
return false;
}
delete eol_spacing_check;
}
if (scope_type_set.contains(ScopeType::CornerFill)) {
return false;
}
if (scope_type_set.contains(ScopeType::Common)) {
RoutingSpacingCheck* routing_spacing_check = new RoutingSpacingCheck(_tech, region_query);
if (!routing_spacing_check->check(target, check_rect)) {
delete routing_spacing_check;
return false;
}
delete routing_spacing_check;
}
}
} else {
// Use rect as the main subject for checking, merge into poly, following the same process as the DEF file check.
return checkSpacing_rect(check_rect, region_query);
}
return true;
}
bool DrcAPI::checkShape(RegionQuery* region_query, DrcRect* check_rect)
{
RoutingWidthCheck* width_check = new RoutingWidthCheck(_tech, region_query);
if (!width_check->check(check_rect)) {
delete width_check;
return false;
}
std::set<DrcPoly*> intersect_poly_set;
std::vector<DrcRect*> drc_rect_list;
drc_rect_list.push_back(check_rect);
region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
DrcPoly* poly = region_query->rebuildPoly_add(intersect_poly_set, drc_rect_list);
NotchSpacingCheck* notch_spacing_check = new NotchSpacingCheck(_tech, region_query);
if (!notch_spacing_check->check(poly)) {
delete notch_spacing_check;
return false;
}
MinStepCheck* min_step_check = new MinStepCheck(_tech, region_query);
if (!min_step_check->check(poly)) {
delete min_step_check;
return false;
}
RoutingAreaCheck* area_check = new RoutingAreaCheck(_tech, region_query);
if (!area_check->check(poly)) {
delete area_check;
return false;
}
delete width_check;
delete notch_spacing_check;
delete min_step_check;
delete area_check;
return true;
}
// bool DrcAPI::check(std::vector<ids::DRCTask> task_list)
// {
// for (auto& [region_query, drc_rect_list] : task_list) {
// for (auto& drc_rect : drc_rect_list) {
// if (!checkSpacing(region_query, drc_rect)) {
// return false;
// }
// if (!checkShape(region_query, drc_rect)) {
// return false;
// }
// // checkMinimumCut(drc_rect);
// }
// }
// return true;
// }
bool DrcAPI::check(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list)
{
for (auto& drc_rect : drc_rect_list) {
if (!checkSpacing(region_query, drc_rect)) {
return false;
}
if (!checkShape(region_query, drc_rect)) {
return false;
}
// checkMinimumCut(drc_rect);
}
return true;
}
// void DrcAPI::del(std::vector<ids::DRCTask> task_list)
// {
// for (auto& [region_query, drc_rect_list] : task_list) {
// std::set<DrcPoly*> intersect_poly_set;
// region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
// region_query->deleteIntersectPoly(intersect_poly_set);
// auto new_poly_list = region_query->rebuildPoly_del(intersect_poly_set, drc_rect_list);
// if (!new_poly_list.empty()) {
// region_query->addPolyList(new_poly_list);
// }
// for (auto& drc_rect : drc_rect_list) {
// region_query->removeDrcRect(drc_rect);
// }
// }
// }
void DrcAPI::del(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list)
{
// std::set<DrcPoly*> intersect_poly_set;
// region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
// region_query->deleteIntersectPoly(intersect_poly_set);
// auto new_poly_list = region_query->rebuildPoly_del(intersect_poly_set, drc_rect_list);
// if (!new_poly_list.empty()) {
// region_query->addPolyList(new_poly_list);
// }
// for (auto& drc_rect : drc_rect_list) {
// region_query->removeDrcRect(drc_rect);
// }
std::set<DrcPoly*> intersect_poly_set;
region_query->getIntersectPoly(intersect_poly_set, drc_rect_list);
for (auto& drc_rect : drc_rect_list) {
region_query->removeDrcRect(drc_rect);
}
if (!intersect_poly_set.empty()) {
std::vector<DrcPoly*> intersect_poly_list;
intersect_poly_list.assign(intersect_poly_set.begin(), intersect_poly_set.end());
region_query->addPolyList(intersect_poly_list);
}
}
// RegionQuery* DrcAPI::createRTree(ids::DRCEnv env)
// {
// RegionQuery* region_query = new RegionQuery();
// initRegionQuery(env, region_query);
// return region_query;
// }
void DrcAPI::initNets(std::vector<DrcRect*>& drc_rect_list, std::map<int, DrcNet>& nets)
{
for (auto& target_drc_rect : drc_rect_list) {
int net_id = target_drc_rect->get_net_id();
int layer_id = target_drc_rect->get_layer_id();
nets[net_id].set_net_id(net_id);
if (target_drc_rect->get_owner_type() == RectOwnerType::kViaCut) {
nets[net_id].add_cut_rect(layer_id, target_drc_rect);
} else {
if (target_drc_rect->get_owner_type() == RectOwnerType::kBlockage) {
continue;
} else {
nets[net_id].add_routing_rect(layer_id, target_drc_rect);
int lb_x = target_drc_rect->get_left();
int lb_y = target_drc_rect->get_bottom();
int rt_x = target_drc_rect->get_right();
int rt_y = target_drc_rect->get_top();
BoostRect boost_rect(lb_x, lb_y, rt_x, rt_y);
nets[net_id].add_routing_rect(layer_id, boost_rect);
}
}
}
}
void DrcAPI::initPoly(std::map<int, DrcNet>& nets, RegionQuery* region_query)
{
for (auto& net_pair : nets) {
initPolyPolygon(&net_pair.second);
initPolyEdges(&net_pair.second, region_query);
// initPolyCorners(&net);
}
}
// bool DrcAPI::checkDRC(std::vector<DrcRect*> origin_rect_list)
// {
// // init RectRTreeMap
// // LayerIdToRTreeMap* region_query = new LayerIdToRTreeMap();
// RegionQuery* region_query = new RegionQuery();
// initRegionQuery(origin_rect_list, region_query);
// std::map<int, DrcNet> nets;
// initNets(origin_rect_list, nets);
// initPoly(nets, region_query);
// // TODO EdgeRtreeMap
// // init check module
// // RoutingSpacingCheck* routing_spacing_check = new RoutingSpacingCheck(_tech, region_query);
// // EOLSpacingCheck* eol_spacing_check = new EOLSpacingCheck(_tech, region_query);
// // NotchSpacingCheck* notch_spacing_check = new NotchSpacingCheck(_tech, region_query);
// // RoutingWidthCheck* width_check = new RoutingWidthCheck(_tech, region_query);
// // MinStepCheck* min_step_check = new MinStepCheck(_tech);
// // RoutingAreaCheck* area_check = new RoutingAreaCheck(_tech);
// // CornerFillSpacingCheck* corner_fill_spacing_check = new CornerFillSpacingCheck(_tech, region_query);
// // CutSpacingCheck* cut_spacing_check = new CutSpacingCheck(_tech, region_query);
// // CutEolSpacingCheck* cut_eol_spacing_check = new CutEolSpacingCheck(_tech, region_query);
// // EnclosureCheck* enclosure_check = new EnclosureCheck(_tech, region_query);
// bool res = true;
// for (auto& target_drc_rect : origin_rect_list) {
// if (!cut_spacing_check->check(target_drc_rect)) {
// return false;
// }
// }
// // for (auto& net : nets) {
// // if (!corner_fill_spacing_check->check(&net.second)) {
// // res = false;
// // break;
// // }
// // if (!min_step_check->check(&net.second)) {
// // res = false;
// // break;
// // }
// // if (!eol_spacing_check->check(&net.second)) {
// // res = false;
// // break;
// // }
// // if (!notch_spacing_check->check(&net.second)) {
// // res = false;
// // break;
// // }
// // if (!width_check->check(&net.second)) {
// // res = false;
// // break;
// // }
// // }
// // delete region_query;
// // // delete area_check;
// // // delete min_step_check;
// // // delete routing_spacing_check;
// // // delete eol_spacing_check;
// // // delete corner_fill_spacing_check;
// return res;
// }
RTreeBox DrcAPI::getRTreeBox(DrcRect* rect)
{
RTreePoint leftBottom(rect->get_left(), rect->get_bottom());
RTreePoint rightTop(rect->get_right(), rect->get_top());
return RTreeBox(leftBottom, rightTop);
}
// void DrcAPI::initSpacingRegion(ids::DRCEnv env, RegionQuery* region_query)
// {
// for (auto& env_rect : env) {
// DrcRect* drc_rect = getDrcRect(env_rect);
// int layer_id = drc_rect->get_layer_id();
// if (env_rect.type == ids::RectType::kCut) {
// region_query->add_cut_rect_to_rtree(layer_id, drc_rect);
// } else {
// // add to origin rtree
// region_query->add_routing_rect_to_rtree(layer_id, drc_rect);
// // add common spacing region to region rtree
// addCommonSpacingRegion(drc_rect, region_query);
// }
// }
// // add EOL and Corner_Fill Spacing region to region rtree
// for (auto& [layer_id, net] : region_query->get_nets_map()) {
// for (auto& [layer_id, target_polys] : net.get_route_polys_list()) {
// for (auto& target_poly : target_polys) {
// addEOLSpacingRegion(target_poly.get(), region_query);
// addCornerFillSpacingRegion();
// removeEOLSpacingRegion();
// removeCornerFillSpacingRegion();
// }
// }
// }
// }
// void DrcAPI::initRegionQuery(ids::DRCEnv env, RegionQuery* region_query)
// {
// initNets(env, region_query->get_nets_map());
// initPoly(region_query->get_nets_map(), region_query);
// initSpacingRegion(env, region_query);
// }
// void DrcAPI::getCommonSpacingMinRegion(DrcRect* common_spacing_min_region, DrcRect* drc_rect)
// {
// int layer_id = drc_rect->get_layer_id();
// int net_id = drc_rect->get_net_id();
// int spacing = _tech->get_drc_routing_layer_list()[layer_id]->get_spacing_table()->get_parallel()->get_spacing(0, 0);
// int lb_x = drc_rect->get_left() - spacing;
// int lb_y = drc_rect->get_bottom() - spacing;
// int rt_x = drc_rect->get_right() + spacing;
// int rt_y = drc_rect->get_top() + spacing;
// common_spacing_min_region->set_coordinate(lb_x, lb_y, rt_x, rt_y);
// common_spacing_min_region->set_owner_type(RectOwnerType::kCommonRegion);
// common_spacing_min_region->set_net_id(net_id);
// common_spacing_min_region->set_connection(drc_rect);
// drc_rect->set_connection(common_spacing_min_region);
// }
// void DrcAPI::getCommonSpacingMaxRegion(DrcRect* common_spacing_min_region, DrcRect* drc_rect)
// {
// int layer_id = drc_rect->get_layer_id();
// int net_id = drc_rect->get_net_id();
// int width = drc_rect->getWidth();
// int length = drc_rect->getLength();
// int spacing = _tech->get_drc_routing_layer_list()[layer_id]->get_spacing_table()->get_parallel()->get_spacing(width, length);
// int lb_x = drc_rect->get_left() - spacing;
// int lb_y = drc_rect->get_bottom() - spacing;
// int rt_x = drc_rect->get_right() + spacing;
// int rt_y = drc_rect->get_top() + spacing;
// common_spacing_min_region->set_coordinate(lb_x, lb_y, rt_x, rt_y);
// common_spacing_min_region->set_owner_type(RectOwnerType::kCommonRegion);
// common_spacing_min_region->set_net_id(net_id);
// common_spacing_min_region->set_connection(drc_rect);
// drc_rect->set_connection(common_spacing_min_region);
// }
// void DrcAPI::addCommonSpacingRegion(DrcRect* drc_rect, RegionQuery* region_query)
// {
// DrcRect* common_spacing_min_region = new DrcRect();
// getCommonSpacingMinRegion(common_spacing_min_region, drc_rect);
// region_query->add_spacing_min_region(common_spacing_min_region);
// DrcRect* common_spacing_max_region = new DrcRect();
// getCommonSpacingMaxRegion(common_spacing_max_region, drc_rect);
// region_query->add_spacing_max_region(common_spacing_max_region);
// }
// void DrcAPI::getEOLSpacingMinRegion(std::vector<DrcRect*> eol_spacing_min_region_list, DrcPoly* drc_poly)
// {
// }
// void DrcAPI::addEOLSpacingRegion(DrcPoly* drc_poly, RegionQuery* region_query)
// {
// std::vector<DrcRect*> eol_spacing_min_region_list;
// getEOLSpacingMinRegion(eol_spacing_min_region_list, drc_poly);
// region_query->add_spacing_min_region(eol_spacing_min_region_list);
// std::vector<DrcRect*> eol_spacing_max_region_list;
// getEOLSpacingMaxRegion(eol_spacing_max_region_list, drc_poly);
// region_query->add_spacing_max_region(eol_spacing_max_region_list);
// }
void DrcAPI::initRegionQuery(std::vector<DrcRect*> origin_rect_list, RegionQuery* region_query)
{
for (auto& drc_rect : origin_rect_list) {
int layer_id = drc_rect->get_layer_id();
if (drc_rect->get_owner_type() == RectOwnerType::kViaCut) {
region_query->add_cut_rect_to_rtree(layer_id, drc_rect);
} else {
region_query->add_routing_rect_to_rtree(layer_id, drc_rect);
}
}
}
void DrcAPI::initPolyEdges(DrcNet* net, RegionQuery* region_query)
{
int routing_layer_num = _tech->get_drc_routing_layer_list().size();
// test_eol
// int routing_layer_num = 1;
// std::vector<std::set<std::pair<DrcCoordinate<int>, DrcCoordinate<int>>>> polygons_edges(routing_layer_num);
// Assign the edges of the fused polygon to the edges in the poly
for (int i = 0; i < routing_layer_num; i++) {
for (auto& poly : net->get_route_polys(i)) {
auto polygon = poly->getPolygon();
initPolyOuterEdges(net, poly.get(), polygon, i, region_query);
// pending
for (auto holeIt = polygon->begin_holes(); holeIt != polygon->end_holes(); holeIt++) {
auto& hole_poly = *holeIt;
initPolyInnerEdges(net, poly.get(), hole_poly, i, region_query);
}
}
}
}
void DrcAPI::initPolyOuterEdges(DrcNet* net, DrcPoly* poly, DrcPolygon* polygon, int layer_id, RegionQuery* region_query)
{
DrcCoordinate bp(-1, -1), ep(-1, -1), firstPt(-1, -1);
BoostPoint bp1, ep1, firstPt1;
std::vector<std::unique_ptr<DrcEdge>> tmpEdges;
// skip the first pt
auto outerIt = polygon->begin();
bp.set((*outerIt).x(), (*outerIt).y());
bp1 = *outerIt;
firstPt.set((*outerIt).x(), (*outerIt).y());
firstPt1 = *outerIt;
outerIt++;
// loop from second to last pt (n-1) edges
for (; outerIt != polygon->end(); outerIt++) {
ep.set((*outerIt).x(), (*outerIt).y());
ep1 = *outerIt;
// auto edge = make_unique<DrcEdge>();
std::unique_ptr<DrcEdge> edge(new DrcEdge);
edge->set_layer_id(layer_id);
edge->addToPoly(poly);
edge->addToNet(net);
// edge->setPoints(bp, ep);
edge->setSegment(bp1, ep1);
edge->setDir();
edge->set_is_fixed(false);
if (region_query) {
region_query->add_routing_edge_to_rtree(layer_id, edge.get());
}
if (!tmpEdges.empty()) {
edge->setPrevEdge(tmpEdges.back().get());
tmpEdges.back()->setNextEdge(edge.get());
}
tmpEdges.push_back(std::move(edge));
bp.set(ep);
bp1 = ep1;
}
// last edge
auto edge = make_unique<DrcEdge>();
edge->set_layer_id(layer_id);
edge->addToPoly(poly);
edge->addToNet(net);
// edge->setPoints(bp, firstPt);
edge->setSegment(bp1, firstPt1);
edge->setDir();
edge->set_is_fixed(false);
edge->setPrevEdge(tmpEdges.back().get());
tmpEdges.back()->setNextEdge(edge.get());
// set first edge
tmpEdges.front()->setPrevEdge(edge.get());
edge->setNextEdge(tmpEdges.front().get());
if (region_query) {
region_query->add_routing_edge_to_rtree(layer_id, edge.get());
}
tmpEdges.push_back(std::move(edge));
// add to polygon edges
poly->addEdges(tmpEdges);
}
void DrcAPI::initPolyInnerEdges(DrcNet* net, DrcPoly* poly, const BoostPolygon& hole_poly, int layer_id, RegionQuery* region_query)
{
DrcCoordinate bp(-1, -1), ep(-1, -1), firstPt(-1, -1);
BoostPoint bp1, ep1, firstPt1;
vector<unique_ptr<DrcEdge>> tmpEdges;
// skip the first pt
auto innerIt = hole_poly.begin();
bp.set((*innerIt).x(), (*innerIt).y());
bp1 = *innerIt;
firstPt.set((*innerIt).x(), (*innerIt).y());
firstPt1 = *innerIt;
innerIt++;
// loop from second to last pt (n-1) edges
for (; innerIt != hole_poly.end(); innerIt++) {
ep.set((*innerIt).x(), (*innerIt).y());
ep1 = *innerIt;
auto edge = make_unique<DrcEdge>();
edge->set_layer_id(layer_id);
edge->addToPoly(poly);
edge->addToNet(net);
edge->setDir();
edge->setSegment(bp1, ep1);
if (region_query) {
region_query->add_routing_edge_to_rtree(layer_id, edge.get());
}
edge->set_is_fixed(false);
if (!tmpEdges.empty()) {
edge->setPrevEdge(tmpEdges.back().get());
tmpEdges.back()->setNextEdge(edge.get());
}
tmpEdges.push_back(std::move(edge));
bp.set(ep);
bp1 = ep1;
}
auto edge = make_unique<DrcEdge>();
edge->set_layer_id(layer_id);
edge->addToPoly(poly);
edge->addToNet(net);
edge->setSegment(bp1, firstPt1);
edge->setDir();
edge->set_is_fixed(false);
if (region_query) {
region_query->add_routing_edge_to_rtree(layer_id, edge.get());
}
edge->setPrevEdge(tmpEdges.back().get());
tmpEdges.back()->setNextEdge(edge.get());
// set first edge
tmpEdges.front()->setPrevEdge(edge.get());
edge->setNextEdge(tmpEdges.front().get());
tmpEdges.push_back(std::move(edge));
// add to polygon edges
poly->addEdges(tmpEdges);
}
/**
* @brief Assign each layer of net polygon to each poly
*
* @param net
*/
void DrcAPI::initPolyPolygon(DrcNet* net)
{
int routing_layer_num = _tech->get_drc_routing_layer_list().size();
// test_eol
// int routing_layer_num = 1;
std::vector<PolygonSet> layer_routing_polys(routing_layer_num);
std::vector<PolygonWithHoles> polygons;
for (int routing_layer_id = 0; routing_layer_id < routing_layer_num; routing_layer_id++) {
polygons.clear();
layer_routing_polys[routing_layer_id] = net->get_routing_polygon_set_by_id(routing_layer_id);
// output to polys
layer_routing_polys[routing_layer_id].get(polygons);
for (auto& polygon : polygons) {
net->addPoly(polygon, routing_layer_id);
}
}
}
void DrcAPI::getCommonSpacingScopeRect(DrcRect* target_rect, DrcRect* scope_rect, int spacing)
{
int lb_x = target_rect->get_left() - spacing;
int lb_y = target_rect->get_bottom() - spacing;
int rt_x = target_rect->get_right() + spacing;
int rt_y = target_rect->get_top() + spacing;
scope_rect->set_coordinate(lb_x, lb_y, rt_x, rt_y);
scope_rect->set_layer_id(target_rect->get_layer_id());
scope_rect->set_layer_order(target_rect->get_layer_order());
}
void DrcAPI::getCommonSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& target_nets, bool is_max)
{
for (auto& [net_id, net] : target_nets) {
for (auto& [layer_id, routing_rect_list] : net.get_layer_to_routing_rects_map()) {
for (auto target_rect : routing_rect_list) {
int spacing;
if (is_max) {
int width = target_rect->getWidth();
int length = target_rect->getLength();
spacing = _tech->get_drc_routing_layer_list()[layer_id]->get_spacing_table()->get_parallel()->get_spacing(width, length);
} else {
spacing = _tech->get_drc_routing_layer_list()[layer_id]->get_spacing_table()->get_parallel()->get_spacing(0, 0);
}
DrcRect* common_spacing_max_scope = new DrcRect();
getCommonSpacingScopeRect(target_rect, common_spacing_max_scope, spacing);
max_scope_list.push_back(common_spacing_max_scope);
}
}
}
}
void DrcAPI::getEOLSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& target_nets, bool is_max)
{
EOLSpacingCheck* eol_spacing_check = new EOLSpacingCheck(_tech, nullptr);
for (auto& [net_id, target_net] : target_nets) {
for (auto& [layer_id, target_polys] : target_net.get_route_polys_list()) {
for (auto& target_poly : target_polys) {
// getEOLSpacingMaxScopeOfPoly(target_poly.get(), max_scope_list);
eol_spacing_check->getScope(target_poly.get(), max_scope_list, is_max);
}
}
}
delete eol_spacing_check;
}
void DrcAPI::getCornerFillSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& target_nets)
{
CornerFillSpacingCheck* cornerfill_check = new CornerFillSpacingCheck(_tech, nullptr);
for (auto& [net_id, target_net] : target_nets) {
for (auto& [layer_id, target_polys] : target_net.get_route_polys_list()) {
for (auto& target_poly : target_polys) {
cornerfill_check->getScope(target_poly.get(), max_scope_list);
}
}
}
delete cornerfill_check;
}
std::vector<DrcRect*> DrcAPI::getMaxScope(std::vector<DrcRect*> origin_rect_list)
{
std::vector<DrcRect*> max_scope_list;
std::map<int, DrcNet> nets;
initNets(origin_rect_list, nets);
initPoly(nets, nullptr);
getCommonSpacingScope(max_scope_list, nets, true);
// getEOLSpacingScope(max_scope_list, nets, true);
// getCornerFillSpacingScope(max_scope_list, nets);
return max_scope_list;
}
std::vector<DrcRect*> DrcAPI::getMinScope(std::vector<DrcRect*> origin_rect_list)
{
std::vector<DrcRect*> min_scope_list;
std::map<int, DrcNet> nets;
initNets(origin_rect_list, nets);
initPoly(nets, nullptr);
getCommonSpacingScope(min_scope_list, nets, false);
// getEOLSpacingScope(min_scope_list, nets, false);
// getCornerFillSpacingScope(min_scope_list, nets);
return min_scope_list;
}
DrcRect* DrcAPI::getDrcRect(int net_id, int lb_x, int lb_y, int rt_x, int rt_y, std::string layer_name, bool is_artifical)
{
DrcRect* drc_rect = new DrcRect(net_id, lb_x, lb_y, rt_x, rt_y);
if (_tech) {
int layer_order = _tech->getLayerOrderByName(layer_name);
drc_rect->set_layer_order(layer_order);
} else {
return nullptr;
}
std::pair<bool, int> layer_info = _tech->getLayerInfoByLayerName(layer_name);
drc_rect->set_layer_id(layer_info.second);
if (is_artifical) {
drc_rect->set_owner_type(RectOwnerType::kBlockage);
} else {
if (!layer_info.first) {
drc_rect->set_owner_type(RectOwnerType::kViaCut);
} else {
drc_rect->set_owner_type(RectOwnerType::kRoutingMetal);
}
}
return drc_rect;
}
DrcRect* DrcAPI::getDrcRect(ids::DRCRect ids_rect)
{
return getDrcRect(-1, ids_rect.lb_x, ids_rect.lb_y, ids_rect.rt_x, ids_rect.rt_y, ids_rect.layer_name, ids_rect.is_artificial);
}
ids::DRCRect DrcAPI::getDrcRect(DrcRect* drc_rect)
{
ids::DRCRect ids_rect;
ids_rect.lb_x = drc_rect->get_rectangle().get_lb_x();
ids_rect.lb_y = drc_rect->get_rectangle().get_lb_y();
ids_rect.rt_x = drc_rect->get_rectangle().get_rt_x();
ids_rect.rt_y = drc_rect->get_rectangle().get_rt_y();
ids_rect.layer_name = _tech->getRoutingLayerNameById(drc_rect->get_layer_id());
return ids_rect;
}
std::map<std::string, std::vector<DrcViolationSpot*>> DrcAPI::check(RegionQuery* region_query)
{
return check(region_query->getRegionRectList());
}
std::map<std::string, std::vector<DrcViolationSpot*>> DrcAPI::check(std::vector<DrcRect*>& region_rect_list, RegionQuery* dr_region_query)
{
std::vector<DrcRect*> cut_rect_list;
std::vector<DrcRect*> routing_rect_list;
std::map<int, DrcNet> nets;
RegionQuery* region_query = nullptr;
if (dr_region_query == nullptr) {
/* init region*/
region_query = new RegionQuery();
for (auto& drc_rect : region_rect_list) {
int layer_id = drc_rect->get_layer_id();
if (drc_rect->get_owner_type() == RectOwnerType::kViaCut) {
cut_rect_list.push_back(drc_rect);
region_query->add_cut_rect_to_rtree(layer_id, drc_rect);
} else if (drc_rect->get_owner_type() == RectOwnerType::kRoutingMetal) {
routing_rect_list.push_back(drc_rect);
region_query->add_routing_rect_to_rtree(layer_id, drc_rect);
}
}
} else {
region_query = dr_region_query;
}
initNets(region_rect_list, nets);
initPoly(nets, region_query);
auto jog_spacing_check = new JogSpacingCheck(_tech, region_query);
auto notch_spacing_check = new NotchSpacingCheck(_tech, region_query);
auto min_step_check = new MinStepCheck(_tech, region_query);
auto corner_fill_spacing_check = new CornerFillSpacingCheck(_tech, region_query);
auto cut_eol_spacing_check = new CutEolSpacingCheck(_tech, region_query);
auto routing_sapcing_check = new RoutingSpacingCheck(_tech, region_query);
auto eol_spacing_check = new EOLSpacingCheck(_tech, region_query);
auto routing_area_check = new RoutingAreaCheck(_tech, region_query);
auto routing_width_check = new RoutingWidthCheck(_tech, region_query);
auto enclosed_area_check = new EnclosedAreaCheck(_tech, region_query);
auto cut_spacing_check = new CutSpacingCheck(_tech, region_query);
auto enclosure_check = new EnclosureCheck(_tech, region_query);
for (auto& [net_id, net] : nets) {
routing_sapcing_check->checkRoutingSpacing(&net);
routing_width_check->checkRoutingWidth(&net);
routing_area_check->checkArea(&net);
enclosed_area_check->checkEnclosedArea(&net);
cut_spacing_check->checkCutSpacing(&net);
eol_spacing_check->checkEOLSpacing(&net);
notch_spacing_check->checkNotchSpacing(&net);
min_step_check->checkMinStep(&net);
corner_fill_spacing_check->checkCornerFillSpacing(&net);
cut_eol_spacing_check->checkCutEolSpacing(&net);
jog_spacing_check->checkJogSpacing(&net);
}
delete jog_spacing_check;
delete notch_spacing_check;
delete min_step_check;
delete corner_fill_spacing_check;
delete cut_eol_spacing_check;
delete routing_sapcing_check;
delete eol_spacing_check;
delete routing_area_check;
delete routing_width_check;
delete enclosed_area_check;
delete cut_spacing_check;
delete enclosure_check;
std::map<std::string, std::vector<DrcViolationSpot*>> vio_map;
region_query->getRegionDetailReport(vio_map);
return vio_map;
}
} // namespace idrc

View File

@ -1,148 +0,0 @@
// ***************************************************************************************
// 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 <string>
#include "../../../database/interaction/ids.hpp"
#include "DRC.h"
#include "DrcEnum.h"
namespace idrc {
class DrcConfig;
class DrcDesign;
class Tech;
class RoutingSpacingCheck;
class CutSpacingCheck;
class RoutingWidthCheck;
class EnclosedAreaCheck;
class RoutingAreaCheck;
class EnclosureCheck;
class DrcSpot;
class DrcRect;
class DrcPolygon;
class DrcPoly;
class RegionQuery;
class IDRWrapper;
class DrcIDBWrapper;
class DrcNet;
class SpotParser;
class MultiPatterning;
class DrcConflictGraph;
class EOLSpacingCheck;
#define DrcAPIInst DrcAPI::getInst()
class DrcAPI
{
public:
static DrcAPI& getInst()
{
if (_drc_api_instance == nullptr) {
_drc_api_instance = new DrcAPI();
}
return *_drc_api_instance;
}
static void destroyInst();
//////////////////////////
RegionQuery* init();
void destroy(RegionQuery* region_query);
RegionQuery* getLayoutRegion() { return _drc != nullptr ? _drc->get_region_query() : nullptr; }
bool check(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list);
void add(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list);
void del(RegionQuery* region_query, std::vector<idrc::DrcRect*> drc_rect_list);
std::map<std::string, std::vector<DrcViolationSpot*>> check(RegionQuery* region_query);
std::map<std::string, std::vector<DrcViolationSpot*>> check(std::vector<DrcRect*>& region_rect_list, RegionQuery* dr_region_query = nullptr);
DrcRect* getDrcRect(int net_id, int lb_x, int lb_y, int rt_x, int rt_y, std::string layer_name, bool is_artificial = false);
DrcRect* getDrcRect(ids::DRCRect drc_rect);
ids::DRCRect getDrcRect(DrcRect* drc_rect);
// Get the maximum influence region of spacing (Common,EOL,Corner_fill)
std::vector<DrcRect*> getMaxScope(std::vector<DrcRect*> origin_rect_list);
// Get the minimum influence region of spacing (Common,EOL,Corner_fill)
std::vector<DrcRect*> getMinScope(std::vector<DrcRect*> origin_rect_list);
/////////////////////////
// interact function
void runDrc();
// // dynamic interaction
// bool check(std::vector<ids::DRCTask> task_list);
// void add(std::vector<ids::DRCTask> task_list);
// void del(std::vector<ids::DRCTask> task_list);
std::map<std::string, int> getCheckResult(RegionQuery* region_query);
std::map<std::string, int> getCheckResult();
std::map<std::string, std::vector<DrcViolationSpot*>> getDetailCheckResult();
// // Get the maximum influence region of spacing (Common,EOL,Corner_fill)
// std::vector<DrcRect*> getMaxScope(std::vector<DrcRect*> origin_rect_list);
// // Get the minimum influence region of spacing (Common,EOL,Corner_fill)
// std::vector<DrcRect*> getMinScope(std::vector<DrcRect*> origin_rect_list);
DrcRect* getDrcRect(int net_id, int lb_x, int lb_y, int rt_x, int rt_y, int layer_order, std::string layer_name,
bool is_artificial = false);
void initDRC();
// RegionQuery* createRTree(ids::DRCEnv env);
bool checkDRC(std::vector<DrcRect*> origin_rect_list);
// static interaction
// std::map<std::string, std::vector<DrcViolationSpot*>> check(std::vector<DrcRect*>& region_rect_list);
private:
static DrcAPI* _drc_api_instance;
Tech* _tech;
DrcIDBWrapper* _idb_wrapper = nullptr;
DRC* _drc = nullptr;
DrcAPI() = default;
~DrcAPI() = default;
void getCommonSpacingMinRegion(DrcRect* common_spacing_min_region, DrcRect* drc_rect);
void getCommonSpacingMaxRegion(DrcRect* common_spacing_min_region, DrcRect* drc_rect);
// void initSpacingRegion(ids::DRCEnv env, RegionQuery* region_query);
void addEOLSpacingRegion(DrcPoly* drc_poly, RegionQuery* region_query);
void addCommonSpacingRegion(DrcRect* drc_rect, RegionQuery* region_query);
void initRegionQuery(std::vector<DrcRect*> origin_rect_list, RegionQuery* region_query);
// DrcRect* getDrcRect(ids::DRCRect ids_rect);
RTreeBox getRTreeBox(DrcRect* rect);
void initPoly(std::map<int, DrcNet>& nets, RegionQuery* region_query);
void initPolyPolygon(DrcNet* net);
void initPolyInnerEdges(DrcNet* net, DrcPoly* poly, const BoostPolygon& hole_poly, int layer_id, RegionQuery* region_query);
void initPolyOuterEdges(DrcNet* net, DrcPoly* poly, DrcPolygon* polygon, int layer_id, RegionQuery* region_query);
void initPolyEdges(DrcNet* net, RegionQuery* region_query);
void initNets(std::vector<DrcRect*>& drc_rect_list, std::map<int, DrcNet>& nets);
// scope
void getCommonSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& nets, bool is_max);
void getCommonSpacingScopeRect(DrcRect* target_rect, DrcRect* scope_rect, int spacing);
void getEOLSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& target_nets, bool is_max);
void getCornerFillSpacingScope(std::vector<DrcRect*>& max_scope_list, std::map<int, DrcNet>& target_nets);
// check
bool checkSpacing(RegionQuery* region_query, DrcRect* check_rect);
bool checkShape(RegionQuery* region_query, DrcRect* drc_rect);
void queryInMaxScope(DrcRect* check_rect, std::map<void*, std::set<ScopeType>>& max_scope_query_result);
bool checkSpacing_rect(DrcRect* check_rect, RegionQuery* region_query);
void mergeRectToPoly(DrcRect* check_rect, RegionQuery* region_query, DrcPoly* poly);
};
} // namespace idrc

View File

@ -1,7 +0,0 @@
INCLUDE_DIRECTORIES(
SYSTEM
## Third Party
${HOME_THIRDPARTY}/json
## Boost
${Boost_INCLUDE_DIRS}
)

View File

@ -1,12 +0,0 @@
add_library(idrc_api_external_lib INTERFACE)
target_link_libraries(idrc_api_external_lib
INTERFACE
idm
)
target_include_directories(idrc_api_external_lib
INTERFACE
${HOME_PLATFORM}/data_manager
${HOME_PLATFORM}/data_manager/file_manager
)

View File

@ -1,191 +0,0 @@
# **iDRC功能介绍文档**
**编制:**
**审核:**
**时间:** 2023年05月06日
---
## **版本修改历史**
| 版本号 | 日期 | 作者 | 简要说明 |
| ------ | ---------- | ---- | -------- |
| 0.10 | 202x-xx-xx | | |
| | | | |
| | | | |
| | | | |
| | | | |
---
## 一、 iDRC目录结构
### 1. api/
实现iDRC与其他子工具交互的接口
### 2. doc/
存放说明文档以及功能手册
### 3. source/
#### 3.1 config/
通过配置文件配置DRC
#### 3.2 data/
##### 3.2.1 basic/
存放iDRC运行需要用到的所有基础数据结构
| 数据结构 | 介绍 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Tech | 存放从TechFile中读取到的设计规则信息以层的结构将规则组织起来 |
| DrcLayer | 存放某一层的所有TechFile规定的所有设计规则要求每个Layer都与Tech LEF中的Layer相对应。 |
| DrcDesign | 版图设计信息的顶层数据结构 |
| DrcNet | 存放版图中的一条net包含一条net的通孔、金属线、与之相连的Pin、以及根据金属线和Pin构建出的Poly结构 |
| DrcPoly | 由一条net中相互交叠的金属线、Enclosure以及Pin融合而来形成的多边矩形结构。 |
| DrcPolygon | 仅存放DrcPoly中的几何信息。 |
| DrcRect | 表示设计中的obj可以是一个金属线段、也可以是一个Enclosure或者是一个Cut |
| DrcRectangle | 仅存放DrcRect中的几何信息。 |
| DrcViolationSpot | 包含违例报告信息的结构体,包括坐标信息,违例类型等。 |
##### 3.2.2 rule/
存放TechFile中的DRC规则目前已经弃用使用iDB中定义的规则数据结构。
##### 3.2.3 iDBWrapper
包装来自iDB中的数据构建iDRC所需的数据结构。
#### 3.3 module/
##### 3.3.1 multi_patterning/
已弃用
##### 3.3.2 region_query/
区域查询模块是在检查时用到的工具内含多个R树R树存放版图几何信息使用Boost库中的R树接口实现供检查时使用主要用途如下
* 用于存放版图的几何信息,查询某一几何区域与版图上其他几何物体的关系;
* 用于存放违例报告的几何图形,防止违例的重复报告;
* 用于存放版图几何物体的影响范围实现DrcAPI相关功能
##### 3.3.3 shape_check/
实现针对非Spacing类型规则的检查主要包括MinStep、Width、Area、Enclosure相关规则的检查
| 检查类型 | 介绍 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 最小步长MinStep规则 | 该规则要求金属线外边缘不可以有超过 TechFile 限定个数的边长小于TechFile规定值的连续边如图1.1所示 |
| 通孔包围Enclosure规则 | 通孔包围规则规定了某一个Cut上下层的金属包围与Cut边缘的最小距离超过这些距离会发生Enclosure违例如图1.2所示 |
| 最小宽度规则 | 最小宽度规则是用于约束版图中导体图形的内边间距(Distance of interior facing edge)如图1.3(a)所示它规定了导体图形的内边间距不得小于TechFile规定的最小宽度参数值包括导体的长度导体的宽度导体的内对角宽度如下图1.3中(b),(c),(d)所示。 |
| 最小面积规则 |最小面积规则规定了各个工艺层的导体面积不能小于TechFile中指定的最小面积参参数值如下图1.4左图中的Area示意 |
| 最小孔洞面积规则 | 最小包围面积规定了由导体环绕包围形成的孔洞面积不能小于TechFile指定的最小面积参数值如下图1.4右图中的Enclosed Area示意。 |
<img src="图片/minstep.png" style="zoom:80%;" />
图1.1 最小步长规则对应的检查对象
<img src="图片/enclosure.png" style="zoom:60%;" />
图1.2 通孔包围规则对应的检查对象
<img src="图片/图片1.3.png" style="zoom:60%;" />
图1.3 导体图形的内边间距(最小宽度规则对应的检查对象)
<img src="图片/图片1.4.png" style="zoom:50%;" />
图1.4 左图为导体图形的面积(最小面积规则对应的检查对象)
右图为导体图形包围形成的孔洞面积(最小包围面积规则对应的检查对象)
##### 3.3.4 spacing_check/
| 名词 | 名词解释 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 短路违规 | 当所属不同线网的导体几何图形产生任何形式的交叠,都会产生短路,比如,所属不同线网的线段(Wire)所属不同线网的Pin和通孔Via线网图形和障碍物Block它们之间的触碰都是不允许的都被视为短路违规如下图1.5所示。 |
| 金属最小间距规则 | 最小间距规则可以理解为版图中导体图形间的外边间距(Distance of exterior facing edge)不得小于TechFile中规定的当前工艺层的最小间距参数值,导体间的外边间距如下图1.2(a)所示间距规则包括检查导体间X方向的间距Y方向间距与角间距如图1.6所示。 |
| 金属最小线端EOL间隔规则 | 该规则要求在TechFile中要求的金属线末端的区域内不可以有其他的金属线与该区域产生交叠区域的可能大小受到线端边EOL的邻接边长度、附近是否有通孔以及相邻金属线等因素影响如图1.7所示。 |
| 金属最小凹槽Notch间隔规则 | 该规则要求在符合TechFile规定条件的由金属线形成凹槽区域中凹槽的底部长度不得小于规定值如图1.8所示。 |
| 金属最小Jog间隔规则 | 该规则要求在一个较宽金属线与其邻近的Parallel Run Length长度符合 TechFile要求的金属线之间存在的某些特定的金属之间的间隔要求如图1.9所示。 |
| 金属最小CornerFill间隔规则 | 该规则要求在金属线外边缘存在符合TechFile要求的拐角处缺口型区域时在该缺口处虚拟出一块金属检查该虚拟出的金属与其他金属的间隔如图1.10所示。 |
| Cut最小间隔规则 | 该规则要求同一Cut层中的任何两个Cut之间的间隔不能小于规定值,Cut层的Spacing计算虽然一般默认为edge-to-edge的欧式距离但有些情况下会因为规则中的某些字段而发生改变某些情况下会以两者在X、Y方向上的最大投影长度来代替欧式距离来计算Spacing如图1.11所示。 |
<img src="图片/图片1.1.png" style="zoom:80%;" />
图1.5 短路违规情况
<img src="图片/图1.2.png" style="zoom:80%;" />
图1.6 导体图形外边间距示意图(最小间距规则对应检查对象)
<img src="图片/EOL.png" style="zoom:80%;" />
图1.7 金属最小线端EOL间隔规则对应的检查对象
<img src="图片/notch.png" style="zoom:80%;" />
图1.8 金属最小凹槽Notch间隔规则对应的检查对象
<img src="图片/jog.png" style="zoom:50%;" />
图1.9 金属最小Jog间隔规则对应的检查对象
<img src="图片/corner_fill.png" style="zoom:50%;" />
图1.10 金属最小CornerFill间隔规则对应的检查对象
<img src="图片/cut_spacing.png" style="zoom:100%;" />
图1.11 Cut最小间隔规则对应的检查对象
##### 3.3.5 spot_parser/
已弃用
#### 3.4 util/
### 4. test/
用于存放单元测试文件
## 二、iDRC command
### 2.1 run_drc
读取Def、Lef文件进行DRC检查并输出DRC全局报告
```tcl
run_drc -config $config -path $gloabal_drc_report_file_path
```
### 2.2 save_drc
保存并输出DRC检查详细报告需要先run_drc得到检查结果
```tcl
run_drc -config $config -path $gloabal_drc_report_file_path
save_drc -path $detail_drc_report_file_path
```
### 2.3 read_drc
读取DRC详细报告
```tcl
read_drc -path $detail_drc_report_file_path
```
### 2.4 init_drc
从DataManager中初始化DRC所需Tech和Design数据
```tcl
init_drc
```
### 2.5 check_drc
从DataManager中初始化DRC所需数据并进行检查输出全局报告到终端
```tcl
check_drc
```
### 2.6 destroy_drc
销毁DRC
```tcl
destroy_drc
```
### 2.7 init_drc_api
从DataManeger中初始化DrcAPI所需的Tech数据
```tcl
init_drc_api
```
### 2.8 destroy_drc_api
销毁DrcAPI
```tcl
destroy_drc_api
```
### 2.9 check_net
检查指定net的是否连通
```tcl
check_net -name $net_name
```
### 2.10 check_all_net
检查所有net的是否连通
```tcl
check_all_net
```

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

View File

@ -0,0 +1,21 @@
if(DEBUG_IDRC_INTERFACE)
message(STATUS "DRC: DEBUG_IDRC_INTERFACE")
set(CMAKE_BUILD_TYPE "Debug")
else()
message(STATUS "DRC: RELEASE_IDRC_INTERFACE")
set(CMAKE_BUILD_TYPE "Release")
endif()
add_library(idrc_interface
${IDRC_INTERFACE}/DRCInterface.cpp
)
target_link_libraries(idrc_interface
PRIVATE
idrc_source
)
target_include_directories(idrc_interface
PUBLIC
${IDRC_INTERFACE}
)

View File

@ -0,0 +1,102 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DRCInterface.hpp"
#include "DataManager.hpp"
namespace idrc {
// public
DRCInterface& DRCInterface::getInst()
{
if (_drc_interface_instance == nullptr) {
_drc_interface_instance = new DRCInterface();
}
return *_drc_interface_instance;
}
void DRCInterface::destroyInst()
{
if (_drc_interface_instance != nullptr) {
delete _drc_interface_instance;
_drc_interface_instance = nullptr;
}
}
#if 1 // 外部调用DRC的API
#if 1 // iDRC
void DRCInterface::initDRC()
{
// 初始化规则
}
void DRCInterface::checkDef()
{
std::vector<idb::IdbLayerShape*> idb_env_shape_list;
std::map<int32_t, std::vector<idb::IdbLayerShape*>> idb_net_pin_shape_map;
std::map<int32_t, std::vector<idb::IdbRegularWireSegment*>> idb_net_result_map;
// create data
{
}
// check
getViolationList(idb_env_shape_list, idb_net_pin_shape_map, idb_net_result_map);
// free memory
{
for (idb::IdbLayerShape* idb_env_shape : idb_env_shape_list) {
delete idb_env_shape;
idb_env_shape = nullptr;
}
for (auto& [net_idx, pin_shape_list] : idb_net_pin_shape_map) {
for (idb::IdbLayerShape* pin_shape : pin_shape_list) {
delete pin_shape;
pin_shape = nullptr;
}
}
for (auto& [net_idx, segment_list] : idb_net_result_map) {
for (idb::IdbRegularWireSegment* segment : segment_list) {
delete segment;
segment = nullptr;
}
}
}
}
std::vector<ids::Violation> DRCInterface::getViolationList(std::vector<idb::IdbLayerShape*>& idb_env_shape_list,
std::map<int32_t, std::vector<idb::IdbLayerShape*>>& idb_net_pin_shape_map,
std::map<int32_t, std::vector<idb::IdbRegularWireSegment*>>& idb_net_result_map)
{
return {};
}
void DRCInterface::destroyDRC()
{
// 销毁规则
}
#endif
#endif
// private
DRCInterface* DRCInterface::_drc_interface_instance = nullptr;
} // namespace idrc

View File

@ -0,0 +1,80 @@
// ***************************************************************************************
// 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 <any>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "../../../database/interaction/ids.hpp"
#if 1 // 前向声明
namespace idb {
class IdbLayerShape;
class IdbRegularWireSegment;
} // namespace idb
namespace idrc {
enum class ViolationType;
class Violation;
} // namespace idrc
#endif
namespace idrc {
#define DRCI (idrc::DRCInterface::getInst())
class DRCInterface
{
public:
static DRCInterface& getInst();
static void destroyInst();
#if 1 // 外部调用DRC的API
#if 1 // iDRC
void initDRC();
void checkDef();
std::vector<ids::Violation> getViolationList(std::vector<idb::IdbLayerShape*>& idb_env_shape_list,
std::map<int32_t, std::vector<idb::IdbLayerShape*>>& idb_net_pin_shape_map,
std::map<int32_t, std::vector<idb::IdbRegularWireSegment*>>& idb_net_result_map);
void destroyDRC();
#endif
#endif
#if 1 // DRC调用外部的API
#endif
private:
static DRCInterface* _drc_interface_instance;
DRCInterface() = default;
DRCInterface(const DRCInterface& other) = delete;
DRCInterface(DRCInterface&& other) = delete;
~DRCInterface() = default;
DRCInterface& operator=(const DRCInterface& other) = delete;
DRCInterface& operator=(DRCInterface&& other) = delete;
// function
};
} // namespace idrc

View File

@ -1,31 +1,18 @@
add_subdirectory(config)
add_subdirectory(data)
add_subdirectory(module)
add_subdirectory(util)
add_library(idrc_src
DRC.cpp
DRCInit.cpp
)
target_include_directories(idrc_src
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${HOME_OPERATION}/iDRC/source/util
# ${HOME_OPERATION}/iDRC/data/basic
)
target_link_libraries(idrc_src
PRIVATE
idrc_config
idrc_db
idrc_multi_pattern
idrc_region_query
idrc_shape_check
idrc_spacing_check
idrc_spot_parser
## set path
set(IDRC_DATA_MANAGER ${IDRC_SOURCE}/data_manager)
set(IDRC_MODULE ${IDRC_SOURCE}/module)
set(IDRC_TOOLKIT ${IDRC_SOURCE}/toolkit)
## build
add_subdirectory(${IDRC_DATA_MANAGER})
add_subdirectory(${IDRC_MODULE})
add_subdirectory(${IDRC_TOOLKIT})
add_library(idrc_source INTERFACE)
target_link_libraries(idrc_source
INTERFACE
idrc_data_manager
idrc_module
idrc_toolkit
)

View File

@ -1,415 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DRC.h"
#include <ctime>
#include "CornerFillSpacingCheck.hpp"
#include "CutEolSpacingCheck.hpp"
#include "CutSpacingCheck.hpp"
#include "DrcConfig.h"
#include "DrcConfigurator.h"
#include "DrcConflictGraph.h"
#include "DrcDesign.h"
#include "DrcIDBWrapper.h"
#include "EOLSpacingCheck.hpp"
#include "EnclosedAreaCheck.h"
#include "EnclosureCheck.hpp"
// #include "IDRWrapper.h"
#include "JogSpacingCheck.hpp"
#include "MinStepCheck.hpp"
#include "MultiPatterning.h"
#include "NotchSpacingCheck.hpp"
#include "RegionQuery.h"
#include "RoutingAreaCheck.h"
#include "RoutingSpacingCheck.h"
#include "RoutingWidthCheck.h"
#include "SpotParser.h"
#include "Tech.h"
#include "idm.h"
namespace idrc {
DRC* DRC::_drc_instance = nullptr;
DRC& DRC::getInst()
{
if (_drc_instance == nullptr) {
_drc_instance = new DRC();
}
return *_drc_instance;
}
void DRC::destroyInst()
{
if (_drc_instance != nullptr) {
delete _drc_instance;
_drc_instance = nullptr;
}
}
DRC::DRC()
{
_config = new DrcConfig();
_drc_design = new DrcDesign();
_tech = new Tech();
_conflict_graph = new DrcConflictGraph();
_multi_patterning = new MultiPatterning();
_region_query = new RegionQuery(_tech);
}
// /**
// * @brief Get the number of short circuit violations in DEF file mode
// *
// * @return int Number of short circuit violations
// */
// int DRC::getShortViolationNum()
// {
// return _routing_spacing_check->get_short_violation_num();
// }
// /**
// * @brief Get the number of spacing violations in DEF file mode
// *
// * @return int Number of spacing violations
// */
// int DRC::getSpacingViolationNum()
// {
// return _routing_spacing_check->get_spacing_violation_num();
// }
// /**
// * @brief Get the number of width violations in DEF file mode
// *
// * @return int Number of width violations
// */
// int DRC::getWidthViolationNum()
// {
// return _routing_width_check->get_width_violation_num();
// }
// /**
// * @brief Get the number of area violations in DEF file mode
// *
// * @return int Number of area violations
// */
// int DRC::getAreaViolationNum()
// {
// return _routing_area_check->get_area_violation_num();
// }
// /**
// * @brief Get the number of enclosed area violations in DEF file mode
// *
// * @return int Number of enclosed area violations
// */
// int DRC::getEnclosedAreaViolationNum()
// {
// return _enclosed_area_check->get_enclosed_area_violation_num();
// }
// /**
// * @brief Return the list of Spots storing short circuit violation information
// *
// * @return std::map<int, std::vector<DrcSpot>>&
// */
// std::map<int, std::vector<DrcSpot>>& DRC::getShortSpotList()
// {
// return _routing_spacing_check->get_routing_layer_to_short_spots_list();
// }
// /**
// * @brief Return the list of Spots storing spacing violation information
// *
// * @return std::map<int, std::vector<DrcSpot>>&
// */
// std::map<int, std::vector<DrcSpot>>& DRC::getSpacingSpotList()
// {
// return _routing_spacing_check->get_routing_layer_to_spacing_spots_list();
// }
// /**
// * @brief Return the list of Spots storing width violation information
// *
// * @return std::map<int, std::vector<DrcSpot>>&
// */
// std::map<int, std::vector<DrcSpot>>& DRC::getWidthSpotList()
// {
// return _routing_width_check->get_routing_layer_to_spots_map();
// }
// /**
// * @brief Return the list of Spots storing area violation information
// *
// * @return std::map<int, std::vector<DrcSpot>>&
// */
// std::map<int, std::vector<DrcSpot>>& DRC::getAreaSpotList()
// {
// return _routing_area_check->get_routing_layer_to_spots_map();
// }
// /**
// * @brief Return the list of Spots storing enclosed area violation information
// *
// * @return std::map<int, std::vector<DrcSpot>>&
// */
// std::map<int, std::vector<DrcSpot>>& DRC::getEnclosedAreaSpotList()
// {
// return _enclosed_area_check->get_routing_layer_to_spots_map();
// }
// /**
// * @brief Initialize Tech data (process design rules data) through the configuration file
// *
// * @param drc_config_path Configuration file path
// */
// void DRC::initTechFromIDB(std::string& drc_config_path)
// {
// DrcConfigurator* configurator = new DrcConfigurator();
// configurator->set(_config, drc_config_path);
// delete configurator;
// _idb_wrapper = new DrcIDBWrapper(_config, _tech, _drc_design, _region_query);
// _idb_wrapper->initTech(); //input IdbBuilder
// }
/**
* @brief Initialize Tech data (process rules data) using the iDB_Builder pointer
*
* @param idb_builder iDB_Builder pointer
*/
void DRC::initTechFromIDB(idb::IdbBuilder* idb_builder)
{
delete _idb_wrapper;
_idb_wrapper = new DrcIDBWrapper(_config, _tech, _drc_design, _region_query);
_idb_wrapper->initTech(idb_builder); //传入IdbBuilder
}
/**
* @brief Initialize each design rule check module to prepare for design rule checks
*
* @param drc_config_path
*/
void DRC::initDRC(std::string& drc_config_path, idb::IdbBuilder* idb_builder)
{
DrcConfigurator* configurator = new DrcConfigurator();
configurator->set(_config, drc_config_path);
delete configurator;
_idb_wrapper = new DrcIDBWrapper(_config, _tech, _drc_design, _region_query);
_idb_wrapper->input(idb_builder); //传入IdbBuilder
}
//通过Data Manager获取数据
void DRC::initDRC()
{
// _tech = new Tech();
// _drc_design = new DrcDesign();
// _region_query = new RegionQuery();
if (dmInst->get_idb_builder()) {
_idb_wrapper = new DrcIDBWrapper(_tech, _drc_design, dmInst->get_idb_builder(), _region_query);
_idb_wrapper->wrapTech();
_idb_wrapper->wrapDesign();
} else {
std::cout << "Error: idb builder is null" << std::endl;
exit(1);
}
}
void DRC::initDesign(std::map<std::string, std::any> config_map)
{
std::string def_path = std::any_cast<std::string>(config_map.find("-def_path")->second);
dmInst->readDef(def_path);
if (dmInst->get_idb_builder()) {
_drc_design = new DrcDesign();
_region_query = new RegionQuery();
_idb_wrapper = new DrcIDBWrapper(_tech, _drc_design, dmInst->get_idb_builder(), _region_query);
_idb_wrapper->wrapDesign();
} else {
std::cout << "Error: idb builder is null" << std::endl;
exit(1);
}
}
/**
* @brief Initialize each design rule check module to prepare for design rule checks
*
*/
void DRC::initCheckModule()
{
_jog_spacing_check = new JogSpacingCheck(_tech, _region_query);
_notch_spacing_check = new NotchSpacingCheck(_tech, _region_query);
_min_step_check = new MinStepCheck(_tech, _region_query);
_corner_fill_spacing_check = new CornerFillSpacingCheck(_tech, _region_query);
_cut_eol_spacing_check = new CutEolSpacingCheck(_tech, _region_query);
_routing_sapcing_check = new RoutingSpacingCheck(_tech, _region_query);
_eol_spacing_check = new EOLSpacingCheck(_tech, _region_query);
_routing_area_check = new RoutingAreaCheck(_tech, _region_query);
_routing_width_check = new RoutingWidthCheck(_tech, _region_query);
_enclosed_area_check = new EnclosedAreaCheck(_tech, _region_query);
_cut_spacing_check = new CutSpacingCheck(_tech, _region_query);
_enclosure_check = new EnclosureCheck(_tech, _region_query);
_spot_parser = SpotParser::getInstance(_config, _tech);
}
/**
* @brief Update the current process data and stored results of each design rule check module to prepare for the next round of checks
*
*/
void DRC::update()
{
_region_query->clear_layer_to_routing_rects_tree_map();
clearRoutingShapesInDrcNetList();
_routing_sapcing_check->reset();
_routing_area_check->reset();
_routing_width_check->reset();
_enclosed_area_check->reset();
}
/**
* @brief Traverse each Net and run each design rule check module for every Net
*
*/
void DRC::run()
{
int index = 0;
for (auto& drc_net : _drc_design->get_drc_net_list()) {
if (index++ % 1000 == 0) {
std::cout << "-" << std::flush;
}
if (index++ % 100000 == 0) {
std::cout << std::endl;
}
_routing_sapcing_check->checkRoutingSpacing(drc_net);
_routing_width_check->checkRoutingWidth(drc_net);
_routing_area_check->checkArea(drc_net);
_enclosed_area_check->checkEnclosedArea(drc_net);
_cut_spacing_check->checkCutSpacing(drc_net);
_eol_spacing_check->checkEOLSpacing(drc_net);
_notch_spacing_check->checkNotchSpacing(drc_net);
_min_step_check->checkMinStep(drc_net);
_corner_fill_spacing_check->checkCornerFillSpacing(drc_net);
_cut_eol_spacing_check->checkCutEolSpacing(drc_net);
// cout << "CutEol" << timeEnd - timeStart << std::endl;
_jog_spacing_check->checkJogSpacing(drc_net);
}
// if (_conflict_graph != nullptr) {
// }
}
// /**
// * @brief Check if the target Net has any design violations (needs to be re-implemented)
// *
// * @param netId
// */
// void DRC::checkTargetNet(int netId)
// {
// // DrcNet* targrt_net = _idr_wrapper->get_drc_net(netId);
// // _routing_sapcing_check->checkRoutingSpacing(targrt_net);
// // _routing_width_check->checkRoutingWidth(targrt_net);
// // _routing_area_check->checkRoutingArea(targrt_net);
// // _enclosed_area_check->checkEnclosedArea(targrt_net);
// }
/**
* @brief Report the results of each design rule check module in the form of a file
*
*
*/
void DRC::report()
{
// _spot_parser->reportSpacingViolation(_routing_sapcing_check);
// _spot_parser->reportShortViolation(_routing_sapcing_check);
// _spot_parser->reportAreaViolation(_routing_area_check);
// _spot_parser->reportWidthViolation(_routing_width_check);
// _spot_parser->reportEnclosedAreaViolation(_enclosed_area_check);
// _spot_parser->reportCutSpacingViolation(_cut_spacing_check);
// _spot_parser->reportEnclosureViolation(_enclosure_check);
// _spot_parser->reportEOLSpacingViolation(_eol_spacing_check);
// _spot_parser->reportEnd2EndSpacingViolation(_eol_spacing_check);
std::map<std::string, int> viotype_to_nums_map;
_region_query->getRegionReport(viotype_to_nums_map);
for (auto& [name, nums] : viotype_to_nums_map) {
std::cout << name << " " << nums << std::endl;
}
}
std::map<std::string, int> DRC::getDrcResult()
{
std::map<std::string, int> viotype_to_nums_map;
_region_query->getRegionReport(viotype_to_nums_map);
return viotype_to_nums_map;
}
std::map<std::string, std::vector<DrcViolationSpot*>> DRC::getDrcDetailResult()
{
std::map<std::string, std::vector<DrcViolationSpot*>> vio_map;
_region_query->getRegionDetailReport(vio_map);
return vio_map;
}
/**
* @brief Interaction interface with iRT
*
* @param layer_to_rects_rtree_map The region routing result of iRT, including conductor information of multiple layers
* @return std::vector<std::pair<DrcRect*, DrcRect*>> A list of rectangle pairs that have spacing or short violations
*/
// std::vector<std::pair<DrcRect*, DrcRect*>> DRC::checkiRTResult(const LayerNameToRTreeMap& layer_to_rects_rtree_map)
// {
// update();
// _routing_sapcing_check->switchToiRTMode();
// _routing_sapcing_check->checkRoutingSpacing(layer_to_rects_rtree_map);
// return _routing_sapcing_check->get_violation_rect_pair_list();
// }
////////////////////////////////////////
////////////////////////////////////////
/////////////////////////private function
void DRC::clearRoutingShapesInDrcNetList()
{
for (auto& drc_net : _drc_design->get_drc_net_list()) {
drc_net->clear_layer_to_routing_rects_map();
drc_net->clear_layer_to_merge_polygon_list();
drc_net->clear_layer_to_routing_polygon_set();
}
}
// void DRC::checkMultipatterning(int check_colorable_num)
// {
// _multi_patterning->set_conflict_graph(_conflict_graph);
// _multi_patterning->checkMultiPatterning(check_colorable_num);
// }
// ////////////////////////////////////////////
// //////debug
// void DRC::printRTree()
// {
// _region_query->printRoutingRectsRTree();
// _region_query->printFixedRectsRTree();
// }
} // namespace idrc

View File

@ -1,168 +0,0 @@
// ***************************************************************************************
// 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 <assert.h>
#include <any>
#include "data/basic/BoostType.h"
namespace idb {
class IdbBuilder;
}
namespace idrc {
class DrcConfig;
class DrcDesign;
class Tech;
class RoutingSpacingCheck;
class CutSpacingCheck;
class RoutingWidthCheck;
class EnclosedAreaCheck;
class RoutingAreaCheck;
class EnclosureCheck;
class NotchSpacingCheck;
class MinStepCheck;
class CornerFillSpacingCheck;
class CutEolSpacingCheck;
class JogSpacingCheck;
class DrcSpot;
class DrcRect;
class DrcPolygon;
class RegionQuery;
class IDRWrapper;
class DrcIDBWrapper;
class DrcNet;
class SpotParser;
class MultiPatterning;
class DrcConflictGraph;
class EOLSpacingCheck;
class DrcViolationSpot;
#define DrcInst (idrc::DRC::getInst())
class DRC
{
public:
static DRC& getInst();
static void destroyInst();
DRC();
~DRC() {}
DRC(const DRC& in) {}
// Initialize iDRC using the configuration file
void initDRC(std::string& drc_config_path, idb::IdbBuilder* idb_builder = nullptr);
// Initialize using DataManager
void initDRC();
// Check DEF initialization
void initDesign(std::map<std::string, std::any> config_map);
// Initialize design rule data in Tech, either through the configuration file or idb_builder pointer
// void initTechFromIDB(std::string& drc_config_path);
void initTechFromIDB(idb::IdbBuilder* idb_builder);
// Interface for interaction with iRT
std::vector<std::pair<DrcRect*, DrcRect*>> checkiRTResult(const LayerNameToRTreeMap& layer_to_rects_rtree_map);
// void checkViolationInRRNetList(std::vector<idr::RRNet>& rr_net_list);
// Update the process data and stored results of the current design rule check modules for the next round of checks
void update();
// Initialize each design rule check module
void initCheckModule();
// Run each design rule check module
void run();
// Report design rule violations in a file
void report();
std::map<std::string, int> getDrcResult();
std::map<std::string, std::vector<DrcViolationSpot*>> getDrcDetailResult();
// // Perform design rule check on the target net
// void checkTargetNet(int netId);
// Get the number of design rule violations in DEF file mode
// int getShortViolationNum();
// int getSpacingViolationNum();
// int getWidthViolationNum();
// int getAreaViolationNum();
// int getEnclosedAreaViolationNum();
// // Get the list of spots under each design rule check module
// std::map<int, std::vector<DrcSpot>>& getShortSpotList();
// std::map<int, std::vector<DrcSpot>>& getSpacingSpotList();
// std::map<int, std::vector<DrcSpot>>& getWidthSpotList();
// std::map<int, std::vector<DrcSpot>>& getAreaSpotList();
// std::map<int, std::vector<DrcSpot>>& getEnclosedAreaSpotList();
// // debug
// void printRTree();
// void getObjectNum();
///////multi patterning
// void checkMultipatterning(int check_colorable_num);
// getter
DrcConfig* get_config() { return _config; }
DrcDesign* get_drc_design() { return _drc_design; }
RegionQuery* get_region_query() { return _region_query; }
Tech* get_tech() { return _tech; }
////////////////// useless ///////////////////////////////////
// init drc polygon
// void initDesignBlockPolygon();
// void initNetsMergePolygon();
// void initNetMergePolygon(DrcNet* net);
// void bindRectangleToPolygon(DrcPolygon* polygon);
// void initNetMergePolyEdge(DrcPolygon* polygon); // not use now
// init conflict graph by polygon
// void initConflictGraphByPolygon();
/////////////////// useless ///////////////////////////////////
////////////////////////////
private:
static DRC* _drc_instance;
DrcConfig* _config;
DrcDesign* _drc_design;
Tech* _tech;
IDRWrapper* _idr_wrapper;
DrcIDBWrapper* _idb_wrapper;
RegionQuery* _region_query;
JogSpacingCheck* _jog_spacing_check;
NotchSpacingCheck* _notch_spacing_check;
MinStepCheck* _min_step_check;
CornerFillSpacingCheck* _corner_fill_spacing_check;
CutEolSpacingCheck* _cut_eol_spacing_check;
RoutingSpacingCheck* _routing_sapcing_check;
EOLSpacingCheck* _eol_spacing_check;
RoutingAreaCheck* _routing_area_check;
RoutingWidthCheck* _routing_width_check;
CutSpacingCheck* _cut_spacing_check;
EnclosedAreaCheck* _enclosed_area_check;
EnclosureCheck* _enclosure_check;
SpotParser* _spot_parser;
DrcConflictGraph* _conflict_graph;
MultiPatterning* _multi_patterning;
// function
void clearRoutingShapesInDrcNetList();
// void addSegmentToDrcPolygon(const BoostSegment& segment, DrcPolygon* polygon);
// void initNetMergePolyEdgeOuter(DrcPolygon* polygon, std::set<int>& x_value_list, std::set<int>& y_value_list);
// void initNetMergePolyEdgeInner(DrcPolygon* polygon, std::set<int>& x_value_list, std::set<int>& y_value_list);
};
} // namespace idrc

View File

@ -1,184 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
// #include "CutSpacingCheck.hpp"
// #include "DRC.h"
// #include "DrcConfig.h"
// #include "DrcConfigurator.h"
// #include "DrcDesign.h"
// #include "DrcIDBWrapper.h"
// #include "EnclosedAreaCheck.h"
// #include "EnclosureCheck.hpp"
// #include "IDRWrapper.h"
// #include "MultiPatterning.h"
// #include "RegionQuery.h"
// #include "RoutingAreaCheck.h"
// #include "RoutingSpacingCheck.h"
// #include "RoutingWidthCheck.h"
// #include "SpotParser.h"
// #include "Tech.h"
// namespace idrc {
// void DRC::initDesignBlockPolygon()
// {
// std::vector<PolygonWithHoles> poly_with_holes_list;
// for (auto& [layerId, polyset] : _drc_design->get_blockage_polygon_set_list()) {
// poly_with_holes_list.clear();
// polyset.get(poly_with_holes_list);
// for (auto& poly_with_holes : poly_with_holes_list) {
// DrcPolygon* polygon = _drc_design->add_blockage_polygon(layerId, poly_with_holes);
// bindRectangleToPolygon(polygon);
// }
// }
// _drc_design->clear_blockage_polygon_set_list();
// }
// void DRC::initNetsMergePolygon()
// {
// for (auto& net : _drc_design->get_drc_net_list()) {
// initNetMergePolygon(net);
// net->clear_layer_to_routing_polygon_set();
// net->clear_layer_to_pin_polygon_set();
// }
// }
// void DRC::initNetMergePolygon(DrcNet* net)
// {
// std::set<int> layer_id_list = net->get_layer_id_list();
// std::vector<PolygonWithHoles> poly_with_holes_list;
// for (int layerId : layer_id_list) {
// poly_with_holes_list.clear();
// PolygonSet poly_set;
// // merge
// poly_set += net->get_routing_polygon_set(layerId);
// poly_set += net->get_pin_polygon_set(layerId);
// poly_set.get(poly_with_holes_list);
// for (auto& poly_with_holes : poly_with_holes_list) {
// DrcPolygon* merge_poly = net->add_merge_polygon(layerId, poly_with_holes);
// merge_poly->set_net_id(net->get_net_id());
// bindRectangleToPolygon(merge_poly);
// // initNetMergePolyEdge(merge_poly);
// }
// }
// }
// void DRC::bindRectangleToPolygon(DrcPolygon* polygon)
// {
// PolygonWithHoles poly_with_hole = polygon->get_polygon();
// PolygonSet polyset1;
// polyset1 += poly_with_hole;
// /////////////////////////////////////////////////
// BoostRect query_rect;
// bp::extents(query_rect, poly_with_hole);
// RTreeBox query_box = DRCUtil::getRTreeBox(query_rect);
// std::vector<std::pair<RTreeBox, DrcRect*>> query_result;
// _region_query->queryInRoutingLayer(polygon->get_layer_id(), query_box, query_result);
// for (auto& [box, rect] : query_result) {
// if (rect->get_net_id() != polygon->get_net_id()) {
// continue;
// }
// BoostRect result_rect = DRCUtil::getBoostRect(rect);
// PolygonSet polyset2;
// polyset2 += result_rect;
// // can`t 1 interact 2
// if (!(polyset2.interact(polyset1).empty())) {
// rect->set_owner_polygon(polygon);
// }
// }
// }
// void DRC::getObjectNum()
// {
// int blockage_num = 0;
// for (auto& [layerId, rectList] : _drc_design->get_layer_to_blockage_list()) {
// blockage_num += rectList.size();
// }
// int routing_shape_num = 0;
// int pin_shape_num = 0;
// for (auto& net : _drc_design->get_drc_net_list()) {
// for (auto& [layerId, shape_list] : net->get_layer_to_routing_rects_map()) {
// routing_shape_num += shape_list.size();
// }
// for (auto& [layerId, shape_list] : net->get_layer_to_pin_rects_map()) {
// pin_shape_num += shape_list.size();
// }
// }
// std::cout << "Pin num : " << pin_shape_num << std::endl;
// std::cout << "via and segment num : " << routing_shape_num << std::endl;
// std::cout << "blockage num : " << blockage_num << std::endl;
// }
////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////not use now
// void DRC::initNetMergePolyEdgeOuter(DrcPolygon* polygon, std::set<int>& x_value_list, std::set<int>& y_value_list)
// {
// PolygonWithHoles poly_with_hole = polygon->get_polygon();
// // skip the first point
// auto outerIt = poly_with_hole.begin();
// BoostPoint first_point((*outerIt).x(), (*outerIt).y());
// BoostPoint begin_temp_point((*outerIt).x(), (*outerIt).y());
// x_value_list.insert((*outerIt).x());
// y_value_list.insert((*outerIt).y());
// BoostPoint end_temp_point;
// ++outerIt;
// for (; outerIt != poly_with_hole.end(); ++outerIt) {
// end_temp_point.x((*outerIt).x());
// end_temp_point.y((*outerIt).y());
// x_value_list.insert((*outerIt).x());
// y_value_list.insert((*outerIt).y());
// BoostSegment segment(begin_temp_point, end_temp_point);
// addSegmentToDrcPolygon(segment, polygon);
// begin_temp_point = end_temp_point;
// }
// BoostSegment last_segment(begin_temp_point, first_point);
// addSegmentToDrcPolygon(last_segment, polygon);
// }
// void DRC::initNetMergePolyEdgeInner(DrcPolygon* polygon, std::set<int>& x_value_list, std::set<int>& y_value_list)
// {
// // Todo
// }
// void DRC::initNetMergePolyEdge(DrcPolygon* polygon)
// {
// std::set<int> x_value_list;
// std::set<int> y_value_list;
// initNetMergePolyEdgeOuter(polygon, x_value_list, y_value_list);
// // Todo initNetMergePolyEdgeInner
// // Todo initEdgeWidth
// }
// void DRC::addSegmentToDrcPolygon(const BoostSegment& segment, DrcPolygon* polygon)
// {
// // std::unique_ptr<DrcEdge> drcEdge = std::make_unique<DrcEdge>(segment);
// // DrcEdge* drc_edge = drcEdge.get();
// // Todo set edge direct!!!!!!!!
// // drc_edge->set_owner_polygon(polygon);
// // polygon->add_polygon_edge(drcEdge);
// // _region_query->add_routing_edge_to_rtree(polygon->get_layer_id(), drc_edge);
// }
// void DRC::initConflictGraphByPolygon()
// {
// _routing_sapcing_check->initConflictGraphByPolygon();
// }
// } // namespace idrc

View File

@ -1,16 +0,0 @@
add_library(idrc_config
DrcConfigurator.cpp
)
target_include_directories(idrc_config
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${HOME_OPERATION}/iDRC/source/util
)
target_link_libraries(idrc_config
PRIVATE
)

View File

@ -1,56 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_CFG_DRC_CONFIG_H_
#define IDRC_SRC_CFG_DRC_CONFIG_H_
#include <map>
#include <string>
#include <vector>
namespace idrc {
class DrcConfig
{
public:
DrcConfig() {}
~DrcConfig() {}
// getter
std::vector<std::string>& get_lef_paths() { return _lef_paths; }
std::string& get_def_path() { return _def_path; }
// OUTPUT
std::string& get_output_dir_path() { return _output_dir_path; }
// setter
// INPUT
void set_lef_paths(const std::vector<std::string>& lef_paths) { _lef_paths = lef_paths; }
void set_def_path(const std::string& def_path) { _def_path = def_path; }
// OUTPUT
void set_output_dir_path(const std::string& output_dir_path) { _output_dir_path = output_dir_path; }
// function
private:
// INPUT
std::vector<std::string> _lef_paths;
std::string _def_path;
// OUTPUT
std::string _output_dir_path;
};
} // namespace idrc
#endif // IDR_SRC_CFG_CONFIG_H_

View File

@ -1,102 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DrcConfigurator.h"
namespace idrc {
void DrcConfigurator::set(DrcConfig* config, std::string& drc_config_path)
{
initConfig(config, drc_config_path);
// checkConfig(config);
printConfig(config);
}
void DrcConfigurator::initConfig(DrcConfig* config, std::string& drc_config_path)
{
std::ifstream drc_config_stream(drc_config_path);
if (drc_config_stream) {
nlohmann::json json;
// read a JSON file
drc_config_stream >> json;
// std::cout << "[Configurator Info] The configuration file '" << drc_config_path << "' is read successfully!" << std::endl;
initConfigByJson(config, json);
} else {
std::cout << "[Configurator Error] Failed to read configuration file '" << drc_config_path << "'!" << std::endl;
exit(1);
}
drc_config_stream.close();
}
void DrcConfigurator::initConfigByJson(DrcConfig* config, nlohmann::json& json)
{
// *************** INPUT ***************
std::vector<std::string>& lef_paths = config->get_lef_paths();
lef_paths.emplace_back(getDataByJson(json, {"INPUT", "tech_lef_path"}));
for (std::string lef_path : getDataByJson(json, {"INPUT", "lef_paths"})) {
lef_paths.emplace_back(lef_path);
}
config->set_def_path(getDataByJson(json, {"INPUT", "def_path"}));
// ***************OUTPUT ***************
// config->set_output_dir_path(getDataByJson(json, {"OUTPUT", "output_dir_path"}));
}
nlohmann::json DrcConfigurator::getDataByJson(nlohmann::json value, std::vector<std::string> ftag_list)
{
int ftag_size = ftag_list.size();
if (ftag_size == 0) {
std::cout << "[Configurator Error] The number of json ftag is zero!" << std::endl;
exit(1);
}
for (int i = 0; i < ftag_size; i++) {
value = value[ftag_list[i]];
}
if (!value.is_null()) {
return value;
}
std::cout << "[Configurator Error] The configuration file key=[";
for (int i = 0; i < ftag_size; i++) {
std::cout << ftag_list[i];
if (i < ftag_size - 1) {
std::cout << ".";
}
}
std::cout << "] is null! exit..." << std::endl;
exit(1);
}
void DrcConfigurator::checkConfig(DrcConfig* config)
{
}
void DrcConfigurator::printConfig(DrcConfig* config)
{
return;
// std::cout << "[Configurator Info] lef_paths:" << std::endl;
// std::vector<std::string>& lef_paths = config->get_lef_paths();
// for (size_t i = 0; i < lef_paths.size(); i++) {
// std::cout << "[Configurator Info] " << lef_paths[i] << std::endl;
// }
// std::cout << "[Configurator Info] def_path: " << std::endl;
// std::cout << "[Configurator Info] " << config->get_def_path() << std::endl;
// std::cout << "[Configurator Info] output_dir_path: " << std::endl;
// std::cout << "[Configurator Info] " << config->get_output_dir_path() << std::endl;
}
} // namespace idrc

View File

@ -1,57 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_CFG_CONFIGURATOR_H_
#define IDRC_SRC_CFG_CONFIGURATOR_H_
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include "DRCCOMUtil.h"
#include "DrcConfig.h"
#include "json.hpp"
namespace idrc {
class DrcConfigurator
{
public:
explicit DrcConfigurator() {}
DrcConfigurator(const DrcConfigurator& other) = delete;
DrcConfigurator(DrcConfigurator&& other) = delete;
~DrcConfigurator() {}
DrcConfigurator& operator=(const DrcConfigurator& other) = delete;
DrcConfigurator& operator=(DrcConfigurator&& other) = delete;
// getter
// setter
// function
void set(DrcConfig* config, std::string& drc_config_path);
private:
// function
void initConfig(DrcConfig* config, std::string& dr_config_path);
void initConfigByJson(DrcConfig* config, nlohmann::json& json);
nlohmann::json getDataByJson(nlohmann::json value, std::vector<std::string> flag_list);
void checkConfig(DrcConfig* config);
void printConfig(DrcConfig* config);
};
} // namespace idrc
#endif // IDR_ACTION_CONFIGURATOR_H_

View File

@ -1,14 +0,0 @@
{
"INPUT": {
"tech_lef_path": "<tech_lef_path>",
"lef_paths": [
"<lef_path1>",
"<lef_path2>",
"<lef_path3>"
],
"def_path": "<def_path>"
},
"OUTPUT": {
"output_dir_path": "<output_dir_path>"
}
}

View File

@ -1,26 +0,0 @@
add_library(idrc_db
DrcIDBWrapper.cpp
IDRWrapper.cpp
basic/DrcNet.cpp
basic/DrcConflictGraph.cpp
basic/Tech.cpp
basic/DrcLayer.cpp
)
target_include_directories(idrc_db
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/rule
${CMAKE_CURRENT_SOURCE_DIR}/basic
${HOME_OPERATION}/iDRC/source/util
${HOME_OPERATION}/iDRC/source/config
)
target_link_libraries(idrc_db
PRIVATE
idrc_config
idrc_region_query
)

File diff suppressed because it is too large Load Diff

View File

@ -1,172 +0,0 @@
// ***************************************************************************************
// 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 <set>
#include "BoostType.h"
#include "DRCCOMUtil.h"
#include "DrcConfig.h"
#include "DrcDesign.h"
#include "DrcPoly.hpp"
#include "DrcRules.hpp"
#include "RegionQuery.h"
#include "Tech.h"
#include "builder.h"
#include "def_service.h"
#include "lef_service.h"
namespace idrc {
class DrcIDBWrapper
{
public:
explicit DrcIDBWrapper() {}
DrcIDBWrapper(DrcConfig* config, Tech* tech) : _config(config), _tech(tech) {}
DrcIDBWrapper(DrcConfig* config, Tech* tech, DrcDesign* design, RegionQuery* region_query)
: _config(config), _tech(tech), _design(design), _region_query(region_query)
{
}
DrcIDBWrapper(Tech* tech, DrcDesign* design, idb::IdbBuilder* in, RegionQuery* region_query)
: _tech(tech), _design(design), _region_query(region_query), _db_builder(in)
{
}
DrcIDBWrapper(Tech* tech, idb::IdbBuilder* in) : _tech(tech), _db_builder(in) {}
DrcIDBWrapper(RegionQuery* region_query) : _region_query(region_query) {}
DrcIDBWrapper(const DrcIDBWrapper& other) = delete;
DrcIDBWrapper(DrcIDBWrapper&& other) = delete;
~DrcIDBWrapper()
{
// if (_db_builder != nullptr) {
// delete _db_builder;
// }
}
DrcIDBWrapper& operator=(const DrcIDBWrapper& other) = delete;
DrcIDBWrapper& operator=(DrcIDBWrapper&& other) = delete;
// getter
DrcConfig* get_config() { return _config; }
Tech* get_tech() { return _tech; }
DrcDesign* get_design() { return _design; }
// setter
// function
void input(idb::IdbBuilder* idb_builder = nullptr);
void initTech(idb::IdbBuilder* db_builder = nullptr);
void wrapTech();
void wrapDesign();
// init polys
void initPolyPolygon(DrcNet* net);
void initPolyEdges(DrcNet* net);
void initPolyCorners(DrcNet* net);
void initPolyMaxRects(DrcNet* net);
void getAllPolygonEdges(DrcNet* net, std::vector<std::set<std::pair<DrcCoordinate<int>, DrcCoordinate<int>>>>& polygon_edges);
void initPolyOuterEdges(DrcNet* net, DrcPoly* poly, DrcPolygon* polygon, int layer_id);
void initPolyInnerEdges(DrcNet* net, DrcPoly* poly, const BoostPolygon& hole_poly, int layer_id);
void initPolyCornerMain(DrcNet* net, DrcPoly* poly);
protected:
// parser
void initIDB(idb::IdbBuilder* db_builder);
void initIDBLayout();
void wrap();
void wrapRoutingLayerList();
void wrapCutLayerList();
void wrapViaLib();
void wrapBlockageList();
void wrapNetList();
void wrapNetPolyList();
DrcNet* get_drc_net(int netId);
private:
DrcConfig* _config = nullptr;
Tech* _tech = nullptr;
DrcDesign* _design = nullptr;
RegionQuery* _region_query = nullptr;
idb::IdbBuilder* _db_builder = nullptr;
std::map<int, DrcNet*> _id_to_net;
/// basic rect wrap function
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/// tech
void wrapRect(DrcRectangle<int>& rect, idb::IdbRect* idb_rect)
{
if (idb_rect == nullptr) {
return;
}
rect.set_lb(idb_rect->get_low_x(), idb_rect->get_low_y());
rect.set_rt(idb_rect->get_high_x(), idb_rect->get_high_y());
}
// getter
idb::IdbBuilder* get_idb_builder() { return _db_builder; }
idb::IdbDesign* get_idb_design() { return _db_builder->get_def_service()->get_design(); }
idb::IdbLayout* get_idb_layout() { return _db_builder->get_lef_service()->get_layout(); }
void wrapRoutingLayer(idb::IdbLayerRouting* idb_routing_layer, DrcRoutingLayer* layer);
void wrapCutLayer(idb::IdbLayerCut* idb_cut_layer, DrcCutLayer* layer);
void wrapVia(idb::IdbVia* idb_via, std::vector<DrcVia*>& via_list);
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
/// design
// rect convert
void wrapRect(DrcRect* drc_rect, idb::IdbRect* idb_rect);
BoostRect getBoostRectFromIdbRect(idb::IdbRect* idb_rect);
// blockage list in def
void wrapBlockageListInDef();
void addPlacementBlockage(idb::IdbPlacementBlockage* idb_blockage, DrcDesign* design);
void addRoutingBlockage(idb::IdbRoutingBlockage* idb_blockage, DrcDesign* design);
void addIdbBlockToDrcDesign(idb::IdbBlockage* idb_blockage, DrcDesign* design);
// instance as blockage
void wrapInstanceListBlockage();
void addInstanceBlockage(idb::IdbInstance* idb_instance, DrcDesign* design);
void addInstanceObsBlockage(idb::IdbInstance* idb_instance, DrcDesign* design);
void addInstancePinBlockage(idb::IdbInstance* idb_instance, DrcDesign* design);
// specialnets as blokage
void wrapSpecialNetListBlockage();
void addSpecialNetBlockage(idb::IdbSpecialNet* idb_net, DrcDesign* design);
void addSpecialNetViaBlockage(idb::IdbSpecialWireSegment* idb_segment, DrcDesign* design);
void addSpecialNetWireBlockage(idb::IdbSpecialWireSegment* idb_segment, DrcDesign* design);
/// basic blockage wrap function
void wrapBlockageFromLayerShape(idb::IdbLayerShape* layer_shape, DrcDesign* design);
// net
bool addNetToDrcDesign(idb::IdbNet* idb_net, DrcDesign* design);
// pin shape
bool addPinListToNet(vector<idb::IdbPin*>& idb_pin_list, DrcNet* drc_net);
bool addPinToNet(idb::IdbPin* idb_pin, DrcNet* drc_net);
bool addPortToNet(idb::IdbLayerShape* idb_shape, DrcNet* drc_net);
// segment via
bool addWireListToNet(vector<idb::IdbRegularWire*> idb_wire_list, DrcNet* drc_net);
bool addWireToNet(idb::IdbRegularWire* idb_wire, DrcNet* drc_net);
bool addIdbSegmentToNet(idb::IdbRegularWireSegment* idb_segment, DrcNet* drc_net);
bool addViaToNet(idb::IdbRegularWireSegment* idb_segment, DrcNet* drc_net);
bool addSegmentToNet(idb::IdbRegularWireSegment* idb_segment, DrcNet* drc_net);
/// basic routing shape wrap function
void addViaShapeToNet(idb::IdbLayerShape* layer_shape, DrcNet* drc_net, idb::IdbCoordinate<int32_t>* center_point, bool is_cut);
void addSegmentShapeToNet(int layer_id, int layer_order, idb::IdbCoordinate<int32_t>* start, idb::IdbCoordinate<int32_t>* end,
DrcNet* drc_net);
void addRectShapeToNet(idb::IdbRegularWireSegment* idb_segment, DrcNet* drc_net);
};
} // namespace idrc

View File

@ -1,381 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "IDRWrapper.h"
namespace idrc {
/**
* @brief initialize all fix shape in drc_design
*
* @param dr_design
*/
// void IDRWrapper::inputAndInitFixedShapes(idr::Design* dr_design)
// {
// double start = 0.0;
// double end = 0.0;
// start = DRCCOMUtil::microtime();
// set_dr_design(dr_design);
// wrapPinListAndBlockageList();
// end = DRCCOMUtil::microtime();
// std::cout << "[IDRWrapper Info] \033[1;32mTotal elapsed time:" << (end - start) << "s \033[0m\n";
// }
// void IDRWrapper::wrapPinListAndBlockageList()
// {
// wrapNetPinList();
// wrapBlockageList();
// }
/**
* @brief initialize all routing shape in drc_design from region router
*
* @param sub_net_list
*/
// void IDRWrapper::inputAndInitRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list)
// {
// for (auto& sub_net : sub_net_list) {
// DrcNet* drc_net = get_drc_net(sub_net.get_rr_net_idx());
// wrapSegmentsAndVias(drc_net, sub_net);
// }
// }
// void IDRWrapper::wrapSegmentsAndVias(DrcNet* drc_net, idr::RRSubNet& sub_net)
// {
// // std::vector<idr::SpaceSegment<idr::RRPoint>> dr_space_segment_list = sub_net.get_best_routing_seg_list();
// std::vector<idr::SpaceSegment<idr::RRPoint>> dr_space_segment_list = sub_net.get_curr_seg_list();
// for (auto& dr_space_segment : dr_space_segment_list) {
// if (dr_space_segment.is_via()) {
// wrapNetVia(dr_space_segment, drc_net);
// } else if (dr_space_segment.is_wiring()) {
// wrapNetSegment(dr_space_segment, drc_net);
// }
// }
// }
// void IDRWrapper::inputAndInitCurrentRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list)
// {
// for (auto& sub_net : sub_net_list) {
// DrcNet* drc_net = get_drc_net(sub_net.get_rr_net_idx());
// std::vector<idr::SpaceSegment<idr::RRPoint>> dr_space_segment_list = sub_net.get_curr_seg_list();
// wrapSegmentsAndVias(drc_net, dr_space_segment_list);
// }
// }
// void IDRWrapper::inputAndInitBestRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list)
// {
// for (auto& sub_net : sub_net_list) {
// DrcNet* drc_net = get_drc_net(sub_net.get_rr_net_idx());
// std::vector<idr::SpaceSegment<idr::RRPoint>> dr_space_segment_list = sub_net.get_best_routing_seg_list();
// wrapSegmentsAndVias(drc_net, dr_space_segment_list);
// }
// }
// void IDRWrapper::inputAndInitRoutingShapesInRRNetList(std::vector<idr::RRNet>& rr_net_list)
// {
// for (auto& rr_net : rr_net_list) {
// DrcNet* drc_net = get_drc_net(rr_net.get_net_idx());
// std::vector<idr::SpaceSegment<idr::RRPoint>> dr_space_segment_list = rr_net.get_routing_seg_list();
// wrapSegmentsAndVias(drc_net, dr_space_segment_list);
// }
// }
// void IDRWrapper::wrapSegmentsAndVias(DrcNet* drc_net, std::vector<idr::SpaceSegment<idr::RRPoint>>& dr_space_segment_list)
// {
// for (auto& dr_space_segment : dr_space_segment_list) {
// if (dr_space_segment.is_via()) {
// wrapNetVia(dr_space_segment, drc_net);
// } else if (dr_space_segment.is_wiring()) {
// wrapNetSegment(dr_space_segment, drc_net);
// }
// }
// }
////wrap rect
// void IDRWrapper::wrapRect(DrcRectangle<int>& rect, idr::Rectangle<int>& dr_rect)
// {
// rect.set_lb(dr_rect.get_lb_x(), dr_rect.get_lb_y());
// rect.set_rt(dr_rect.get_rt_x(), dr_rect.get_rt_y());
// }
// void IDRWrapper::wrapRect(DrcRect* drc_rect, idr::Rectangle<int>& dr_rect)
// {
// if (drc_rect == nullptr) {
// std::cout << "[IDRWrapper error:drc_rect is null]" << std::endl;
// return;
// }
// drc_rect->set_lb(dr_rect.get_lb_x(), dr_rect.get_lb_y());
// drc_rect->set_rt(dr_rect.get_rt_x(), dr_rect.get_rt_y());
// }
/**
* @brief wrap Blockage List
*
*/
// void IDRWrapper::wrapBlockageList()
// {
// DrcDesign* drc_design = get_drc_design();
// std::vector<idr::Blockage> _idr_blockage_list = _dr_design->get_blockage_list();
// // std::cout<<"block_list.size is :: "<<_idr_blockage_list.size()<<std::endl;
// for (auto& dr_block : _idr_blockage_list) {
// DrcRect* drc_block = new DrcRect();
// wrapBlockage(dr_block, drc_block);
// int layerId = drc_block->get_layer_id();
// drc_design->add_blockage(layerId, drc_block);
// _region_query->add_fixed_rect_to_rtree(layerId, drc_block);
// }
// }
// void IDRWrapper::wrapBlockage(idr::Blockage& dr_block, DrcRect* drc_block)
// {
// int layerId = dr_block.get_layer_idx() + 1;
// drc_block->set_owner_type(RectOwnerType::kBlockage);
// drc_block->set_layer_id(layerId);
// drc_block->set_is_fixed(true);
// wrapRect(drc_block, dr_block.get_region());
// }
/**
* @brief wrap Net Pin List
*
*/
// void IDRWrapper::wrapNetPinList()
// {
// std::vector<idr::Net> _idr_net_list = _dr_design->get_net_list();
// for (auto& dr_net : _idr_net_list) {
// DrcNet* drc_net = get_drc_net(dr_net.get_net_idx());
// wrapNetPinList(dr_net, drc_net);
// }
// }
// void IDRWrapper::wrapNetPinList(idr::Net& dr_net, DrcNet* drc_net)
// {
// std::vector<idr::Pin> dr_pin_list = dr_net.get_pin_list();
// for (auto& dr_pin : dr_pin_list) {
// std::vector<idr::Port> dr_port_list = dr_pin.get_port_list();
// for (auto& dr_port : dr_port_list) {
// int layer_id = dr_port.get_layer_idx() + 1;
// for (auto& dr_rect : dr_port.get_port_shape()) {
// DrcRectangle<int> rect;
// wrapRect(rect, dr_rect);
// DrcRect* pin_rect = new DrcRect(layer_id, rect);
// pin_rect->set_net_id(drc_net->get_net_id());
// pin_rect->set_owner_type(RectOwnerType::kPin);
// pin_rect->set_is_fixed(true);
// drc_net->add_pin_rect(layer_id, pin_rect);
// _region_query->add_fixed_rect_to_rtree(layer_id, pin_rect);
// }
// }
// }
// }
/**
* @brief transform dr_space_segment to drc rect
*
* @param dr_space_segment_list
* @param drc_net
*/
// void IDRWrapper::wrapNetVia(idr::SpaceSegment<idr::RRPoint>& dr_space_segment, DrcNet* drc_net)
// {
// Tech* tech = get_tech();
// // via_idx should match with in tech
// int dr_via_idx = dr_space_segment.get_via_lib_idx();
// idr::RRPoint first_point = dr_space_segment.get_segment().get_first();
// idr::Coordinate<int> dr_via_coor = first_point.get_coord();
// // via_idx in dr should match with in tech
// DrcVia* via = tech->findViaByIdx(dr_via_idx);
// // bottom
// DrcEnclosure bottom_enclosure = via->get_bottom_enclosure();
// DrcRect* drc_via_bottom = getViaMetalRect(dr_via_coor.get_x(), dr_via_coor.get_y(), bottom_enclosure);
// if (drc_via_bottom != nullptr) {
// drc_via_bottom->set_net_id(drc_net->get_net_id());
// drc_via_bottom->set_via_idx(via->get_via_idx());
// drc_net->add_routing_rect(drc_via_bottom->get_layer_id(), drc_via_bottom);
// _region_query->add_routing_rect_to_rtree(drc_via_bottom->get_layer_id(), drc_via_bottom);
// }
// top
// DrcEnclosure top_enclosure = via->get_top_enclosure();
// DrcRect* drc_via_top = getViaMetalRect(dr_via_coor.get_x(), dr_via_coor.get_y(), top_enclosure);
// if (drc_via_top != nullptr) {
// drc_via_top->set_net_id(drc_net->get_net_id());
// drc_via_top->set_via_idx(via->get_via_idx());
// drc_net->add_routing_rect(drc_via_top->get_layer_id(), drc_via_top);
// _region_query->add_routing_rect_to_rtree(drc_via_top->get_layer_id(), drc_via_top);
// }
// }
// DrcRect* IDRWrapper::getViaMetalRect(int center_x, int center_y, DrcEnclosure& enclosure)
// {
// int layerId = enclosure.get_layer_idx();
// int lb_x = enclosure.get_shape().get_lb_x() + center_x;
// int lb_y = enclosure.get_shape().get_lb_y() + center_y;
// int rt_x = enclosure.get_shape().get_rt_x() + center_x;
// int rt_y = enclosure.get_shape().get_rt_y() + center_y;
// DrcRectangle<int> rectangle(lb_x, lb_y, rt_x, rt_y);
// // Detection and de duplication
// if (_region_query->isExistingRectangleInRoutingRTree(layerId, rectangle)) {
// // std::cout << "[DRC IDRWrapper Info]:Duplicate Rectangle From Via" << std::endl;
// return nullptr;
// }
// DrcRect* drc_via_metal_rect = new DrcRect(layerId, rectangle);
// drc_via_metal_rect->set_owner_type(RectOwnerType::kViaMetal);
// drc_via_metal_rect->set_is_fixed(false);
// return drc_via_metal_rect;
// }
// /**
// * @brief transform dr_space_segment to drc rect
// *
// * @param dr_space_segment
// * @param drc_net
// */
// void IDRWrapper::wrapNetSegment(idr::SpaceSegment<idr::RRPoint>& dr_space_segment, DrcNet* drc_net)
// {
// idr::Segment<idr::RRPoint> dr_segment = dr_space_segment.get_segment();
// idr::RRPoint first_point = dr_segment.get_first();
// idr::RRPoint second_point = dr_segment.get_second();
// // segment begin and end
// int begin_x = std::min(first_point.get_coord().get_x(), second_point.get_coord().get_x());
// int begin_y = std::min(first_point.get_coord().get_y(), second_point.get_coord().get_y());
// int end_x = std::max(first_point.get_coord().get_x(), second_point.get_coord().get_x());
// int end_y = std::max(first_point.get_coord().get_y(), second_point.get_coord().get_y());
// int layerId = first_point.get_layer_idx() + 1;
// int wire_width = dr_space_segment.get_wire_width();
// DrcRectangle<int> rectangle(begin_x - wire_width / 2, begin_y - wire_width / 2, end_x + wire_width / 2, end_y + wire_width / 2);
// // Detection and de duplication
// if (_region_query->isExistingRectangleInRoutingRTree(layerId, rectangle)) {
// // std::cout << "[DRC IDRWrapper Info]:Duplicate Rectangle From Segment" << std::endl;
// return;
// }
// DrcRect* segment_rect = new DrcRect(layerId, rectangle);
// segment_rect->set_net_id(drc_net->get_net_id());
// segment_rect->set_owner_type(RectOwnerType::kSegment);
// segment_rect->set_is_fixed(false);
// drc_net->add_routing_rect(layerId, segment_rect);
// _region_query->add_routing_rect_to_rtree(layerId, segment_rect);
// }
// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////for region routing
// DrcNet* IDRWrapper::get_drc_net(int netId)
// {
// DrcNet* drc_net = nullptr;
// auto it = _id_to_net.find(netId);
// if (it == _id_to_net.end()) {
// DrcDesign* drc_design = get_drc_design();
// drc_net = drc_design->add_drc_net();
// drc_net->set_net_id(netId);
// _id_to_net[netId] = drc_net;
// } else {
// drc_net = it->second;
// }
// return drc_net;
// }
/**
* @brief wrapRoutingLayerList
*
*/
// void IDRWrapper::wrapRoutingLayerList()
// {
// Tech* tech = get_tech();
// std::vector<idr::RoutingLayer> _dr_routing_layer_list = _dr_design->get_routing_layer_list();
// for (auto& dr_routing_layer : _dr_routing_layer_list) {
// DrcRoutingLayer* drc_routing_layer = tech->add_routing_layer();
// wrapRoutingLayer(dr_routing_layer, drc_routing_layer);
// }
// }
// void IDRWrapper::wrapRoutingLayer(idr::RoutingLayer& dr_routing_layer, DrcRoutingLayer* drc_routing_layer)
// {
// drc_routing_layer->set_name(dr_routing_layer.get_layer_name());
// drc_routing_layer->set_layer_id(dr_routing_layer.get_layer_idx() + 1);
// drc_routing_layer->set_layer_type(LayerType::kRouting);
// drc_routing_layer->set_direction(dr_routing_layer.isRoutingH() ? LayerDirection::kHorizontal : LayerDirection::kVertical);
// drc_routing_layer->set_min_width(dr_routing_layer.get_min_width());
// std::vector<idr::Spacing> dr_spacing_list = dr_routing_layer.get_spacing_list();
// drc_routing_layer->set_min_spacing(dr_spacing_list.front().get_min_spacing());
// for (size_t i = 1; i < dr_spacing_list.size(); ++i) {
// SpacingRangeRule* spacing_range_rule = drc_routing_layer->add_spacing_range_rule();
// spacing_range_rule->set_min_width(dr_spacing_list[i].get_min_range());
// spacing_range_rule->set_max_width(dr_spacing_list[i].get_max_range());
// spacing_range_rule->set_spacing(dr_spacing_list[i].get_min_spacing());
// }
// }
/**
* @brief wrap Via Lib
*
*/
// void IDRWrapper::wrapViaLib()
// {
// Tech* tech = get_tech();
// std::vector<idr::Via> dr_via_list = _dr_design->get_via_lib();
// for (auto& dr_via : dr_via_list) {
// Via* via = tech->add_via();
// wrapVia(dr_via, via);
// }
// }
// void IDRWrapper::wrapVia(idr::Via& dr_via, Via* via)
// {
// if (via == nullptr) {
// std::cout << "[IDRWrapper Error] via is empty!" << std::endl;
// exit(1);
// }
// via->set_via_name(dr_via.get_via_name());
// /// set index
// via->set_via_idx(dr_via.get_via_idx());
// // set layer
// /// top
// idr::Enclosure dr_top_enclosure = dr_via.get_top_enclosure();
// Enclosure top_enclosure;
// top_enclosure.set_layer_idx(dr_top_enclosure.get_layer_idx() + 1);
// Rectangle<int> rect_top;
// wrapRect(rect_top, dr_top_enclosure.get_shape());
// top_enclosure.set_shape(rect_top);
// via->set_top_enclosure(top_enclosure);
// /// bottom
// idr::Enclosure dr_bottom_enclosure = dr_via.get_bottom_enclosure();
// Enclosure bottom_enclosure;
// bottom_enclosure.set_layer_idx(dr_bottom_enclosure.get_layer_idx() + 1);
// Rectangle<int> rect_bottom;
// wrapRect(rect_bottom, dr_bottom_enclosure.get_shape());
// bottom_enclosure.set_shape(rect_bottom);
// via->set_bottom_enclosure(bottom_enclosure);
// }
} // namespace idrc

View File

@ -1,96 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_IDRWRAPPER_H_
#define IDRC_SRC_DB_IDRWRAPPER_H_
#include "DRCCOMUtil.h"
// #include "Database.h"
#include "DrcConfig.h"
#include "DrcDesign.h"
// #include "RRNet.h"
// #include "RRSubNet.h"
#include "RegionQuery.h"
namespace idrc {
class IDRWrapper
{
public:
IDRWrapper(DrcConfig* config, Tech* tech, DrcDesign* drc_design, RegionQuery* region_query)
: _config(config), _tech(tech), _drc_design(drc_design), _region_query(region_query)
{
}
IDRWrapper(const IDRWrapper& other) = delete;
IDRWrapper(IDRWrapper&& other) = delete;
~IDRWrapper() {}
IDRWrapper& operator=(const IDRWrapper& other) = delete;
IDRWrapper& operator=(IDRWrapper&& other) = delete;
// setter
// void set_dr_design(idr::Database* dr_design) { _dr_design = dr_design; }
// // getter
// idr::Database* get_dr_design() { return _dr_design; }
// Tech* get_tech() { return _tech; }
DrcDesign* get_drc_design() { return _drc_design; }
DrcConfig* get_config() { return _config; }
// // function
// void inputAndInitFixedShapes(idr::Database* dr_design);
// // void inputAndInitRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list);
// // RRSubNet
// void inputAndInitCurrentRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list);
// void inputAndInitBestRoutingShapes(std::vector<idr::RRSubNet>& sub_net_list);
// // RRNet
// void inputAndInitRoutingShapesInRRNetList(std::vector<idr::RRNet>& rr_net_list);
DrcNet* get_drc_net(int netId);
protected:
// init for region
/// init fix shapes
void wrapPinListAndBlockageList();
void wrapBlockageList();
void wrapNetPinList();
// init routing shapes
// void wrapSegmentsAndVias(DrcNet* drc_net, idr::RRSubNet& sub_net);
// void wrapSegmentsAndVias(DrcNet* drc_net, std::vector<idr::SpaceSegment<idr::RRPoint>>& dr_space_segment_list);
// init for all layout
// void wrapBlockageList();
// void wrapNetList();
// void wrapRoutingLayerList();
// void wrapViaLib();
private:
DrcConfig* _config = nullptr;
Tech* _tech = nullptr;
DrcDesign* _drc_design = nullptr;
// idr::Database* _dr_design = nullptr;
RegionQuery* _region_query = nullptr;
std::map<int, DrcNet*> _id_to_net;
// function
// void wrapBlockage(idr::Blockage& dr_block, DrcRect* drc_block);
// void wrapNetPinList(idr::Net& dr_net, DrcNet* drc_net);
// void wrapRect(DrcRectangle<int>& rect, idr::Rectangle<int>& dr_rect);
// void wrapRect(DrcRect* drc_rect, idr::Rectangle<int>& dr_rect);
// void wrapNetVia(idr::SpaceSegment<idr::RRPoint>& dr_space_segment, DrcNet* drc_net);
// DrcRect* getViaMetalRect(int center_x, int center_y, DrcEnclosure& enclosure);
// void wrapNetSegment(idr::SpaceSegment<idr::RRPoint>& dr_space_segment, DrcNet* drc_net);
};
} // namespace idrc
#endif

View File

@ -1,52 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_BOOST_TYPE_H_
#define IDRC_SRC_DB_BOOST_TYPE_H_
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/polygon/polygon.hpp>
namespace idrc {
class DrcEdge;
class DrcRect;
using namespace boost::polygon::operators;
namespace bp = boost::polygon;
typedef boost::polygon::point_data<int> BoostPoint;
typedef boost::polygon::segment_data<int> BoostSegment;
typedef boost::polygon::polygon_90_data<int> BoostPolygon;
typedef boost::polygon::polygon_90_with_holes_data<int> PolygonWithHoles;
typedef boost::polygon::polygon_90_set_data<int> PolygonSet;
typedef boost::polygon::rectangle_data<int> BoostRect;
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::d2::point_xy<int, bg::cs::cartesian> RTreePoint;
typedef bg::model::segment<RTreePoint> RTreeSegment;
typedef bg::model::box<RTreePoint> RTreeBox;
typedef std::pair<RTreeSegment, DrcEdge*> rtree_edge_value;
typedef std::pair<RTreeBox, DrcRect*> rtree_rect_value;
typedef std::map<std::string, bgi::rtree<std::pair<RTreeBox, DrcRect*>, bgi::quadratic<16>>> LayerNameToRTreeMap;
typedef std::map<int, bgi::rtree<std::pair<RTreeBox, DrcRect*>, bgi::quadratic<16>>> LayerIdToRTreeMap;
typedef bgi::rtree<std::pair<RTreeBox, DrcRect*>, bgi::quadratic<16>> RectRTree;
} // namespace idrc
#endif

View File

@ -1,86 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DrcConflictGraph.h"
namespace idrc {
DrcConflictGraph::~DrcConflictGraph()
{
clearAllNode();
}
void DrcConflictGraph::clearAllNode()
{
for (auto node : _conflict_graph) {
if (node != nullptr) {
delete node;
node = nullptr;
}
}
_conflict_graph.clear();
}
// void DrcConflictGraph::addEdge(DrcRect* spot_rect, DrcRect* conflict_rect)
// {
// DrcConflictNode* spot_node = getConflictNode(spot_rect);
// DrcConflictNode* conflict_node = getConflictNode(conflict_rect);
// spot_node->addConflictNode(conflict_node);
// conflict_node->addConflictNode(spot_node);
// }
DrcConflictNode* DrcConflictGraph::getConflictNode(DrcRect* conflict_rect)
{
DrcConflictNode* conflict_node = nullptr;
if (_rect_to_node.find(conflict_rect) == _rect_to_node.end()) {
conflict_node = new DrcConflictNode(conflict_rect);
_rect_to_node[conflict_rect] = conflict_node;
_conflict_graph.push_back(conflict_node);
conflict_node->set_node_id(_conflict_graph.size());
} else {
conflict_node = _rect_to_node[conflict_rect];
}
return conflict_node;
}
// init by drc_polygon
void DrcConflictGraph::initGraph(const std::map<DrcPolygon*, std::set<DrcPolygon*>>& conflict_map)
{
std::map<DrcPolygon*, DrcConflictNode*> polygon_to_node;
for (auto& [spot_polygon, conflict_polygon_list] : conflict_map) {
DrcConflictNode* spot_node = getConflictNode(polygon_to_node, spot_polygon);
for (auto conflict_polygon : conflict_polygon_list) {
DrcConflictNode* conflict_node = getConflictNode(polygon_to_node, conflict_polygon);
spot_node->addConflictNode(conflict_node);
// conflict_node->addConflictNode(spot_node);
}
}
}
DrcConflictNode* DrcConflictGraph::getConflictNode(std::map<DrcPolygon*, DrcConflictNode*>& polygon_to_node, DrcPolygon* conflict_polygon)
{
DrcConflictNode* conflict_node = nullptr;
if (polygon_to_node.find(conflict_polygon) == polygon_to_node.end()) {
conflict_node = new DrcConflictNode(conflict_polygon);
polygon_to_node[conflict_polygon] = conflict_node;
_conflict_graph.push_back(conflict_node);
conflict_node->set_node_id(_conflict_graph.size());
} else {
conflict_node = polygon_to_node[conflict_polygon];
}
return conflict_node;
}
} // namespace idrc

View File

@ -1,57 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_CONFLICTGRAPH_H_
#define IDRC_SRC_DB_CONFLICTGRAPH_H_
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <vector>
#include "DrcConflictNode.h"
#include "DrcRect.h"
namespace idrc {
class DrcConflictGraph
{
public:
DrcConflictGraph() {}
~DrcConflictGraph();
// setter
void addNode(DrcConflictNode* conflict_node) { _conflict_graph.push_back(conflict_node); }
void set_conflict_graph(const std::vector<DrcConflictNode*>& conflict_node_list) { _conflict_graph = conflict_node_list; }
// getter
std::vector<DrcConflictNode*>& get_conflict_node_list() { return _conflict_graph; }
int get_node_num() { return _conflict_graph.size(); }
// function
// void addEdge(DrcRect* rect1, DrcRect* rect2);
DrcConflictNode* getConflictNode(DrcRect* conflict_rect);
void clearRectToNodeRecord() { _rect_to_node.clear(); }
void clearAllNode();
// init by polygon
void initGraph(const std::map<DrcPolygon*, std::set<DrcPolygon*>>& conflict_map);
DrcConflictNode* getConflictNode(std::map<DrcPolygon*, DrcConflictNode*>& polygon_to_node, DrcPolygon* conflict_polygon);
private:
std::map<DrcRect*, DrcConflictNode*> _rect_to_node;
std::vector<DrcConflictNode*> _conflict_graph;
};
} // namespace idrc
#endif

View File

@ -1,74 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_CONFLICTNODE_H_
#define IDRC_SRC_DB_CONFLICTNODE_H_
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <vector>
#include "DrcRect.h"
namespace idrc {
class DrcConflictNode
{
public:
DrcConflictNode() {}
explicit DrcConflictNode(DrcRect* drc_rect) { _spot_rect = drc_rect; }
explicit DrcConflictNode(DrcPolygon* drc_polygon) { _spot_polygon = drc_polygon; }
explicit DrcConflictNode(int node_id) { _node_id = node_id; }
~DrcConflictNode() {}
// add conflict node
void addConflictNode(DrcConflictNode* conflict_node) { _conflict_node_list.push_back(conflict_node); }
// setter
void set_parent_node(DrcConflictNode* parent) { _parent_node = parent; }
void erase_parent_node() { _parent_node = nullptr; }
void set_node_id(int id) { _node_id = id; }
void set_color(int color) { _color = color; }
void erase_color() { _color = 0; }
void set_conflict_node_list(std::vector<DrcConflictNode*>& conflict_node_list)
{
_conflict_node_list.clear();
_conflict_node_list = conflict_node_list;
}
// getter
std::vector<DrcConflictNode*>& get_conflict_node_list() { return _conflict_node_list; }
int get_node_id() const { return _node_id; }
DrcRect* get_rect() { return _spot_rect; }
DrcPolygon* get_polygon() { return _spot_polygon; }
DrcConflictNode* get_parent_node() { return _parent_node; }
int get_color() const { return _color; }
int get_conflict_node_num() { return _conflict_node_list.size(); }
private:
int _node_id = -1;
int _color = 0;
DrcConflictNode* _parent_node = nullptr;
DrcRect* _spot_rect = nullptr;
DrcPolygon* _spot_polygon = nullptr;
std::vector<DrcConflictNode*> _conflict_node_list;
};
struct DrcConflictNodeCmp
{
bool operator()(DrcConflictNode* a, DrcConflictNode* b) { return (a->get_conflict_node_num()) > (b->get_conflict_node_num()); }
};
} // namespace idrc
#endif

View File

@ -1,106 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_COORDINATE_H_
#define IDRC_SRC_DB_COORDINATE_H_
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
namespace idrc {
template <typename T>
class DrcCoordinate
{
public:
explicit DrcCoordinate() {}
explicit DrcCoordinate(const T x, const T y)
{
static_assert(std::is_same<T, int>::value || std::is_same<T, double>::value, "Must use int or double here!");
_x = x;
_y = y;
}
DrcCoordinate(const DrcCoordinate& other)
{
_x = other._x;
_y = other._y;
}
DrcCoordinate(DrcCoordinate&& other)
{
_x = std::move(other._x);
_y = std::move(other._y);
}
~DrcCoordinate() {}
DrcCoordinate& operator=(const DrcCoordinate& other)
{
_x = other._x;
_y = other._y;
return (*this);
}
DrcCoordinate& operator=(DrcCoordinate&& other)
{
_x = std::move(other._x);
_y = std::move(other._y);
return (*this);
}
bool operator==(const DrcCoordinate& other) { return (_x == other._x && _y == other._y); }
bool operator!=(const DrcCoordinate& other) { return !((*this) == other); }
// getter
T get_x() const { return _x; }
T get_y() const { return _y; }
// setters
void set(const T& x, const T& y)
{
_x = x;
_y = y;
}
void set(DrcCoordinate& in)
{
_x = in.get_x();
_y = in.get_y();
}
void set_x(const T& x) { _x = x; }
void set_y(const T& y) { _y = y; }
// function
private:
T _x = -1;
T _y = -1;
};
template <typename T>
struct cmpCoordinateXASC
{
bool operator()(const DrcCoordinate<T>& a, const DrcCoordinate<T>& b) const
{
return a.get_x() != b.get_x() ? a.get_x() < b.get_x() : a.get_y() < b.get_y();
}
};
template <typename T>
struct cmpCoordinateYASC
{
bool operator()(const DrcCoordinate<T>& a, const DrcCoordinate<T>& b) const
{
return a.get_y() != b.get_y() ? a.get_y() < b.get_y() : a.get_x() < b.get_x();
}
};
} // namespace idrc
#endif // IDRC_SRC_DB_COORDINATE_H_

View File

@ -1,55 +0,0 @@
// ***************************************************************************************
// 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 "BoostType.h"
#include "DrcEdge.h"
#include "DrcEnum.h"
namespace idrc {
class DrcCorner : public BoostPoint
{
public:
DrcCorner() : BoostPoint(), _corner_dir(CornerDirEnum::kNone) {}
DrcCorner* getPrevCorner() const { return _pre_corner; }
DrcCorner* getNextCorner() const { return _next_corner; }
DrcEdge* getPrevEdge() const { return _pre_edge; }
DrcEdge* getNextEdge() const { return _next_edge; }
// BoostPoint getPoint() const { return _point; }
CornerDirEnum getDir() const { return _corner_dir; }
bool isFixed() const { return _fixed; }
// setters
void setPrevCorner(DrcCorner* in) { _pre_corner = in; }
void setNextCorner(DrcCorner* in) { _next_corner = in; }
void setPrevEdge(DrcEdge* in) { _pre_edge = in; }
void setNextEdge(DrcEdge* in) { _next_edge = in; }
void setDir(CornerDirEnum in) { _corner_dir = in; }
void setFixed(bool in) { _fixed = in; }
private:
// BoostPoint _point;
DrcCorner* _pre_corner;
DrcCorner* _next_corner;
DrcEdge* _pre_edge;
DrcEdge* _next_edge;
// DrcCornerTypeEnum _corner_type;
CornerDirEnum _corner_dir; // points away from poly for convex and concave
bool _fixed;
};
} // namespace idrc

View File

@ -1,107 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_DRC_DESIGN_H_
#define IDRC_SRC_DB_DRC_DESIGN_H_
#include <memory>
#include <utility>
#include "BoostType.h"
#include "DrcNet.h"
#include "DrcPolygon.h"
#include "DrcSpot.h"
#include "DrcViolationSpot.h"
#include "Tech.h"
namespace idrc {
class DrcDesign
{
public:
DrcDesign() {}
~DrcDesign()
{
clear_drc_net_list();
clear_blockage_list();
}
// setter
void add_drc_net(DrcNet* drc_net) { _drc_net_list.push_back(drc_net); }
void add_blockage(int routingLayerId, DrcRect* block_rect) { _layer_to_blockage_list[routingLayerId].push_back(block_rect); }
void add_blockage(int routingLayerId, const BoostRect& block_rect) { _blockage_polygon_set_list[routingLayerId] += block_rect; }
DrcPolygon* add_blockage_polygon(int routingLayerId, const PolygonWithHoles& drc_poly)
{
std::unique_ptr<DrcPolygon> drcPolygon = std::make_unique<DrcPolygon>(routingLayerId, drc_poly);
DrcPolygon* drc_polygon = drcPolygon.get();
_layer_to_drc_block_polygon_list[routingLayerId].push_back(std::move(drcPolygon));
return drc_polygon;
}
// getter
std::vector<DrcNet*>& get_drc_net_list() { return _drc_net_list; }
std::map<int, std::vector<DrcRect*>>& get_layer_to_blockage_list() { return _layer_to_blockage_list; }
std::map<int, bp::polygon_90_set_data<int>>& get_blockage_polygon_set_list() { return _blockage_polygon_set_list; }
// function
int get_net_num() { return _drc_net_list.size(); }
DrcNet* add_drc_net()
{
DrcNet* drc_net = new DrcNet();
_drc_net_list.push_back(drc_net);
return drc_net;
}
// DrcRect* add_blockage(int routingLayerId, DrcRect* drcRect)
// {
// DrcRect* block_rect = new DrcRect();
// _blockage_list.push_back(block_rect);
// return block_rect;
// }
void clear_drc_net_list()
{
for (auto net : _drc_net_list) {
if (net != nullptr) {
delete net;
net = nullptr;
}
}
_drc_net_list.clear();
}
void clear_blockage_list()
{
for (auto& [layer_id, blockage_list] : _layer_to_blockage_list) {
for (auto blockage : blockage_list) {
if (blockage != nullptr) {
delete blockage;
blockage = nullptr;
}
}
}
_layer_to_blockage_list.clear();
}
void clear_blockage_polygon_set_list() { _blockage_polygon_set_list.clear(); }
private:
std::vector<DrcNet*> _drc_net_list;
std::map<int, std::vector<DrcRect*>> _layer_to_blockage_list;
////////////////////////////////////////////////////
//下面两个目前工程上没用multi-patterning相关
std::map<int, bp::polygon_90_set_data<int>> _blockage_polygon_set_list;
std::map<int, std::vector<std::unique_ptr<DrcPolygon>>> _layer_to_drc_block_polygon_list;
// std::vector<DrcRect*> _instance_list;
};
} // namespace idrc
#endif

View File

@ -1,133 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_DRCEDGE_H_
#define IDRC_SRC_DB_DRCEDGE_H_
#include <algorithm>
#include <memory>
#include "BoostType.h"
#include "DrcCoordinate.h"
#include "DrcCorner.hpp"
#include "DrcEnum.h"
#include "DrcNet.h"
#include "DrcPoly.hpp"
namespace idrc {
class DrcPolygon;
class DrcNet;
class DrcEdge : public BoostSegment
{
public:
DrcEdge() : BoostSegment(), _layer_id(-1), _is_fixed(false), _edge_dir(EdgeDirection::kNone) {}
explicit DrcEdge(const DrcEdge& segment)
: BoostSegment(segment),
_layer_id(-1),
_is_fixed(false),
_owner_poly(nullptr),
_owner_net(nullptr),
_pre_edge(nullptr),
_next_edge(nullptr),
_low_corner(nullptr),
_high_corner(nullptr),
_edge_dir(EdgeDirection::kNone),
_directed_segment(segment)
{
}
// explicit DrcEdge(const DrcEdge& other) = default;
explicit DrcEdge(DrcEdge&& other) = default;
~DrcEdge() {}
DrcEdge& operator=(const DrcEdge& other) = default;
DrcEdge& operator=(DrcEdge& other) = default;
// setter
void setSegment(const BoostSegment& in) { _directed_segment = in; }
void setSegment(const BoostPoint& bp, const BoostPoint& ep)
{
_directed_segment.low(bp);
_directed_segment.high(ep);
}
void setPrevEdge(DrcEdge* in) { _pre_edge = in; }
void setNextEdge(DrcEdge* in) { _next_edge = in; }
void setLowCorner(DrcCorner* in) { _low_corner = in; }
void setHighCorner(DrcCorner* in) { _high_corner = in; }
void set_owner_polygon(DrcPoly* polygon) { _owner_poly = polygon; }
void set_layer_id(int layerId) { _layer_id = layerId; }
void set_is_fixed(bool isFixed) { _is_fixed = isFixed; }
void set_edge_dir(EdgeDirection dir) { _edge_dir = dir; }
void set_segment(const BoostSegment& boost_segment) { _directed_segment = boost_segment; }
void setDir()
{
if (get_begin_x() == get_end_x()) {
if (get_begin_y() < get_end_y()) {
_edge_dir = EdgeDirection::kNorth;
} else {
_edge_dir = EdgeDirection::kSouth;
}
// WEST / EAST
} else {
if (get_begin_x() < get_end_x()) {
_edge_dir = EdgeDirection::kEast;
} else {
_edge_dir = EdgeDirection::kWest;
}
}
}
// getter
int getLength() { return std::max(get_max_x() - get_min_x(), get_max_y() - get_min_y()); }
DrcEdge* getPreEdge() { return _pre_edge; }
DrcEdge* getNextEdge() { return _next_edge; }
int get_layer_id() const { return _layer_id; }
bool get_is_fixed() const { return _is_fixed; }
EdgeDirection get_edge_dir() const { return _edge_dir; }
BoostPoint get_begin() const { return _directed_segment.low(); }
BoostPoint get_end() const { return _directed_segment.high(); }
int get_begin_x() const { return get_begin().x(); }
int get_begin_y() const { return get_begin().y(); }
int get_end_x() const { return get_end().x(); }
int get_end_y() const { return get_end().y(); }
int get_min_x() const { return std::min(get_begin_x(), get_end_x()); }
int get_min_y() const { return std::min(get_begin_y(), get_end_y()); }
int get_max_x() const { return std::max(get_begin_x(), get_end_x()); }
int get_max_y() const { return std::max(get_begin_y(), get_end_y()); }
DrcPoly* get_owner_polygon() { return _owner_poly; }
// function
bool isHorizontal() const { return get_begin_y() == get_end_y(); }
bool isVertical() const { return get_begin_x() == get_end_x(); }
void addToPoly(DrcPoly* in) { _owner_poly = in; }
void addToNet(DrcNet* in) { _owner_net = in; }
private:
int _layer_id = -1;
// int _width = -1;
bool _is_fixed;
DrcPoly* _owner_poly;
DrcNet* _owner_net;
DrcEdge* _pre_edge;
DrcEdge* _next_edge;
DrcCorner* _low_corner;
DrcCorner* _high_corner;
EdgeDirection _edge_dir;
BoostSegment _directed_segment;
};
} // namespace idrc
#endif

View File

@ -1,70 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_DRC_ENCLOSURE_H_
#define IDRC_SRC_DB_DRC_ENCLOSURE_H_
#include "DrcEnum.h"
#include "DrcRectangle.h"
namespace idrc {
class DrcEnclosure
{
public:
explicit DrcEnclosure() : _layer_idx(0), _shape(DrcRectangle<int>()) {}
DrcEnclosure(const DrcEnclosure& other)
{
_layer_idx = other._layer_idx;
_shape = other._shape;
// _direction = other._direction;
}
DrcEnclosure(DrcEnclosure&& other)
{
_layer_idx = std::move(other._layer_idx);
_shape = std::move(other._shape);
// _direction = std::move(other._direction);
}
~DrcEnclosure() {}
DrcEnclosure& operator=(const DrcEnclosure& other)
{
_layer_idx = other._layer_idx;
_shape = other._shape;
// _direction = other._direction;
return (*this);
}
DrcEnclosure& operator=(DrcEnclosure&& other)
{
_layer_idx = std::move(other._layer_idx);
_shape = std::move(other._shape);
// _direction = std::move(other._direction);
return (*this);
}
// getter
int get_layer_idx() const { return _layer_idx; }
DrcRectangle<int>& get_shape() { return _shape; }
// DrcDirection get_direction() { return _direction; }
// setters
void set_shape(DrcRectangle<int>& shape) { _shape = shape; }
void set_layer_idx(int layer_idx) { _layer_idx = layer_idx; }
// void set_direction(DrcDirection direction) { _direction = direction; }
// function
private:
int _layer_idx;
DrcRectangle<int> _shape;
// DrcDirection _direction;
};
} // namespace idrc
#endif

View File

@ -1,169 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_DRCTYPE_H_
#define IDRC_SRC_DB_DRCTYPE_H_
namespace idrc {
enum class QueryBoxDir
{
kNone = 0,
kUp = 1,
kDown = 2,
kLeft = 3,
kRight = 4,
kNE = 5,
kNW = 6,
kSE = 7,
kSW = 8
};
enum class EdgeDirection
{
kNone = 0,
kNorth = 1,
kEast = 2,
kSouth = 3,
kWest = 4,
};
enum class CornerDirEnum
{
kNone = 0,
kNE,
kSE,
kSW,
kNW
};
enum class RuleTypeEnum
{ // check FlexDR.h fixMode
kShortRule = 0,
kAreaRule = 1,
kWidthRule = 2,
kMaxWidthRule,
kSpacingRule,
kMinEnclosedAreaRule,
kDensityRule,
kCutSpacingRule,
kSpacingTablePrlRule,
kMinimumCutRule,
kEnclosureRule,
kLEF58VoltageSpacingRule,
kLEF58CutSpacingRule,
kLEF58SpacingTableCutRule,
kLEF58CutClassRule,
kLEF58SquaEnclosureRule,
kLEF58RectEnclosureRule,
kLEF58EnclosureEdgeRule,
kLEF58SpacingTableJogRule,
kLEF58MinStepRule,
kLEF58MinimumCutRule,
kLEF58AreaRule,
kLEF58SpacingEOLRule
};
enum class ViolationType
{
kNone = 0,
kRoutingWidth = 1,
kRoutingArea = 2,
kRoutingSpacing = 3,
kEnclosedArea = 4,
kShort = 5,
kDensity = 6,
kEnclosure = 7,
kCutSpacing = 8,
kEnd2EndEOLSpacing = 9,
kEOLSpacing = 10,
kCutEOLSpacing = 11,
kCutDiffLayerSpacing = 12,
kEnclosureEdge = 13,
kCornerFillingSpacing = 14,
kJogSpacing = 15,
kNotchSpacing = 16,
kMinStep = 17,
kCutShort,
};
enum class LayerType
{
kNone = 0,
kRouting = 1,
kCut = 2
};
enum class LayerDirection
{
kNone = 0,
kHorizontal = 1,
kVertical = 2
};
enum class ScopeType
{
kNone = 0,
kMax,
kMin,
EOL,
CornerFill,
Common
};
enum class RectOwnerType
{
kNone = 0,
kRoutingMetal,
kSegment,
kViaMetal,
kViaCut,
kPin,
kObs,
kBlockage,
kSpotMark,
kCommonRegion,
kEOLRegion,
kCornerFillRegion,
kCutCommonRegion
};
enum class DrcDirection
{
kNone = 0,
kHorizontal = 1,
kVertical = 2,
kOblique = 3
};
enum class MinimumCutDirEnum
{
Default = 0,
FromBelow = 1,
FromAbove = 2
};
enum class EnclosureDirEnum
{
Default = 0,
Below = 1,
Above = 2
};
} // namespace idrc
#endif

View File

@ -1,72 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DrcLayer.h"
namespace idrc {
// SpacingRangeRule* DrcRoutingLayer::add_spacing_range_rule()
// {
// SpacingRangeRule* spacing_range_rule = new SpacingRangeRule();
// _spacing_range_rule_list.push_back(spacing_range_rule);
// return spacing_range_rule;
// }
int DrcRoutingLayer::getRoutingSpacing(int width)
{
for (auto& spacingRangeRule : _spacing_range_rule_list) {
if (width >= spacingRangeRule->get_min_width() && width <= spacingRangeRule->get_max_width()) {
return spacingRangeRule->get_spacing();
}
}
return _min_spacing;
}
int DrcRoutingLayer::getLayerMaxRequireSpacing(DrcRect* target_rect)
{
int spacing = _min_spacing;
if (isSpacingTable()) {
spacing = _spacing_table->get_parallel_spacing(target_rect->getWidth(), target_rect->getLength());
} else {
for (auto& spacing_range_rule : _spacing_range_rule_list) {
int range_rule_spacing = spacing_range_rule->get_spacing();
if (spacing < range_rule_spacing) {
spacing = range_rule_spacing;
}
}
}
return spacing;
}
void DrcRoutingLayer::clear_density_rule()
{
if (_density_rule != nullptr) {
delete _density_rule;
_density_rule = nullptr;
}
}
void DrcRoutingLayer::clear_spacing_range_rule_list()
{
for (SpacingRangeRule* spacing_range_rule : _spacing_range_rule_list) {
if (spacing_range_rule != nullptr) {
delete spacing_range_rule;
spacing_range_rule = nullptr;
}
}
}
} // namespace idrc

View File

@ -1,210 +0,0 @@
// ***************************************************************************************
// 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 <string>
#include <vector>
#include "DensityRule.h"
#include "DrcEnum.h"
#include "DrcRect.h"
#include "DrcRules.hpp"
#include "IdbLayer.h"
#include "SpacingRangeRule.h"
namespace idrc {
class DrcLayer
{
public:
DrcLayer() : _layer_id(-1), _name(""), _layer_type(LayerType::kNone) {}
virtual ~DrcLayer() {}
// setter
void set_name(const std::string& name) { _name = name; }
void set_layer_type(const LayerType& type) { _layer_type = type; }
void set_layer_id(const int layerId) { _layer_id = layerId; }
// getter
const std::string& get_name() const { return _name; }
LayerType get_layer_type() const { return _layer_type; }
int get_layer_id() const { return _layer_id; }
private:
int _layer_id;
std::string _name;
LayerType _layer_type;
};
class DrcRoutingLayer : public DrcLayer
{
public:
DrcRoutingLayer()
: _default_width(-1),
_min_area(-1),
_min_width(-1),
_min_spacing(-1),
_min_enclosed_area(-1),
_direction(LayerDirection::kNone),
_density_rule(nullptr)
{
}
~DrcRoutingLayer()
{
clear_density_rule();
clear_spacing_range_rule_list();
}
// setter
void set_default_width(int width) { _default_width = width; }
void set_min_area(int area) { _min_area = area; }
void set_min_width(int width) { _min_width = width; }
void set_min_spacing(int spacing) { _min_spacing = spacing; }
void set_min_enclosed_area(int min_enclosed_area) { _min_enclosed_area = min_enclosed_area; }
void set_direction(LayerDirection direction) { _direction = direction; }
void set_density_rule(DensityRule* density_rule) { _density_rule = density_rule; }
void set_lef58_eol_spacing_rule_list(const std::vector<std::shared_ptr<idb::routinglayer::Lef58SpacingEol>>& in)
{
_lef58_eol_spacing_rule_list = in;
}
void set_spacing_table(const std::shared_ptr<idb::IdbLayerSpacingTable> in) { _spacing_table = in; }
void set_notch_spacing_rule(const idb::IdbLayerSpacingNotchLength& in)
{
_notch_spacing_rule.set_min_spacing(in.get_min_spacing());
_notch_spacing_rule.set_notch_length(in.get_notch_length());
}
void set_lef58_notch_spacing_rule(const std::shared_ptr<idb::routinglayer::Lef58SpacingNotchlength> in)
{
_lef58_notch_spacing_rule = in;
}
void set_lef58_area_rule_list(const std::vector<std::shared_ptr<idb::routinglayer::Lef58Area>>& in) { _lef58_area_rule_list = in; }
void set_lef58_min_step_rule(const std::vector<std::shared_ptr<idb::routinglayer::Lef58MinStep>>& in) { _lef58_min_step_rule = in; }
void set_min_step_rule(const std::shared_ptr<idb::IdbMinStep> in) { _min_step_rule = in; }
void set_lef58_jog_spacing_rule(const std::shared_ptr<idb::routinglayer::Lef58SpacingTableJogToJog> in) { _lef58_jog_spacing_rule = in; }
void set_lef58_corner_fill_spacing_rule(const std::shared_ptr<idb::routinglayer::Lef58CornerFillSpacing> in)
{
_lef58_corner_fill_spacing_rule = in;
}
// SpacingRangeRule* add_spacing_range_rule();
// getter
int get_default_width() const { return _default_width; }
int get_min_area() const { return _min_area; }
int get_min_width() const { return _min_width; }
int get_min_spacing() const { return _min_spacing; }
int get_min_enclosed_area() const { return _min_enclosed_area; }
LayerDirection get_direction() const { return _direction; }
std::vector<SpacingRangeRule*>& get_spacing_range_rule_list() { return _spacing_range_rule_list; }
// std::vector<MinimumCutRule*>& getMinimumCutRuleList() { return _minimum_cut_rule_list; }
std::vector<std::shared_ptr<idb::routinglayer::Lef58SpacingEol>>& get_lef58_eol_spacing_rule_list()
{
return _lef58_eol_spacing_rule_list;
}
std::shared_ptr<idb::IdbLayerSpacingTable> get_spacing_table() { return _spacing_table; }
idb::IdbLayerSpacingNotchLength& get_notch_spacing_rule() { return _notch_spacing_rule; }
std::shared_ptr<idb::routinglayer::Lef58SpacingNotchlength> get_lef58_notch_spacing_rule() { return _lef58_notch_spacing_rule; }
std::vector<std::shared_ptr<idb::routinglayer::Lef58Area>>& get_lef58_area_rule_list() { return _lef58_area_rule_list; }
std::shared_ptr<idb::IdbMinStep> get_min_step_rule() { return _min_step_rule; }
std::vector<std::shared_ptr<idb::routinglayer::Lef58MinStep>> get_lef58_min_step_rule() { return _lef58_min_step_rule; }
std::shared_ptr<idb::routinglayer::Lef58SpacingTableJogToJog> get_lef58_jog_spacing_rule() { return _lef58_jog_spacing_rule; }
std::shared_ptr<idb::routinglayer::Lef58CornerFillSpacing> get_lef58_corner_fill_spacing_rule()
{
return _lef58_corner_fill_spacing_rule;
}
// function
int getRoutingSpacing(int width);
int getLayerMaxRequireSpacing(DrcRect* target_rect);
bool isSpacingTable() { return _spacing_table->get_parallel() != nullptr; }
void clear_density_rule();
void clear_spacing_range_rule_list();
private:
int _default_width;
int _min_area;
int _min_width;
int _min_spacing;
int _min_enclosed_area;
LayerDirection _direction;
DensityRule* _density_rule;
std::vector<SpacingRangeRule*> _spacing_range_rule_list;
// std::vector<MinimumCutRule*> _minimum_cut_rule_list;
std::vector<std::shared_ptr<idb::routinglayer::Lef58SpacingEol>> _lef58_eol_spacing_rule_list;
std::shared_ptr<idb::IdbLayerSpacingTable> _spacing_table;
idb::IdbLayerSpacingNotchLength _notch_spacing_rule;
std::shared_ptr<idb::routinglayer::Lef58SpacingNotchlength> _lef58_notch_spacing_rule;
std::vector<std::shared_ptr<idb::routinglayer::Lef58Area>> _lef58_area_rule_list;
std::shared_ptr<idb::IdbMinStep> _min_step_rule;
std::vector<std::shared_ptr<idb::routinglayer::Lef58MinStep>> _lef58_min_step_rule;
std::shared_ptr<idb::routinglayer::Lef58SpacingTableJogToJog> _lef58_jog_spacing_rule;
std::shared_ptr<idb::routinglayer::Lef58CornerFillSpacing> _lef58_corner_fill_spacing_rule;
};
class DrcCutLayer : public DrcLayer
{
public:
DrcCutLayer() : _cut_spacing(-1), _width(-1) {}
~DrcCutLayer() {}
// setter
void set_cut_spacing(int cut_spacing) { _cut_spacing = cut_spacing; }
void set_default_width(int in) { _width = in; }
void setLEF58EnclosureRuleList(std::shared_ptr<std::vector<idb::cutlayer::Lef58Enclosure>> in) { _lef58_enclosure_rule_list = in; }
void set_lef58_spacing_table_list(std::vector<std::shared_ptr<idb::cutlayer::Lef58SpacingTable>>& in) { _lef58_spacing_table_list = in; }
void set_lef58_cut_class_list(std::vector<std::shared_ptr<idb::cutlayer::Lef58Cutclass>>& in) { _lef58_cut_class_list = in; }
void set_lef58_cut_eol_spacing(std::shared_ptr<idb::cutlayer::Lef58EolSpacing> in) { _lef58_cut_eol_spacing = in; }
void set_lef58_enclosure_list(std::vector<std::shared_ptr<idb::cutlayer::Lef58Enclosure>>& in) { _lef58_enclosure_list = in; }
void set_lef58_enclosure_edge_list(std::vector<std::shared_ptr<idb::cutlayer::Lef58EnclosureEdge>>& in)
{
_lef58_enclosure_edge_list = in;
}
void set_enclosure_above(idb::IdbLayerCutEnclosure* in) { _enclosure_above = in; }
void set_enclosure_below(idb::IdbLayerCutEnclosure* in) { _enclosure_below = in; }
// getter
int get_cut_spacing() const { return _cut_spacing; }
int get_default_width() const { return _width; }
std::vector<std::shared_ptr<idb::cutlayer::Lef58SpacingTable>>& get_lef58_spacing_table_list() { return _lef58_spacing_table_list; }
std::vector<std::shared_ptr<idb::cutlayer::Lef58Cutclass>>& get_lef58_cut_class_list() { return _lef58_cut_class_list; }
std::shared_ptr<idb::cutlayer::Lef58EolSpacing> get_lef58_cut_eol_spacing() { return _lef58_cut_eol_spacing; }
std::vector<std::shared_ptr<idb::cutlayer::Lef58Enclosure>>& get_lef58_enclosure_list() { return _lef58_enclosure_list; }
std::vector<std::shared_ptr<idb::cutlayer::Lef58EnclosureEdge>>& get_lef58_enclosure_edge_list() { return _lef58_enclosure_edge_list; }
idb::IdbLayerCutEnclosure* get_enclosure_above() { return _enclosure_above; }
idb::IdbLayerCutEnclosure* get_enclosure_below() { return _enclosure_below; }
// std::vector<EnclosureRule*>& getEnclosureRuleList() { return _enclosure_rule_list; }
// std::vector<EnclosureRule*>& getBelowEnclosureRuleList() { return _below_enclosure_rule_list; }
// std::vector<EnclosureRule*>& getAboveEnclosureRuleList() { return _above_enclosure_rule_list; }
private:
int _cut_spacing;
int _width;
idb::IdbLayerCutEnclosure* _enclosure_below;
idb::IdbLayerCutEnclosure* _enclosure_above;
std::vector<std::shared_ptr<idb::cutlayer::Lef58SpacingTable>> _lef58_spacing_table_list;
std::vector<std::shared_ptr<idb::cutlayer::Lef58Cutclass>> _lef58_cut_class_list;
std::shared_ptr<idb::cutlayer::Lef58EolSpacing> _lef58_cut_eol_spacing;
std::vector<std::shared_ptr<idb::cutlayer::Lef58Enclosure>> _lef58_enclosure_list;
std::vector<std::shared_ptr<idb::cutlayer::Lef58EnclosureEdge>> _lef58_enclosure_edge_list;
// std::vector<EnclosureRule*> _enclosure_rule_list;
// std::vector<EnclosureRule*> _below_enclosure_rule_list;
// std::vector<EnclosureRule*> _above_enclosure_rule_list;
std::shared_ptr<std::vector<idb::cutlayer::Lef58Enclosure>> _lef58_enclosure_rule_list;
};
} // namespace idrc

View File

@ -1,104 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#include "DrcNet.h"
namespace idrc {
std::set<int> DrcNet::get_layer_id_list()
{
std::set<int> layer_id_list;
for (auto& [layerId, polyset] : _layer_to_routing_polygon_set) {
layer_id_list.insert(layerId);
}
for (auto& [layerId, polyset] : _layer_to_pin_polygon_set) {
layer_id_list.insert(layerId);
}
return layer_id_list;
}
DrcPolygon* DrcNet::add_merge_polygon(int routingLayer, const PolygonWithHoles& poly)
{
std::unique_ptr<DrcPolygon> drcPolygon = std::make_unique<DrcPolygon>(routingLayer, poly);
DrcPolygon* drc_polygon = drcPolygon.get();
_layer_to_merge_polygon_list[routingLayer].push_back(std::move(drcPolygon));
// assert(drc_polygon != nullptr);
return drc_polygon;
}
void DrcNet::clear_layer_to_routing_rects_map()
{
for (auto& [layer_id, routing_rect_list] : _layer_to_routing_rects_map) {
for (auto routing_rect : routing_rect_list) {
if (routing_rect != nullptr) {
delete routing_rect;
routing_rect = nullptr;
}
}
}
_layer_to_routing_rects_map.clear();
}
void DrcNet::clear_layer_to_pin_rects_map()
{
for (auto& [layer_id, pin_rect_list] : _layer_to_pin_rects_map) {
for (auto pin_rect : pin_rect_list) {
if (pin_rect != nullptr) {
delete pin_rect;
pin_rect = nullptr;
}
}
}
_layer_to_pin_rects_map.clear();
}
void DrcNet::clear_layer_to_cut_rects_map()
{
for (auto& [layer_id, cut_rect_list] : _layer_to_cut_rects_map) {
for (auto cut_rect : cut_rect_list) {
if (cut_rect != nullptr) {
delete cut_rect;
cut_rect = nullptr;
}
}
}
_layer_to_cut_rects_map.clear();
}
void DrcNet::addPoly(PolygonWithHoles shape, int layer_id)
{
DrcPoly* poly = new DrcPoly();
poly->setNet(this);
poly->set_layer_id(layer_id);
DrcPolygon* polygon = new DrcPolygon(shape, layer_id, poly, this);
poly->setPolygon(polygon);
// polygon->set_boost_polygon(shape);
// std::cout << (*poly->getPolygon()->begin()).x() << " " << (*poly->getPolygon()->begin()).y()
// << std::endl;
// for (auto outerIt = polygon->begin(); outerIt != polygon->end(); outerIt++) {
// auto bp1 = *outerIt;
// std::cout << "BP::::::::" << bp1.x() << " " << bp1.y() << std::endl;
// }
// auto poly = std::make_unique<DrcPoly>(shape, layer_id, this);
// poly->set_layer_id(_layer_to_route_polys_map[layer_id].size());
_route_polys_list[layer_id].push_back(std::unique_ptr<DrcPoly>(poly));
}
void DrcNet::addPoly(DrcPoly* poly)
{
int layer_id = poly->get_layer_id();
_route_polys_list[layer_id].push_back(std::unique_ptr<DrcPoly>(poly));
}
} // namespace idrc

View File

@ -1,148 +0,0 @@
// ***************************************************************************************
// 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.
// ***************************************************************************************
#ifndef IDRC_SRC_DB_DRCNET_H_
#define IDRC_SRC_DB_DRCNET_H_
#include <assert.h>
#include <algorithm>
#include <map>
#include <memory>
#include <vector>
#include "BoostType.h"
#include "DrcEdge.h"
#include "DrcPoly.hpp"
#include "DrcPolygon.h"
#include "DrcRect.h"
namespace idrc {
class DrcPoly;
class DrcNet
{
public:
DrcNet() {}
explicit DrcNet(int netId) { _net_id = netId; }
DrcNet(DrcNet&& other) = default;
~DrcNet()
{
clear_layer_to_routing_rects_map();
clear_layer_to_pin_rects_map();
clear_layer_to_cut_rects_map();
}
DrcNet& operator=(DrcNet&& other) = default;
// setter
void set_net_id(int net_id) { _net_id = net_id; }
void add_routing_rect(int routingLayerId, DrcRect* rect)
{
DrcRect* new_rect = new DrcRect(*rect);
_layer_to_routing_rects_map[routingLayerId].push_back(new_rect);
}
void add_pin_rect(int routingLayerId, DrcRect* rect)
{
DrcRect* new_rect = new DrcRect(*rect);
_layer_to_pin_rects_map[routingLayerId].push_back(new_rect);
}
void add_rect_edge(int routingLayerId, DrcEdge* edge) { _layer_to_rect_edges_map[routingLayerId].push_back(edge); }
void add_cut_rect(int cutLayerId, DrcRect* rect)
{
DrcRect* new_rect = new DrcRect(*rect);
_layer_to_cut_rects_map[cutLayerId].push_back(new_rect);
}
// getter
int get_net_id() const { return _net_id; }
std::vector<DrcRect*>& get_layer_routing_rects(int routingLayerId) { return _layer_to_routing_rects_map[routingLayerId]; }
std::vector<DrcRect*>& get_layer_pin_rects(int routingLayerId) { return _layer_to_pin_rects_map[routingLayerId]; }
std::vector<DrcEdge*>& get_layer_rect_edges(int routingLayerId) { return _layer_to_rect_edges_map[routingLayerId]; }
std::vector<DrcRect*>& get_layer_cut_rects(int cutLayerId) { return _layer_to_cut_rects_map[cutLayerId]; }
std::map<int, PolygonSet>& get_routing_polygon_set_map() { return _layer_to_routing_polygon_set; }
PolygonSet& get_routing_polygon_set_by_id(int routing_layer_id) { return _layer_to_routing_polygon_set[routing_layer_id]; }
std::map<int, std::vector<DrcRect*>>& get_layer_to_routing_rects_map() { return _layer_to_routing_rects_map; }
std::map<int, std::vector<DrcRect*>>& get_layer_to_pin_rects_map() { return _layer_to_pin_rects_map; }
std::map<int, std::vector<DrcRect*>>& get_layer_to_cut_rects_map() { return _layer_to_cut_rects_map; }
std::map<int, std::set<DrcPoly*>>& get_layer_to_routing_poly_map() { return _layer_to_poly_set_map; }
std::set<DrcPoly*>& get_routing_poly_set(int layer_id) { return _layer_to_poly_set_map[layer_id]; }
// function
// clear
void clear_layer_to_routing_rects_map();
void clear_layer_to_pin_rects_map();
void clear_layer_to_cut_rects_map();
void clear_layer_to_routing_polygon_set() { _layer_to_routing_polygon_set.clear(); }
void clear_layer_to_pin_polygon_set() { _layer_to_pin_polygon_set.clear(); }
void clear_layer_to_merge_polygon_list() { _layer_to_merge_polygon_list.clear(); }
// function
void add_pin_rect(int routingLayer, const BoostRect& rect) { _layer_to_pin_polygon_set[routingLayer] += rect; }
void add_routing_rect(int routingLayer, const BoostRect& rect)
{
// std::cout << this->get_net_id() << std::endl;
_layer_to_routing_polygon_set[routingLayer] += rect;
}
void add_merge_polygon(int routingLayer, std::unique_ptr<DrcPolygon>& poly)
{
_layer_to_merge_polygon_list[routingLayer].push_back(std::move(poly));
}
void addPoly(PolygonWithHoles shape, int layer_id);
void addPoly(DrcPoly* poly);
DrcPolygon* add_merge_polygon(int routingLayer, const PolygonWithHoles& poly);
// getter
std::vector<std::unique_ptr<DrcPoly>>& get_route_polys(int layer_id) { return _route_polys_list[layer_id]; }
std::map<int, std::vector<std::unique_ptr<DrcPoly>>>& get_route_polys_list() { return _route_polys_list; }
std::map<int, bp::polygon_90_set_data<int>>& get_layer_to_routing_polygon_set() { return _layer_to_routing_polygon_set; }
// BoostPolygon& get_routing_polygon_set_by_id(int layer_id){return _layer_to_routing_polygon_set[layer_id];}
std::map<int, bp::polygon_90_set_data<int>>& get_layer_to_pin_polygon_set() { return _layer_to_pin_polygon_set; }
bp::polygon_90_set_data<int>& get_routing_polygon_set(int layerId) { return _layer_to_routing_polygon_set[layerId]; }
bp::polygon_90_set_data<int>& get_pin_polygon_set(int layerId) { return _layer_to_pin_polygon_set[layerId]; }
std::set<int> get_layer_id_list();
private:
int _net_id;
// segemnt and viaMetal rect
std::map<int, std::vector<DrcRect*>> _layer_to_routing_rects_map;
// pin rect is fixed
std::map<int, std::vector<DrcRect*>> _layer_to_pin_rects_map;
std::map<int, std::vector<std::unique_ptr<DrcPoly>>> _route_polys_list;
////////////////////////////
// 工程上未用到multi-patterning相关
std::map<int, bp::polygon_90_set_data<int>> _layer_to_routing_polygon_set;
std::map<int, bp::polygon_90_set_data<int>> _layer_to_pin_polygon_set;
std::map<int, std::vector<std::unique_ptr<DrcPolygon>>> _layer_to_merge_polygon_list; // merge
// api
std::map<int, std::set<DrcPoly*>> _layer_to_poly_set_map;
///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// not use now
// cut rect only for cut layer
std::map<int, std::vector<DrcRect*>> _layer_to_cut_rects_map;
// rect edge from routing rect and pin rect
std::map<int, std::vector<DrcEdge*>> _layer_to_rect_edges_map;
};
} // namespace idrc
#endif

View File

@ -1,84 +0,0 @@
// ***************************************************************************************
// 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 <vector>
#include "DrcCorner.hpp"
#include "DrcNet.h"
#include "DrcPolygon.h"
namespace idrc {
class DrcNet;
class DrcPolygon;
class DrcPoly
{
public:
DrcPoly() : _layer_id(-1), _net_id(-1), _polygon(nullptr), _net(nullptr) /*, dirty(false)*/, _edges(), _corners(), _max_rects() {}
DrcPoly(const PolygonWithHoles& shape_in, int layer_num_in, DrcNet* net_in)
: _layer_id(-1),
_net_id(-1),
_polygon(std::make_unique<DrcPolygon>(shape_in, layer_num_in, this, net_in).get()),
_net(net_in) /*, dirty(true)*/,
_edges(),
_corners(),
_max_rects()
{
}
DrcPoly(const PolygonWithHoles& shape_in, int layer_num_in, int net_id)
: _layer_id(-1),
_net_id(net_id),
_polygon(std::make_unique<DrcPolygon>(shape_in, layer_num_in, this, net_id).get()),
_net(nullptr),
_edges(),
_corners(),
_max_rects()
{
}
int get_layer_id() const { return _layer_id; }
DrcPolygon* getPolygon() const { return _polygon; }
DrcNet* getNet() const { return _net; }
int getNetId() const { return _net_id; }
std::set<DrcRect*>& getScopes() { return _scope_set; }
std::vector<std::vector<std::unique_ptr<DrcEdge>>>& getEdges() { return _edges; }
void setNet(DrcNet* in) { _net = in; }
void setNetId(int net_id) { _net_id = net_id; }
void setPolygon(DrcPolygon* in) { _polygon = in; }
void set_layer_id(int in) { _layer_id = in; }
void addScope(DrcRect* scope_rect) { _scope_set.insert(scope_rect); }
void addEdges(std::vector<std::unique_ptr<DrcEdge>>& in) { _edges.push_back(std::move(in)); }
void addCorners(std::vector<std::unique_ptr<DrcCorner>>& in) { _corners.push_back(std::move(in)); }
private:
int _layer_id;
int _net_id;
DrcPolygon* _polygon;
DrcNet* _net;
std::vector<std::vector<std::unique_ptr<DrcEdge>>> _edges;
std::vector<std::vector<std::unique_ptr<DrcCorner>>> _corners;
std::set<DrcRect*> _scope_set;
std::vector<DrcRect*> _max_rects;
};
} // namespace idrc

Some files were not shown because too many files have changed in this diff Show More