update idrc
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
# add_subdirectory(iDRC)
|
||||
add_subdirectory(iDRCPro)
|
||||
add_subdirectory(iDRC)
|
||||
add_subdirectory(iECO)
|
||||
add_subdirectory(iFP)
|
||||
add_subdirectory(iIR)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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提供全局报告与详细报告两种形式的报告文件,全局报告文件以文本形式给出,包含各类规则的违例个数;详细报告文件包含了每个违例的详细信息,违例的标注框(标注出违例在版图上的具体位置)、违例的类型、层信息等,支持使用可视化界面读取查看。
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
INCLUDE_DIRECTORIES(
|
||||
SYSTEM
|
||||
## Third Party
|
||||
${HOME_THIRDPARTY}/json
|
||||
## Boost
|
||||
${Boost_INCLUDE_DIRS}
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
|
@ -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}
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
)
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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>"
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||