26 Commits

Author SHA1 Message Date
  Emin ec8249490a
!80 fix(build): improve Tcl header inclusion for better compatibility 1 month ago
  ZhishengZeng f523332c83
!97 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 26c848c683 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 6a1783c7a9 update ino 2 months ago
  Emin dfc6f6f673 !96 fix(build): improve Tcl header inclusion for better compatibility 2 months ago
  Emin 25272ae09a !95 Revert 'Pull Request !94 : build: fix TCL include directory detection' 2 months ago
  Emin 7eb140dd44 !94 build: fix TCL include directory detection 2 months ago
  YihangQiu b34131ca18 feat: expose buildRCTree APIs 2 months ago
  ZhishengZeng d6c51e7a01
!93 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 7af6db3966 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng ee8a92eeab add get_congestion 2 months ago
  ZhishengZeng 47186fec23
!92 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng be1b7bdb16 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 6fff1a899e update egr 2 months ago
  simintao 2b2f2b534a Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao 8ad69d4cd7 fix:verilog read assign 2 months ago
  ZhishengZeng e7c159e90b
!91 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 19dff4eac0 Merge branch 'master' of gitee.com:ieda-ipd/iEDA into nn_master 2 months ago
  ZhishengZeng 73b1c33833 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  ZhishengZeng 0fed4e541c update egr 2 months ago
  ZhishengZeng 48b1207d25 update er 2 months ago
  YihangQiu 725d30d4d9 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  YihangQiu 961ae5c17d feat: add via info in vectorization(tech.json) 2 months ago
  YihangQiu bc479c5de5 fix: via's cut size in iDB 2 months ago
  simintao 4aeeabce1c Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao 8d2f2a0894 fix:assign and verilog read 2 months ago
29 changed files with 883 additions and 137 deletions
Split View
  1. +10
    -0
      src/database/manager/builder/def_builder/def_read.cpp
  2. +7
    -2
      src/database/manager/builder/lef_builder/lef_read.cpp
  3. +4
    -4
      src/database/manager/builder/verilog_builder/verilog_read.cpp
  4. +1
    -1
      src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest
  5. +10
    -0
      src/evaluation/api/timing_api.cc
  6. +3
    -0
      src/evaluation/api/timing_api.hh
  7. +10
    -0
      src/evaluation/src/module/timing/timing_eval.cc
  8. +3
    -0
      src/evaluation/src/module/timing/timing_eval.hh
  9. +1
    -0
      src/interface/tcl/tcl_irt/CMakeLists.txt
  10. +1
    -0
      src/interface/tcl/tcl_irt/include/tcl_register_irt.h
  11. +14
    -0
      src/interface/tcl/tcl_irt/include/tcl_rt.h
  12. +38
    -0
      src/interface/tcl/tcl_irt/src/tcl_rt_get_congestion.cpp
  13. +73
    -36
      src/operation/iNO/source/module/fix_fanout/FixFanout.cpp
  14. +37
    -0
      src/operation/iRT/interface/RTInterface.cpp
  15. +1
    -0
      src/operation/iRT/interface/RTInterface.hpp
  16. +424
    -69
      src/operation/iRT/source/module/early_router/EarlyRouter.cpp
  17. +12
    -3
      src/operation/iRT/source/module/early_router/EarlyRouter.hpp
  18. +6
    -2
      src/operation/iRT/source/module/early_router/er_data_manager/ERComParam.hpp
  19. +43
    -0
      src/operation/iRT/source/module/early_router/er_data_manager/ERConflictGroup.hpp
  20. +40
    -0
      src/operation/iRT/source/module/early_router/er_data_manager/ERConflictPoint.hpp
  21. +4
    -0
      src/operation/iRT/source/module/early_router/er_data_manager/ERModel.hpp
  22. +4
    -2
      src/operation/iRT/source/module/early_router/er_data_manager/ERPin.hpp
  23. +20
    -10
      src/operation/iRT/source/module/early_router/framwork.txt
  24. +1
    -1
      src/operation/iRT/source/module/layer_assigner/framwork.txt
  25. +1
    -1
      src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp
  26. +2
    -2
      src/operation/iRT/source/module/supply_analyzer/framwork.txt
  27. +2
    -2
      src/operation/iSTA/source/module/shell-cmd/CmdVerilogToDef.cc
  28. +5
    -1
      src/utility/tcl/ScriptEngine.hh
  29. +106
    -1
      src/vectorization/src/data_manager/vec_file.cpp

+ 10
- 0
src/database/manager/builder/def_builder/def_read.cpp View File

@@ -1865,6 +1865,7 @@ int32_t DefRead::parse_via(defiVia* def_via)
def_via->rowCol(&num_rows, &num_cols);
}
master_generate->set_cut_row_col(num_rows, num_cols);
master_instance->set_cut_row_col(num_rows, num_cols);

/// if pattern exist, cut array must follow the pattern rule
if (def_via->hasCutPattern()) {
@@ -1926,6 +1927,15 @@ int32_t DefRead::parse_via(defiVia* def_via)
}
}

{
int32_t num_rows = 1;
int32_t num_cols = 1;
if (def_via->hasRowCol()) {
def_via->rowCol(&num_rows, &num_cols);
}
master_instance->set_cut_row_col(num_rows, num_cols);
}

master_instance->set_cut_rect(min_x, min_y, max_x, max_y);
master_instance->set_via_shape();
}


+ 7
- 2
src/database/manager/builder/lef_builder/lef_read.cpp View File

@@ -1308,9 +1308,14 @@ int LefRead::parse_via(lefiVia* lef_via)
via_master->set_via_shape();

/// rows and cols
if (lef_via->hasRowCol()) {
via_master->set_cut_row_col(lef_via->numCutRows(), lef_via->numCutCols());
int32_t num_rows = 1;
int32_t num_cols = 1;
if (lef_via->hasRowCol()){
num_rows = lef_via->numCutRows();
num_cols = lef_via->numCutCols();
}
via_master->set_cut_row_col(num_rows, num_cols);

}

return kDbSuccess;


+ 4
- 4
src/database/manager/builder/verilog_builder/verilog_read.cpp View File

@@ -442,7 +442,7 @@ int32_t RustVerilogRead::build_assign()
auto* the_left_io_pin = idb_io_pin_list->find_pin(left_net_name.c_str());
auto* the_right_io_pin = idb_io_pin_list->find_pin(right_net_name.c_str());

if (the_left_idb_net && the_right_idb_net) {
if (the_left_idb_net && the_right_idb_net && the_left_idb_net != the_right_idb_net) {
// assign net = net, need merge two net to one net.

// std::cout << "merge " << left_net_name << " = " << right_net_name << "\n";
@@ -476,7 +476,7 @@ int32_t RustVerilogRead::build_assign()
idb_net_list->remove_net(left_net_name);
remove_to_merge_nets[left_net_name] = the_right_idb_net;

} else if (the_left_idb_net && !the_left_io_pin) {
} else if (the_left_idb_net) {
if (the_right_io_pin && the_right_io_pin->is_io_pin()) {
// assign net = input_port;
the_left_idb_net->add_io_pin(the_right_io_pin);
@@ -490,8 +490,8 @@ int32_t RustVerilogRead::build_assign()
LOG_ERROR << "constant net should connect to tie cell.";
}
}
} else if (the_right_idb_net && !the_right_io_pin) {
if (the_left_io_pin->is_io_pin()) {
} else if (the_right_idb_net) {
if (the_left_io_pin && the_left_io_pin->is_io_pin()) {
// assign output_port = net;
the_right_idb_net->add_io_pin(the_left_io_pin);
the_left_io_pin->set_net(the_right_idb_net);


+ 1
- 1
src/database/manager/parser/verilog/verilog-rust/verilog-parser/src/verilog_parser/grammar/verilog.pest View File

@@ -10,7 +10,7 @@ line_comment = _{ "//" ~ (!("\n") ~ ASCII)* ~ ("\n" | EOI) }
multiline_comment = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
COMMENT = _{ line_comment | multiline_comment }

no_equal_char = _{ASCII_ALPHANUMERIC | "_" | "\\" | "[" | "]" | "/" | ":" | "$" | "." | "'" | "-"}
no_equal_char = _{ASCII_ALPHANUMERIC | "_" | "\\" | "[" | "]" | "/" | ":" | "$" | "." | "'" | "-" | "*"}
char = _{ no_equal_char | "=" }

// Donnot deal with yosys with (* top = 1 *)


+ 10
- 0
src/evaluation/api/timing_api.cc View File

@@ -134,4 +134,14 @@ std::map<int, double> TimingAPI::patchIRDropMap(std::map<int, std::pair<std::pai
return EVAL_STA_INST->patchIRDropMap(patch_xy_map);
}

void TimingAPI::buildRCTree(const std::string& routing_type)
{
EVAL_STA_INST->buildRCTree(routing_type);
}

void TimingAPI::buildSpefRCTree(const std::string& work_dir)
{
EVAL_STA_INST->buildSpefRCTree(work_dir);
}

} // namespace ieval

+ 3
- 0
src/evaluation/api/timing_api.hh View File

@@ -65,6 +65,9 @@ class TimingAPI
std::map<int, double> patchTimingMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch_xy_map);
std::map<int, double> patchPowerMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch_xy_map);
std::map<int, double> patchIRDropMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch_xy_map);
void buildRCTree(const std::string& routing_type);
void buildSpefRCTree(const std::string& work_dir);

private:
static TimingAPI* _timing_api;


+ 10
- 0
src/evaluation/src/module/timing/timing_eval.cc View File

@@ -157,4 +157,14 @@ std::map<int, double> TimingEval::patchIRDropMap(std::map<int, std::pair<std::pa
return EVAL_INIT_STA_INST->patchIRDropMap(patch);
}

void TimingEval::buildRCTree(const std::string& routing_type)
{
EVAL_INIT_STA_INST->buildRCTree(routing_type);
}

void TimingEval::buildSpefRCTree(const std::string& work_dir)
{
EVAL_INIT_STA_INST->buildSpefRCTree(work_dir);
}

} // namespace ieval

+ 3
- 0
src/evaluation/src/module/timing/timing_eval.hh View File

@@ -64,6 +64,9 @@ class TimingEval
std::map<int, double> patchTimingMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch);
std::map<int, double> patchPowerMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch);
std::map<int, double> patchIRDropMap(std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>>& patch);
void buildRCTree(const std::string& routing_type);
void buildSpefRCTree(const std::string& work_dir);

private:
static TimingEval* _timing_eval;


+ 1
- 0
src/interface/tcl/tcl_irt/CMakeLists.txt View File

@@ -5,6 +5,7 @@ add_library(tcl_irt
${HOME_INTERFACE}/tcl/tcl_irt/src/tcl_destroy_rt.cpp
${HOME_INTERFACE}/tcl/tcl_irt/src/tcl_rt_clean_def.cpp
${HOME_INTERFACE}/tcl/tcl_irt/src/tcl_rt_fix_fanout.cpp
${HOME_INTERFACE}/tcl/tcl_irt/src/tcl_rt_get_congestion.cpp
)

target_link_libraries(tcl_irt


+ 1
- 0
src/interface/tcl/tcl_irt/include/tcl_register_irt.h View File

@@ -32,6 +32,7 @@ int registerCmdRT()
// aux
registerTclCmd(TclRTCleanDef, "rt_clean_def");
registerTclCmd(TclRTFixFanout, "rt_fix_fanout");
registerTclCmd(TclRTGetCongestion, "rt_get_congestion");
return EXIT_SUCCESS;
}


+ 14
- 0
src/interface/tcl/tcl_irt/include/tcl_rt.h View File

@@ -110,6 +110,20 @@ class TclRTFixFanout : public TclCmd
std::vector<std::pair<std::string, ValueType>> _config_list;
};

class TclRTGetCongestion : public TclCmd
{
public:
explicit TclRTGetCongestion(const char* cmd_name);
~TclRTGetCongestion() override = default;

unsigned check() override { return 1; };

unsigned exec() override;

private:
std::vector<std::pair<std::string, ValueType>> _config_list;
};

#endif

} // namespace tcl

+ 38
- 0
src/interface/tcl/tcl_irt/src/tcl_rt_get_congestion.cpp View File

@@ -0,0 +1,38 @@
// ***************************************************************************************
// 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 "RTInterface.hpp"
#include "tcl_rt.h"
#include "tcl_util.h"

namespace tcl {

TclRTGetCongestion::TclRTGetCongestion(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned TclRTGetCongestion::exec()
{
if (!check()) {
return 0;
}

RTI.getCongestion();

return 1;
}

} // namespace tcl

+ 73
- 36
src/operation/iNO/source/module/fix_fanout/FixFanout.cpp View File

@@ -48,43 +48,80 @@ void FixFanout::fixIO() {
continue;
}
if (idb_io_pin->get_pin_name() == idb_io_pin->get_net()->get_net_name()) {
continue;
}
// 在当前net中解开io pin
idb::IdbNet *origin_net = idb_io_pin->get_net();
if (origin_net == nullptr) {
std::cout << "curr_net is empty !!!" << std::endl;
}
origin_net->remove_pin(idb_io_pin);
// 加入原来的io net
idb::IdbNet *io_net = idb_net_list->find_net(idb_io_pin->get_pin_name());
if (io_net == nullptr) {
io_net = new IdbNet();
io_net->set_net_name(idb_io_pin->get_pin_name());
idb_net_list->add_net(io_net);
}
idb_io_pin->set_net(io_net);
idb_io_pin->set_net_name(io_net->get_net_name());
// 生成buf
idb::IdbInstance *new_buf = new IdbInstance();
new_buf->set_name("zzs_buf_" + std::to_string(new_idx++));
new_buf->set_cell_master(idb_cell_master_list->find_cell_master(buffer_name));
idb_instance_list->add_instance(new_buf);
// 插入buf
for (idb::IdbPin *buf_pin : new_buf->get_pin_list()->get_pin_list()) {
if (buf_pin->get_term()->get_type() == idb::IdbConnectType::kPower ||
buf_pin->get_term()->get_type() == idb::IdbConnectType::kGround) {
continue;
idb::IdbNet *origin_net = idb_io_pin->get_net();
std::vector<idb::IdbPin *> instance_pin_list =
origin_net->get_instance_pin_list()->get_pin_list();
// 在origin net中解开所有instance_pin
for (idb::IdbPin *instance_pin : instance_pin_list) {
origin_net->remove_pin(instance_pin);
}
// 构建新的net
idb::IdbNet *new_net = new IdbNet();
new_net->set_net_name("zzs_net_" + std::to_string(new_idx++));
idb_net_list->add_net(new_net);
// 将原instance pin加入新net
for (idb::IdbPin *instance_pin : instance_pin_list) {
new_net->add_instance_pin(instance_pin);
instance_pin->set_net(new_net);
instance_pin->set_net_name(new_net->get_net_name());
}
if (buf_pin->get_term()->get_direction() == idb::IdbConnectDirection::kInput) {
origin_net->add_instance_pin(buf_pin);
buf_pin->set_net(origin_net);
buf_pin->set_net_name(origin_net->get_net_name());
} else if (buf_pin->get_term()->get_direction() ==
idb::IdbConnectDirection::kOutput) {
io_net->add_instance_pin(buf_pin);
buf_pin->set_net(io_net);
buf_pin->set_net_name(io_net->get_net_name());
// 生成buf
idb::IdbInstance *new_buf = new IdbInstance();
new_buf->set_name("zzs_buf_" + std::to_string(new_idx++));
new_buf->set_cell_master(idb_cell_master_list->find_cell_master(buffer_name));
idb_instance_list->add_instance(new_buf);
// 插入buf
for (idb::IdbPin *buf_pin : new_buf->get_pin_list()->get_pin_list()) {
if (buf_pin->get_term()->get_type() == idb::IdbConnectType::kPower ||
buf_pin->get_term()->get_type() == idb::IdbConnectType::kGround) {
continue;
}
if (buf_pin->get_term()->get_direction() == idb::IdbConnectDirection::kInput) {
origin_net->add_instance_pin(buf_pin);
buf_pin->set_net(origin_net);
buf_pin->set_net_name(origin_net->get_net_name());
} else if (buf_pin->get_term()->get_direction() ==
idb::IdbConnectDirection::kOutput) {
new_net->add_instance_pin(buf_pin);
buf_pin->set_net(new_net);
buf_pin->set_net_name(new_net->get_net_name());
}
}

} else {
idb::IdbNet *origin_net = idb_io_pin->get_net();
// 在origin net中解开io pin
origin_net->remove_pin(idb_io_pin);
// 加入原来的io net
idb::IdbNet *io_net = idb_net_list->find_net(idb_io_pin->get_pin_name());
if (io_net == nullptr) {
io_net = new IdbNet();
io_net->set_net_name(idb_io_pin->get_pin_name());
idb_net_list->add_net(io_net);
}
idb_io_pin->set_net(io_net);
idb_io_pin->set_net_name(io_net->get_net_name());
// 生成buf
idb::IdbInstance *new_buf = new IdbInstance();
new_buf->set_name("zzs_buf_" + std::to_string(new_idx++));
new_buf->set_cell_master(idb_cell_master_list->find_cell_master(buffer_name));
idb_instance_list->add_instance(new_buf);
// 插入buf
for (idb::IdbPin *buf_pin : new_buf->get_pin_list()->get_pin_list()) {
if (buf_pin->get_term()->get_type() == idb::IdbConnectType::kPower ||
buf_pin->get_term()->get_type() == idb::IdbConnectType::kGround) {
continue;
}
if (buf_pin->get_term()->get_direction() == idb::IdbConnectDirection::kInput) {
origin_net->add_instance_pin(buf_pin);
buf_pin->set_net(origin_net);
buf_pin->set_net_name(origin_net->get_net_name());
} else if (buf_pin->get_term()->get_direction() ==
idb::IdbConnectDirection::kOutput) {
io_net->add_instance_pin(buf_pin);
buf_pin->set_net(io_net);
buf_pin->set_net_name(io_net->get_net_name());
}
}
}
}


+ 37
- 0
src/operation/iRT/interface/RTInterface.cpp View File

@@ -185,6 +185,8 @@ void RTInterface::destroyRT()

void RTInterface::cleanDef()
{
#if 1

//////////////////////////////////////////
// 删除net内所有的wire
IdbNetList* idb_net_list = dmInst->get_idb_def_service()->get_design()->get_net_list();
@@ -210,6 +212,8 @@ void RTInterface::cleanDef()
// 删除虚空的io_pin
//////////////////////////////////////////

#endif

#if 0

//////////////////////////////////////////
@@ -348,6 +352,39 @@ void RTInterface::fixFanout()
}
}

void RTInterface::getCongestion()
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");

initFlute();
RTGP.init();
RTDE.init();

PinAccessor::initInst();
RTPA.access();
PinAccessor::destroyInst();

SupplyAnalyzer::initInst();
RTSA.analyze();
SupplyAnalyzer::destroyInst();

TopologyGenerator::initInst();
RTTG.generate();
TopologyGenerator::destroyInst();

LayerAssigner::initInst();
RTLA.assign();
LayerAssigner::destroyInst();

destroyFlute();
RTGP.destroy();
RTDE.destroy();

RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());

}

#endif

#endif


+ 1
- 0
src/operation/iRT/interface/RTInterface.hpp View File

@@ -81,6 +81,7 @@ class RTInterface
void destroyRT();
void cleanDef();
void fixFanout();
void getCongestion();
#endif

#endif


+ 424
- 69
src/operation/iRT/source/module/early_router/EarlyRouter.cpp View File

@@ -56,8 +56,13 @@ void EarlyRouter::route()
RTLOG.info(Loc::current(), "Starting...");
ERModel er_model = initERModel();
setERComParam(er_model);
generateAccessPoint(er_model);
generateAccessPatch(er_model);
initAccessPointList(er_model);
// debugPlotERModel(er_model, "before");
buildConflictList(er_model);
eliminateConflict(er_model);
uploadAccessPoint(er_model);
uploadAccessPatch(er_model);
// debugPlotERModel(er_model, "middle");
buildSupplySchedule(er_model);
analyzeSupply(er_model);
buildIgnoreNet(er_model);
@@ -72,7 +77,8 @@ void EarlyRouter::route()
buildLayerOrientSupply(er_model);
assignLayer(er_model);
outputResult(er_model);
// debugPlotERModel(er_model, "best");
// debugPlotERModel(er_model, "after");
cleanTempResult(er_model);
updateSummary(er_model);
printSummary(er_model);
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
@@ -116,6 +122,7 @@ ERNet EarlyRouter::convertToERNet(Net& net)

void EarlyRouter::setERComParam(ERModel& er_model)
{
int32_t max_candidate_point_num = 10;
int32_t supply_reduction = 0;
double boundary_wire_unit = 1;
double internal_wire_unit = 1;
@@ -129,11 +136,12 @@ void EarlyRouter::setERComParam(ERModel& er_model)
double overflow_unit = 4 * non_prefer_wire_unit;

/**
* supply_reduction, boundary_wire_unit, internal_wire_unit, internal_via_unit, topo_spilt_length, expand_step_num, expand_step_length, via_unit,
* overflow_unit
* max_candidate_point_num, supply_reduction, boundary_wire_unit, internal_wire_unit, internal_via_unit, topo_spilt_length, expand_step_num,
* expand_step_length, via_unit, overflow_unit
*/
ERComParam er_com_param(supply_reduction, boundary_wire_unit, internal_wire_unit, internal_via_unit, topo_spilt_length, expand_step_num, expand_step_length,
via_unit, overflow_unit);
ERComParam er_com_param(max_candidate_point_num, supply_reduction, boundary_wire_unit, internal_wire_unit, internal_via_unit, topo_spilt_length,
expand_step_num, expand_step_length, via_unit, overflow_unit);
RTLOG.info(Loc::current(), "max_candidate_point_num: ", er_com_param.get_max_candidate_point_num());
RTLOG.info(Loc::current(), "supply_reduction: ", er_com_param.get_supply_reduction());
RTLOG.info(Loc::current(), "boundary_wire_unit: ", er_com_param.get_boundary_wire_unit());
RTLOG.info(Loc::current(), "internal_wire_unit: ", er_com_param.get_internal_wire_unit());
@@ -147,7 +155,7 @@ void EarlyRouter::setERComParam(ERModel& er_model)
er_model.set_er_com_param(er_com_param);
}

void EarlyRouter::generateAccessPoint(ERModel& er_model)
void EarlyRouter::initAccessPointList(ERModel& er_model)
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");
@@ -181,38 +189,77 @@ void EarlyRouter::generateAccessPoint(ERModel& er_model)
if (routing_pin_shape_list.empty()) {
RTLOG.error(Loc::current(), "The routing_pin_shape_list is empty!");
}
er_pin.set_access_point(AccessPoint(er_pin.get_pin_idx(), getAccessCoord(routing_pin_shape_list.front().second)));
for (LayerCoord access_coord : getAccessCoordList(er_model, routing_pin_shape_list.front().second)) {
er_pin.get_access_point_list().emplace_back(er_pin.get_pin_idx(), access_coord);
}
}

std::vector<PlanarCoord> coord_list;
for (ERPin& er_pin : er_net.get_er_pin_list()) {
coord_list.push_back(er_pin.get_access_point().get_real_coord());
for (AccessPoint& access_point : er_pin.get_access_point_list()) {
coord_list.push_back(access_point.get_real_coord());
}
}
BoundingBox& bounding_box = er_net.get_bounding_box();
bounding_box.set_real_rect(RTUTIL.getBoundingBox(coord_list));
bounding_box.set_grid_rect(RTUTIL.getOpenGCellGridRect(bounding_box.get_real_rect(), gcell_axis));

for (ERPin& er_pin : er_net.get_er_pin_list()) {
AccessPoint& access_point = er_pin.get_access_point();
access_point.set_grid_coord(RTUTIL.getGCellGridCoordByBBox(access_point.get_real_coord(), gcell_axis, bounding_box));
for (AccessPoint& access_point : er_pin.get_access_point_list()) {
access_point.set_grid_coord(RTUTIL.getGCellGridCoordByBBox(access_point.get_real_coord(), gcell_axis, bounding_box));
RTDM.updateNetAccessPointToGCellMap(ChangeType::kAdd, er_net.get_net_idx(), &access_point);
}
}
}
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}

LayerCoord EarlyRouter::getAccessCoord(std::vector<EXTLayerRect>& shape_list)
std::vector<LayerCoord> EarlyRouter::getAccessCoordList(ERModel& er_model, std::vector<EXTLayerRect>& pin_shape_list)
{
Die& die = RTDM.getDatabase().get_die();
int32_t manufacture_grid = RTDM.getDatabase().get_manufacture_grid();
std::vector<RoutingLayer>& routing_layer_list = RTDM.getDatabase().get_routing_layer_list();
std::map<int32_t, PlanarRect>& layer_enclosure_map = RTDM.getDatabase().get_layer_enclosure_map();

int32_t curr_layer_idx;
{
for (EXTLayerRect& pin_shape : pin_shape_list) {
if (pin_shape_list.front().get_layer_idx() != pin_shape.get_layer_idx()) {
RTLOG.error(Loc::current(), "The pin_shape_list is not on the same layer!");
}
}
curr_layer_idx = pin_shape_list.front().get_layer_idx();
}
std::vector<PlanarRect> legal_rect_list;
{
std::vector<PlanarRect> origin_pin_shape_list;
for (EXTLayerRect& pin_shape : pin_shape_list) {
origin_pin_shape_list.push_back(pin_shape.get_real_rect());
}
std::vector<PlanarRect> shrinked_rect_list;
{
PlanarRect& enclosure = layer_enclosure_map[curr_layer_idx];
int32_t enclosure_half_x_span = enclosure.getXSpan() / 2;
int32_t enclosure_half_y_span = enclosure.getYSpan() / 2;
int32_t half_min_width = routing_layer_list[curr_layer_idx].get_min_width() / 2;
int32_t shrinked_x_size = std::max(half_min_width, enclosure_half_x_span);
int32_t shrinked_y_size = std::max(half_min_width, enclosure_half_y_span);
for (PlanarRect& real_rect :
RTUTIL.getClosedShrinkedRectListByBoost(origin_pin_shape_list, shrinked_x_size, shrinked_y_size, shrinked_x_size, shrinked_y_size)) {
shrinked_rect_list.push_back(real_rect);
}
}
if (shrinked_rect_list.empty()) {
legal_rect_list = origin_pin_shape_list;
} else {
legal_rect_list = shrinked_rect_list;
}
}
std::vector<LayerCoord> layer_coord_list;
for (EXTLayerRect& legal_shape : shape_list) {
int32_t ll_x = legal_shape.get_real_rect().get_ll_x();
int32_t ll_y = legal_shape.get_real_rect().get_ll_y();
int32_t ur_x = legal_shape.get_real_rect().get_ur_x();
int32_t ur_y = legal_shape.get_real_rect().get_ur_y();
int32_t curr_layer_idx = legal_shape.get_layer_idx();
for (PlanarRect& legal_shape : legal_rect_list) {
int32_t ll_x = legal_shape.get_ll_x();
int32_t ll_y = legal_shape.get_ll_y();
int32_t ur_x = legal_shape.get_ur_x();
int32_t ur_y = legal_shape.get_ur_y();
// 避免 off_grid
while (ll_x % manufacture_grid != 0) {
ll_x++;
@@ -226,7 +273,7 @@ LayerCoord EarlyRouter::getAccessCoord(std::vector<EXTLayerRect>& shape_list)
while (ur_y % manufacture_grid != 0) {
ur_y--;
}
RoutingLayer curr_routing_layer = routing_layer_list[curr_layer_idx];
RoutingLayer& curr_routing_layer = routing_layer_list[curr_layer_idx];
std::vector<int32_t> x_track_list = RTUTIL.getScaleList(ll_x, ur_x, curr_routing_layer.getXTrackGridList());
std::vector<int32_t> y_track_list = RTUTIL.getScaleList(ll_y, ur_y, curr_routing_layer.getYTrackGridList());
std::vector<int32_t> x_shape_list;
@@ -252,15 +299,13 @@ LayerCoord EarlyRouter::getAccessCoord(std::vector<EXTLayerRect>& shape_list)
y_shape_list.emplace_back(ur_y);
}
// track grid
if (layer_coord_list.empty()) {
for (int32_t x : x_track_list) {
for (int32_t y : y_track_list) {
layer_coord_list.emplace_back(x, y, curr_layer_idx);
}
for (int32_t x : x_track_list) {
for (int32_t y : y_track_list) {
layer_coord_list.emplace_back(x, y, curr_layer_idx);
}
}
// on track
if (layer_coord_list.empty()) {
{
for (int32_t x : x_shape_list) {
for (int32_t y : y_track_list) {
layer_coord_list.emplace_back(x, y, curr_layer_idx);
@@ -273,11 +318,9 @@ LayerCoord EarlyRouter::getAccessCoord(std::vector<EXTLayerRect>& shape_list)
}
}
// on shape
if (layer_coord_list.empty()) {
for (int32_t x : x_shape_list) {
for (int32_t y : y_shape_list) {
layer_coord_list.emplace_back(x, y, curr_layer_idx);
}
for (int32_t x : x_shape_list) {
for (int32_t y : y_shape_list) {
layer_coord_list.emplace_back(x, y, curr_layer_idx);
}
}
}
@@ -307,66 +350,364 @@ LayerCoord EarlyRouter::getAccessCoord(std::vector<EXTLayerRect>& shape_list)
}
std::sort(layer_coord_list.begin(), layer_coord_list.end(), CmpLayerCoordByXASC());
layer_coord_list.erase(std::unique(layer_coord_list.begin(), layer_coord_list.end()), layer_coord_list.end());
uniformSampleCoordList(er_model, layer_coord_list);
if (layer_coord_list.empty()) {
RTLOG.error(Loc::current(), "The layer_coord_list is empty!");
}
return layer_coord_list.front();
return layer_coord_list;
}

void EarlyRouter::uniformSampleCoordList(ERModel& er_model, std::vector<LayerCoord>& layer_coord_list)
{
int32_t max_candidate_point_num = er_model.get_er_com_param().get_max_candidate_point_num();

PlanarRect bounding_box = RTUTIL.getBoundingBox(layer_coord_list);
int32_t grid_num = static_cast<int32_t>(std::sqrt(max_candidate_point_num));
double grid_x_span = bounding_box.getXSpan() / grid_num;
double grid_y_span = bounding_box.getYSpan() / grid_num;

std::set<PlanarCoord, CmpPlanarCoordByXASC> visited_set;
std::vector<LayerCoord> new_layer_coord_list;
for (LayerCoord& layer_coord : layer_coord_list) {
PlanarCoord grid_coord(static_cast<int32_t>((layer_coord.get_x() - bounding_box.get_ll_x()) / grid_x_span),
static_cast<int32_t>((layer_coord.get_y() - bounding_box.get_ll_y()) / grid_y_span));
if (!RTUTIL.exist(visited_set, grid_coord)) {
new_layer_coord_list.push_back(layer_coord);
visited_set.insert(grid_coord);
if (static_cast<int32_t>(new_layer_coord_list.size()) >= max_candidate_point_num) {
break;
}
}
}
layer_coord_list = new_layer_coord_list;
}

void EarlyRouter::generateAccessPatch(ERModel& er_model)
void EarlyRouter::buildConflictList(ERModel& er_model)
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");

ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis();
std::vector<RoutingLayer>& routing_layer_list = RTDM.getDatabase().get_routing_layer_list();
int32_t bottom_routing_layer_idx = RTDM.getConfig().bottom_routing_layer_idx;
int32_t top_routing_layer_idx = RTDM.getConfig().top_routing_layer_idx;
std::vector<ERConflictGroup>& er_conflict_group_list = er_model.get_er_conflict_group_list();

std::map<ERPin*, std::set<ERPin*>> pin_conflict_map;
for (auto& [curr_pin, conflict_pin_set] : getPinConlictMap(er_model)) {
pin_conflict_map[curr_pin] = conflict_pin_set;
}
for (auto& [curr_pin, conflict_pin_set] : pin_conflict_map) {
if (conflict_pin_set.empty()) {
continue;
}
std::vector<std::pair<ERPin*, ERPin*>> conflict_list;
std::map<ERPin*, int32_t> pin_idx_map;
std::queue<ERPin*> pin_queue = RTUTIL.initQueue(curr_pin);
while (!pin_queue.empty()) {
ERPin* er_pin = RTUTIL.getFrontAndPop(pin_queue);
if (!RTUTIL.exist(pin_idx_map, er_pin)) {
pin_idx_map[er_pin] = pin_idx_map.size();
}
if (!RTUTIL.exist(pin_conflict_map, er_pin)) {
continue;
}
std::set<ERPin*>& conflict_pin_set = pin_conflict_map[er_pin];
for (ERPin* conflict_pin : conflict_pin_set) {
conflict_list.emplace_back(er_pin, conflict_pin);
pin_queue.push(conflict_pin);
}
conflict_pin_set.clear();
}
ERConflictGroup er_conflict_group;
std::vector<std::vector<ERConflictPoint>>& conflict_point_list_list = er_conflict_group.get_conflict_point_list_list();
conflict_point_list_list.resize(pin_idx_map.size());
for (auto& [er_pin, conflict_point_list_idx] : pin_idx_map) {
std::vector<ERConflictPoint> conflict_point_list;
for (AccessPoint& access_point : er_pin->get_access_point_list()) {
ERConflictPoint conflict_point;
conflict_point.set_er_pin(er_pin);
conflict_point.set_access_point(&access_point);
conflict_point.set_coord(access_point.get_real_coord());
conflict_point.set_layer_idx(access_point.get_layer_idx());
conflict_point_list.push_back(conflict_point);
}
conflict_point_list_list[conflict_point_list_idx] = conflict_point_list;
}
std::map<int32_t, std::vector<int32_t>>& conflict_map = er_conflict_group.get_conflict_map();
for (std::pair<ERPin*, ERPin*>& conflict_pair : conflict_list) {
conflict_map[pin_idx_map[conflict_pair.first]].push_back(pin_idx_map[conflict_pair.second]);
}
er_conflict_group_list.push_back(er_conflict_group);
}
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}

std::vector<std::pair<ERPin*, std::set<ERPin*>>> EarlyRouter::getPinConlictMap(ERModel& er_model)
{
GridMap<GCell>& gcell_map = RTDM.getDatabase().get_gcell_map();
Die& die = RTDM.getDatabase().get_die();

std::vector<ERNet>& er_net_list = er_model.get_er_net_list();

std::vector<std::pair<ERPin*, std::set<ERPin*>>> pin_conflict_list;
for (ERNet& er_net : er_net_list) {
for (ERPin& er_pin : er_net.get_er_pin_list()) {
pin_conflict_list.emplace_back(&er_pin, std::set<ERPin*>{});
}
}
#pragma omp parallel for
for (std::pair<ERPin*, std::set<ERPin*>>& pin_conflict_pair : pin_conflict_list) {
ERPin* er_pin = pin_conflict_pair.first;
std::set<ERPin*>& conflict_pin_set = pin_conflict_pair.second;

for (AccessPoint& access_point : er_pin->get_access_point_list()) {
PlanarCoord& grid_coord = access_point.get_grid_coord();
for (int32_t x : {grid_coord.get_x() - 1, grid_coord.get_x(), grid_coord.get_x() + 1}) {
for (int32_t y : {grid_coord.get_y() - 1, grid_coord.get_y(), grid_coord.get_y() + 1}) {
if (!RTUTIL.isInside(die.get_grid_rect(), PlanarCoord(x, y))) {
continue;
}
for (auto& [net_idx, access_point_set] : gcell_map[x][y].get_net_access_point_map()) {
for (AccessPoint* gcell_access_point : access_point_set) {
ERPin* gcell_pin = &er_net_list[net_idx].get_er_pin_list()[gcell_access_point->get_pin_idx()];
if (gcell_pin == er_pin) {
continue;
}
if (hasConflict(access_point, *gcell_access_point)) {
conflict_pin_set.insert(gcell_pin);
}
}
}
}
}
}
}
return pin_conflict_list;
}

bool EarlyRouter::hasConflict(AccessPoint& curr_access_point, AccessPoint& gcell_access_point)
{
return hasConflict(curr_access_point.getRealLayerCoord(), gcell_access_point.getRealLayerCoord());
}

bool EarlyRouter::hasConflict(LayerCoord layer_coord1, LayerCoord layer_coord2)
{
std::vector<RoutingLayer>& routing_layer_list = RTDM.getDatabase().get_routing_layer_list();

std::set<int32_t> conflict_layer_idx_set;
{
int32_t start_layer_idx = layer_coord1.get_layer_idx();
int32_t end_layer_idx = layer_coord2.get_layer_idx();
RTUTIL.swapByASC(start_layer_idx, end_layer_idx);
for (int32_t layer_idx = start_layer_idx; layer_idx <= end_layer_idx; layer_idx++) {
if (layer_idx < (static_cast<int32_t>(routing_layer_list.size()) - 1)) {
conflict_layer_idx_set.insert(layer_idx);
conflict_layer_idx_set.insert(layer_idx + 1);
} else {
conflict_layer_idx_set.insert(layer_idx);
conflict_layer_idx_set.insert(layer_idx - 1);
}
}
}
PlanarCoord& planar_coord1 = layer_coord1.get_planar_coord();
PlanarCoord& planar_coord2 = layer_coord2.get_planar_coord();
for (int32_t conflict_layer_idx : conflict_layer_idx_set) {
RoutingLayer& routing_layer = routing_layer_list[conflict_layer_idx];
int32_t min_width = routing_layer.get_min_width();
int32_t min_length = routing_layer.get_min_area() / min_width;

int32_t x_distance = 0;
int32_t y_distance = 0;
if (routing_layer.isPreferH()) {
x_distance = min_length;
y_distance = min_width;
} else {
x_distance = min_width;
y_distance = min_length;
}
PlanarRect searched_rect = RTUTIL.getEnlargedRect(planar_coord1, x_distance, y_distance, x_distance, y_distance);
if (RTUTIL.isInside(searched_rect, planar_coord2, false)) {
return true;
}
}
return false;
}

void EarlyRouter::eliminateConflict(ERModel& er_model)
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");

// 给有conflict的pin设置
for (ERConflictGroup& er_conflict_group : er_model.get_er_conflict_group_list()) {
for (ERConflictPoint& best_point : getBestPointList(er_conflict_group)) {
best_point.get_er_pin()->set_access_point(*best_point.get_access_point());
}
}
// 给没有conflict的pin设置
for (ERNet& er_net : er_model.get_er_net_list()) {
for (ERPin& er_pin : er_net.get_er_pin_list()) {
if (er_pin.get_access_point().get_layer_idx() < 0) {
er_pin.set_access_point(er_pin.get_access_point_list().front());
}
}
}
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}

std::vector<ERConflictPoint> EarlyRouter::getBestPointList(ERConflictGroup& er_conflict_group)
{
std::vector<std::vector<ERConflictPoint>>& conflict_point_list_list = er_conflict_group.get_conflict_point_list_list();
std::map<int32_t, std::vector<int32_t>>& conflict_map = er_conflict_group.get_conflict_map();

std::vector<ERConflictPoint> curr_ap_list;
for (std::vector<ERConflictPoint>& conflict_point_list : conflict_point_list_list) {
curr_ap_list.push_back(conflict_point_list.front());
}
bool improved = true;
while (improved) {
improved = false;
for (int32_t i = 0; i < static_cast<int32_t>(conflict_point_list_list.size()); ++i) {
std::vector<int32_t> conflict_j_list;
if (RTUTIL.exist(conflict_map, i)) {
conflict_j_list = conflict_map[i];
} else {
RTLOG.error(Loc::current(), "The conflict_map is not exist i!");
}
int32_t best_conflict_count = INT32_MAX;
int32_t best_min_distance = INT32_MAX;
ERConflictPoint best_ap = curr_ap_list[i];
for (ERConflictPoint& conflict_point : conflict_point_list_list[i]) {
int32_t conflict_count = 0;
int32_t min_distance = INT32_MAX;
for (int32_t j : conflict_j_list) {
if (hasConflict(conflict_point, curr_ap_list[j])) {
++conflict_count;
}
min_distance = std::min(min_distance, RTUTIL.getManhattanDistance(conflict_point, curr_ap_list[j]));
}
// 优先比较冲突数,其次比较最小曼哈顿距离(越小越好)
if (conflict_count < best_conflict_count || (conflict_count == best_conflict_count && min_distance < best_min_distance)) {
best_conflict_count = conflict_count;
best_min_distance = min_distance;
best_ap = conflict_point;
}
}
if (best_ap.get_access_point() != curr_ap_list[i].get_access_point()) {
curr_ap_list[i] = best_ap;
improved = true;
}
}
}
return curr_ap_list;
}

void EarlyRouter::uploadAccessPoint(ERModel& er_model)
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");

ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis();
Die& die = RTDM.getDatabase().get_die();

for (auto& [net_idx, access_point_set] : RTDM.getNetAccessPointMap(die)) {
for (AccessPoint* access_point : access_point_set) {
RTDM.updateNetAccessPointToGCellMap(ChangeType::kDel, net_idx, access_point);
}
}
for (ERNet& er_net : er_model.get_er_net_list()) {
std::vector<PlanarCoord> coord_list;
for (ERPin& er_pin : er_net.get_er_pin_list()) {
coord_list.push_back(er_pin.get_access_point().get_real_coord());
}
BoundingBox& bounding_box = er_net.get_bounding_box();
bounding_box.set_real_rect(RTUTIL.getBoundingBox(coord_list));
bounding_box.set_grid_rect(RTUTIL.getOpenGCellGridRect(bounding_box.get_real_rect(), gcell_axis));
for (ERPin& er_pin : er_net.get_er_pin_list()) {
AccessPoint& access_point = er_pin.get_access_point();
int32_t curr_layer_idx = access_point.get_layer_idx();
access_point.set_grid_coord(RTUTIL.getGCellGridCoordByBBox(access_point.get_real_coord(), gcell_axis, bounding_box));
RTDM.updateNetAccessPointToGCellMap(ChangeType::kAdd, er_net.get_net_idx(), &access_point);
}
}
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}

void EarlyRouter::uploadAccessPatch(ERModel& er_model)
{
Monitor monitor;
RTLOG.info(Loc::current(), "Starting...");

ScaleAxis& gcell_axis = RTDM.getDatabase().get_gcell_axis();
std::vector<RoutingLayer>& routing_layer_list = RTDM.getDatabase().get_routing_layer_list();
std::map<int32_t, PlanarRect>& layer_enclosure_map = RTDM.getDatabase().get_layer_enclosure_map();
int32_t bottom_routing_layer_idx = RTDM.getConfig().bottom_routing_layer_idx;
int32_t top_routing_layer_idx = RTDM.getConfig().top_routing_layer_idx;
int32_t only_pitch = RTDM.getOnlyPitch();

for (ERNet& er_net : er_model.get_er_net_list()) {
for (ERPin& er_pin : er_net.get_er_pin_list()) {
PlanarCoord access_coord = er_pin.get_access_point().get_real_coord();
int32_t curr_layer_idx = er_pin.get_access_point().get_layer_idx();
{
RoutingLayer& routing_layer = routing_layer_list[curr_layer_idx];
std::vector<int32_t> x_track_list
= RTUTIL.getScaleList(access_coord.get_x() - only_pitch, access_coord.get_x() + only_pitch, routing_layer.getXTrackGridList());
std::vector<int32_t> y_track_list
= RTUTIL.getScaleList(access_coord.get_y() - only_pitch, access_coord.get_y() + only_pitch, routing_layer.getYTrackGridList());

int32_t min_distance = INT_MAX;
PlanarCoord best_coord = access_coord;
for (int32_t x : x_track_list) {
for (int32_t y : y_track_list) {
PlanarCoord track_coord(x, y);
int32_t distance = RTUTIL.getManhattanDistance(access_coord, track_coord);
if (distance < min_distance) {
min_distance = distance;
best_coord = track_coord;
}
}
}
access_coord = best_coord;
}
int32_t min_layer_idx = curr_layer_idx;
int32_t max_layer_idx = curr_layer_idx;
if (er_pin.get_is_core()) {
if (curr_layer_idx < bottom_routing_layer_idx) {
max_layer_idx = bottom_routing_layer_idx + 1;
} else if (top_routing_layer_idx < curr_layer_idx) {
max_layer_idx = top_routing_layer_idx - 1;
} else if (curr_layer_idx < top_routing_layer_idx) {
max_layer_idx = curr_layer_idx + 1;
} else {
max_layer_idx = curr_layer_idx - 1;
}
} else {
if (curr_layer_idx < bottom_routing_layer_idx) {
max_layer_idx = bottom_routing_layer_idx;
} else if (top_routing_layer_idx < curr_layer_idx) {
max_layer_idx = top_routing_layer_idx;
} else if (curr_layer_idx < top_routing_layer_idx) {
max_layer_idx = curr_layer_idx;
{
if (er_pin.get_is_core()) {
if (curr_layer_idx < bottom_routing_layer_idx) {
max_layer_idx = bottom_routing_layer_idx + 1;
} else if (top_routing_layer_idx < curr_layer_idx) {
max_layer_idx = top_routing_layer_idx - 1;
} else if (curr_layer_idx < top_routing_layer_idx) {
max_layer_idx = curr_layer_idx + 1;
} else {
max_layer_idx = curr_layer_idx - 1;
}
} else {
max_layer_idx = curr_layer_idx;
if (curr_layer_idx < bottom_routing_layer_idx) {
max_layer_idx = bottom_routing_layer_idx;
} else if (top_routing_layer_idx < curr_layer_idx) {
max_layer_idx = top_routing_layer_idx;
} else if (curr_layer_idx < top_routing_layer_idx) {
max_layer_idx = curr_layer_idx;
} else {
max_layer_idx = curr_layer_idx;
}
}
RTUTIL.swapByASC(min_layer_idx, max_layer_idx);
}
RTUTIL.swapByASC(min_layer_idx, max_layer_idx);
for (int32_t layer_idx = min_layer_idx; layer_idx <= max_layer_idx; layer_idx++) {
if (layer_idx == curr_layer_idx) {
continue;
}
RoutingLayer& routing_layer = routing_layer_list[layer_idx];
int32_t half_width = routing_layer.get_min_width() / 2;
int32_t half_length = routing_layer.get_min_area() / routing_layer.get_min_width() / 2;
int32_t min_length = routing_layer.get_min_area() / routing_layer.get_min_width();
PlanarRect& enclosure = layer_enclosure_map[layer_idx];
int32_t half_x_span = enclosure.getXSpan() / 2;
int32_t half_y_span = enclosure.getYSpan() / 2;

EXTLayerRect patch;
if (routing_layer.isPreferH()) {
patch.set_real_rect(RTUTIL.getEnlargedRect(access_point.get_real_coord(), half_length, half_width, half_length, half_width));
patch.set_real_rect(RTUTIL.getEnlargedRect(access_coord, min_length - half_x_span, half_width, half_x_span, half_width));
} else {
patch.set_real_rect(RTUTIL.getEnlargedRect(access_point.get_real_coord(), half_width, half_length, half_width, half_length));
patch.set_real_rect(RTUTIL.getEnlargedRect(access_coord, half_width, min_length - half_y_span, half_width, half_y_span));
}
patch.set_grid_rect(RTUTIL.getClosedGCellGridRect(patch.get_real_rect(), gcell_axis));
patch.set_layer_idx(layer_idx);
@@ -1971,6 +2312,22 @@ void EarlyRouter::outputLayerOverflowCSV(ERModel& er_model)
RTLOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}

void EarlyRouter::cleanTempResult(ERModel& er_model)
{
Die& die = RTDM.getDatabase().get_die();

for (auto& [net_idx, segment_set] : RTDM.getNetDetailedResultMap(die)) {
for (Segment<LayerCoord>* segment : segment_set) {
RTDM.updateNetDetailedResultToGCellMap(ChangeType::kDel, net_idx, segment);
}
}
for (auto& [net_idx, patch_set] : RTDM.getNetDetailedPatchMap(die)) {
for (EXTLayerRect* patch : patch_set) {
RTDM.updateNetDetailedPatchToGCellMap(ChangeType::kDel, net_idx, patch);
}
}
}

#if 1 // update env

void EarlyRouter::updateDemandToGraph(ERModel& er_model, ChangeType change_type, MTree<PlanarCoord>& coord_tree)
@@ -2354,16 +2711,14 @@ void EarlyRouter::debugPlotERModel(ERModel& er_model, std::string flag)
}

// access_point
for (ERNet& er_net : er_model.get_er_net_list()) {
GPStruct access_point_struct(RTUTIL.getString("access_point(net_", er_net.get_net_idx(), ")"));
for (ERPin& er_pin : er_net.get_er_pin_list()) {
AccessPoint& access_point = er_pin.get_access_point();

int32_t x = access_point.get_real_x();
int32_t y = access_point.get_real_y();
for (auto& [net_idx, access_point_set] : RTDM.getNetAccessPointMap(die)) {
GPStruct access_point_struct(RTUTIL.getString("access_point(net_", net_idx, ")"));
for (AccessPoint* access_point : access_point_set) {
int32_t x = access_point->get_real_x();
int32_t y = access_point->get_real_y();

GPBoundary access_point_boundary;
access_point_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(access_point.get_layer_idx()));
access_point_boundary.set_layer_idx(RTGP.getGDSIdxByRouting(access_point->get_layer_idx()));
access_point_boundary.set_data_type(static_cast<int32_t>(GPDataType::kAccessPoint));
access_point_boundary.set_rect(x - point_size, y - point_size, x + point_size, y + point_size);
access_point_struct.push(access_point_boundary);


+ 12
- 3
src/operation/iRT/source/module/early_router/EarlyRouter.hpp View File

@@ -53,9 +53,17 @@ class EarlyRouter
std::vector<ERNet> convertToERNetList(std::vector<Net>& net_list);
ERNet convertToERNet(Net& net);
void setERComParam(ERModel& er_model);
void generateAccessPoint(ERModel& er_model);
LayerCoord getAccessCoord(std::vector<EXTLayerRect>& shape_list);
void generateAccessPatch(ERModel& er_model);
void initAccessPointList(ERModel& er_model);
std::vector<LayerCoord> getAccessCoordList(ERModel& er_model, std::vector<EXTLayerRect>& pin_shape_list);
void uniformSampleCoordList(ERModel& er_model, std::vector<LayerCoord>& layer_coord_list);
void buildConflictList(ERModel& er_model);
std::vector<std::pair<ERPin*, std::set<ERPin*>>> getPinConlictMap(ERModel& er_model);
bool hasConflict(AccessPoint& curr_access_point, AccessPoint& gcell_access_point);
bool hasConflict(LayerCoord layer_coord1, LayerCoord layer_coord2);
void eliminateConflict(ERModel& er_model);
std::vector<ERConflictPoint> getBestPointList(ERConflictGroup& er_conflict_group);
void uploadAccessPoint(ERModel& er_model);
void uploadAccessPatch(ERModel& er_model);
void buildSupplySchedule(ERModel& er_model);
void analyzeSupply(ERModel& er_model);
EXTLayerRect getSearchRect(LayerCoord& first_coord, LayerCoord& second_coord);
@@ -116,6 +124,7 @@ class EarlyRouter
void outputLayerGuide(ERModel& er_model);
void outputLayerNetCSV(ERModel& er_model);
void outputLayerOverflowCSV(ERModel& er_model);
void cleanTempResult(ERModel& er_model);

#if 1 // update env
void updateDemandToGraph(ERModel& er_model, ChangeType change_type, MTree<PlanarCoord>& coord_tree);


+ 6
- 2
src/operation/iRT/source/module/early_router/er_data_manager/ERComParam.hpp View File

@@ -24,9 +24,10 @@ class ERComParam
{
public:
ERComParam() = default;
ERComParam(int32_t supply_reduction, double boundary_wire_unit, double internal_wire_unit, double internal_via_unit, int32_t topo_spilt_length,
int32_t expand_step_num, int32_t expand_step_length, double via_unit, double overflow_unit)
ERComParam(int32_t max_candidate_point_num, int32_t supply_reduction, double boundary_wire_unit, double internal_wire_unit, double internal_via_unit,
int32_t topo_spilt_length, int32_t expand_step_num, int32_t expand_step_length, double via_unit, double overflow_unit)
{
_max_candidate_point_num = max_candidate_point_num;
_supply_reduction = supply_reduction;
_boundary_wire_unit = boundary_wire_unit;
_internal_wire_unit = internal_wire_unit;
@@ -39,6 +40,7 @@ class ERComParam
}
~ERComParam() = default;
// getter
int32_t get_max_candidate_point_num() const { return _max_candidate_point_num; }
int32_t get_supply_reduction() const { return _supply_reduction; }
double get_boundary_wire_unit() const { return _boundary_wire_unit; }
double get_internal_wire_unit() const { return _internal_wire_unit; }
@@ -49,6 +51,7 @@ class ERComParam
double get_via_unit() const { return _via_unit; }
double get_overflow_unit() const { return _overflow_unit; }
// setter
void set_max_candidate_point_num(const int32_t max_candidate_point_num) { _max_candidate_point_num = max_candidate_point_num; }
void set_supply_reduction(const int32_t supply_reduction) { _supply_reduction = supply_reduction; }
void set_boundary_wire_unit(const double boundary_wire_unit) { _boundary_wire_unit = boundary_wire_unit; }
void set_internal_wire_unit(const double internal_wire_unit) { _internal_wire_unit = internal_wire_unit; }
@@ -60,6 +63,7 @@ class ERComParam
void set_overflow_unit(const double overflow_unit) { _overflow_unit = overflow_unit; }

private:
int32_t _max_candidate_point_num = -1;
int32_t _supply_reduction = -1;
double _boundary_wire_unit = -1;
double _internal_wire_unit = -1;


+ 43
- 0
src/operation/iRT/source/module/early_router/er_data_manager/ERConflictGroup.hpp View File

@@ -0,0 +1,43 @@
// ***************************************************************************************
// 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 "ERConflictPoint.hpp"

namespace irt {

class ERConflictGroup
{
public:
ERConflictGroup() = default;
~ERConflictGroup() = default;
// getter
std::vector<std::vector<ERConflictPoint>>& get_conflict_point_list_list() { return _conflict_point_list_list; }
std::map<int32_t, std::vector<int32_t>>& get_conflict_map() { return _conflict_map; }
// setter
void set_conflict_point_list_list(const std::vector<std::vector<ERConflictPoint>>& conflict_point_list_list)
{
_conflict_point_list_list = conflict_point_list_list;
}
void set_conflict_map(const std::map<int32_t, std::vector<int32_t>>& conflict_map) { _conflict_map = conflict_map; }
// function
private:
std::vector<std::vector<ERConflictPoint>> _conflict_point_list_list;
std::map<int32_t, std::vector<int32_t>> _conflict_map;
};

} // namespace irt

+ 40
- 0
src/operation/iRT/source/module/early_router/er_data_manager/ERConflictPoint.hpp View File

@@ -0,0 +1,40 @@
// ***************************************************************************************
// 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 "ERPin.hpp"

namespace irt {

class ERConflictPoint : public LayerCoord
{
public:
ERConflictPoint() = default;
~ERConflictPoint() = default;
// getter
ERPin* get_er_pin() { return _er_pin; }
AccessPoint* get_access_point() { return _access_point; }
// setter
void set_er_pin(ERPin* er_pin) { _er_pin = er_pin; }
void set_access_point(AccessPoint* access_point) { _access_point = access_point; }
// function
private:
ERPin* _er_pin = nullptr;
AccessPoint* _access_point = nullptr;
};

} // namespace irt

+ 4
- 0
src/operation/iRT/source/module/early_router/er_data_manager/ERModel.hpp View File

@@ -16,6 +16,7 @@
// ***************************************************************************************
#pragma once

#include "ERConflictGroup.hpp"
#include "ERComParam.hpp"
#include "ERNet.hpp"
#include "ERNode.hpp"
@@ -31,6 +32,7 @@ class ERModel
// getter
std::vector<ERNet>& get_er_net_list() { return _er_net_list; }
ERComParam& get_er_com_param() { return _er_com_param; }
std::vector<ERConflictGroup>& get_er_conflict_group_list() { return _er_conflict_group_list; }
std::vector<std::vector<std::pair<LayerCoord, LayerCoord>>>& get_grid_pair_list_list() { return _grid_pair_list_list; }
std::vector<ERNet*>& get_er_task_list() { return _er_task_list; }
GridMap<ERNode>& get_planar_node_map() { return _planar_node_map; }
@@ -38,6 +40,7 @@ class ERModel
// setter
void set_er_net_list(const std::vector<ERNet>& er_net_list) { _er_net_list = er_net_list; }
void set_er_com_param(const ERComParam& er_com_param) { _er_com_param = er_com_param; }
void set_er_conflict_group_list(const std::vector<ERConflictGroup>& er_conflict_group_list) { _er_conflict_group_list = er_conflict_group_list; }
void set_grid_pair_list_list(const std::vector<std::vector<std::pair<LayerCoord, LayerCoord>>>& grid_pair_list_list)
{
_grid_pair_list_list = grid_pair_list_list;
@@ -55,6 +58,7 @@ class ERModel
private:
std::vector<ERNet> _er_net_list;
ERComParam _er_com_param;
std::vector<ERConflictGroup> _er_conflict_group_list;
std::vector<std::vector<std::pair<LayerCoord, LayerCoord>>> _grid_pair_list_list;
std::vector<ERNet*> _er_task_list;
GridMap<ERNode> _planar_node_map;


+ 4
- 2
src/operation/iRT/source/module/early_router/er_data_manager/ERPin.hpp View File

@@ -18,6 +18,7 @@

#include "AccessPoint.hpp"
#include "EXTLayerRect.hpp"
#include "Pin.hpp"
#include "PlanarCoord.hpp"
#include "RTHeader.hpp"

@@ -30,12 +31,13 @@ class ERPin : public Pin
explicit ERPin(const Pin& pin) : Pin(pin) {}
~ERPin() = default;
// getter
std::vector<AccessPoint>& get_access_point_list() { return _access_point_list; }
// setter
void set_access_point_list(const std::vector<AccessPoint>& access_point_list) { _access_point_list = access_point_list; }
// function

private:
std::vector<AccessPoint> _access_point_list;
};

} // namespace irt

+ 20
- 10
src/operation/iRT/source/module/early_router/framwork.txt View File

@@ -1,12 +1,22 @@
initERModel:初始化ERModel
setERComParam:设置布线参数
generateAccessPoint:简单生成ap点,以shape的中心为主要点
initERTaskList:构建task,有序
buildPlanarNodeMap:初始化平面graph
buildPlanarNodeNeighbor:构建graph的邻居
buildPlanarOrientSupply:从supply_analyzer获取supply的access
generateTopoTree:对每个net生成topo树
buildLayerNodeMap:初始化层graph
buildLayerNodeNeighbor:构建graph的邻居
buildLayerOrientSupply:从supply_analyzer获取supply的access
generateGlobalTree:生成全局布线结果
initAccessPointList:初始化所有候选ap点
buildConflictList:构建有冲突的pin
eliminateConflict:消除pin之间的冲突
uploadAccessPoint:更新ap点
uploadAccessPatch:添加ap点出pin结果
buildSupplySchedule:构建将要计算的Schedule
analyzeSupply:分析GCell之间的形状等特征,确定supply
buildIgnoreNet:构建可忽略的net
analyzeDemandUnit:分析每个gcell上不同的damand
initERTaskList:初始化布线任务
buildPlanarNodeMap:构建平面Graph,只有节点,其他信息后续构建
buildPlanarNodeNeighbor:将平面Graph所有节点连接
buildPlanarOrientSupply:构建平面Graph的supply
generateTopology:生成线网的拓扑
buildLayerNodeMap:构建空间Graph,只有节点,其他信息后续构建
buildLayerNodeNeighbor:将空间Graph所有节点连接
buildLayerOrientSupply:构建空间Graph的supply
assignLayer:进行层分配
outputResult:输出CSV等布线结果
cleanTempResult:清空临时结果

+ 1
- 1
src/operation/iRT/source/module/layer_assigner/framwork.txt View File

@@ -5,5 +5,5 @@ buildLayerNodeMap:初始化graph
buildLANodeNeighbor:构建graph的邻居
buildOrientSupply:从supply_analyzer获取supply的access
buildPlaneTree:从顶层拿取topo树
routeLAModel:
routeLAModel:进行层分配
routeLATask:一个接一个的la_net进行布线

+ 1
- 1
src/operation/iRT/source/module/pin_accessor/PinAccessor.cpp View File

@@ -390,7 +390,7 @@ std::vector<AccessPoint> PinAccessor::getAccessPointList(PAModel& pa_model, int3
while (ur_y % manufacture_grid != 0) {
ur_y--;
}
RoutingLayer curr_routing_layer = routing_layer_list[curr_layer_idx];
RoutingLayer& curr_routing_layer = routing_layer_list[curr_layer_idx];
std::vector<int32_t> x_track_list = RTUTIL.getScaleList(ll_x, ur_x, curr_routing_layer.getXTrackGridList());
std::vector<int32_t> y_track_list = RTUTIL.getScaleList(ll_y, ur_y, curr_routing_layer.getYTrackGridList());
std::vector<int32_t> x_shape_list;


+ 2
- 2
src/operation/iRT/source/module/supply_analyzer/framwork.txt View File

@@ -2,5 +2,5 @@ initSAModel:初始化model
setSAComParam:设置sa_model的参数
buildSupplySchedule:构建将要计算的Schedule
analyzeSupply:分析GCell之间的形状等特征,确定supply
buildIgnoreNet:构建可忽略的net
analyzeDemandUnit:分析每个gcell上不同的damand

+ 2
- 2
src/operation/iSTA/source/module/shell-cmd/CmdVerilogToDef.cc View File

@@ -85,8 +85,8 @@ unsigned CmdVerilogToDef::exec() {

TclOption* def_option = getOptionOrArg("-def");
const auto* def_file = def_option->getStringVal();
if (const auto ret = db_builder->saveDef(def_file); !ret) {
LOG_FATAL << "Fail to Save DEF file!";
if (const auto ret = db_builder->saveDef(def_file); ret) {
LOG_ERROR << "Fail to Save DEF file!";
}

// the below two lines is used to test idb verilog.


+ 5
- 1
src/utility/tcl/ScriptEngine.hh View File

@@ -24,7 +24,11 @@

#pragma once

#include <tcl8.6/tcl.h>
#if __has_include(<tcl8.6/tcl.h>)
#include <tcl8.6/tcl.h>
#else
#include <tcl.h>
#endif

#include <memory>
#include <mutex>


+ 106
- 1
src/vectorization/src/data_manager/vec_file.cpp View File

@@ -686,6 +686,11 @@ bool VecLayoutFileIO::saveJsonTech()

/// vias
{
auto* idb_layout = dmInst->get_idb_layout();
auto* idb_design = dmInst->get_idb_design();
auto* idb_lef_vias = idb_layout->get_via_list();
auto* idb_def_vias = idb_design->get_via_list();

auto& via_map = _layout->get_via_name_map();
json_tech["via_num"] = via_map.size();

@@ -694,7 +699,107 @@ bool VecLayoutFileIO::saveJsonTech()
json json_via;
json_via["id"] = id;
json_via["name"] = via_name;

auto* idb_via = idb_lef_vias->find_via(via_name);
if (idb_via == nullptr) {
idb_via = idb_def_vias->find_via(via_name);
}
if (idb_via != nullptr) {
// RECT in bottom layer, cut layer, top layer
auto bottom_layer_shape = idb_via->get_bottom_layer_shape();
auto bottom_bbox = bottom_layer_shape.get_bounding_box();
json json_bottom_bbox;
json_bottom_bbox["llx"] = bottom_bbox.get_low_x();
json_bottom_bbox["lly"] = bottom_bbox.get_low_y();
json_bottom_bbox["urx"] = bottom_bbox.get_high_x();
json_bottom_bbox["ury"] = bottom_bbox.get_high_y();
json_via["bottom"] = json_bottom_bbox;
auto cut_layer_shape = idb_via->get_cut_layer_shape();
auto cut_bbox = cut_layer_shape.get_bounding_box();
json json_cut_bbox;
json_cut_bbox["llx"] = cut_bbox.get_low_x();
json_cut_bbox["lly"] = cut_bbox.get_low_y();
json_cut_bbox["urx"] = cut_bbox.get_high_x();
json_cut_bbox["ury"] = cut_bbox.get_high_y();
json_via["cut"] = json_cut_bbox;
auto top_layer_shape = idb_via->get_top_layer_shape();
auto top_bbox = top_layer_shape.get_bounding_box();
json json_top_bbox;
json_top_bbox["llx"] = top_bbox.get_low_x();
json_top_bbox["lly"] = top_bbox.get_low_y();
json_top_bbox["urx"] = top_bbox.get_high_x();
json_top_bbox["ury"] = top_bbox.get_high_y();
json_via["top"] = json_top_bbox;
// Cut size (row and col array)
json_via["row"] = idb_via->get_instance()->get_cut_rows();
json_via["col"] = idb_via->get_instance()->get_cut_cols();

// Direction
auto bottom_center = bottom_bbox.get_middle_point();
auto cut_center = cut_bbox.get_middle_point();
auto top_center = top_bbox.get_middle_point();
std::string bottom_direction = "C"; // default center
std::string top_direction = "C"; // default center

// Use aspect ratio to determine orientation type
int bottom_width = bottom_bbox.get_width();
int bottom_height = bottom_bbox.get_height();
double bottom_aspect_ratio = (double)bottom_width / bottom_height;
int top_width = top_bbox.get_width();
int top_height = top_bbox.get_height();
double top_aspect_ratio = (double)top_width / top_height;

if (bottom_aspect_ratio > 1.1) {
// Horizontal direction - check if cut is left (W) or right (E) shifted
if (std::abs(cut_center.get_x() - bottom_center.get_x()) > 1) {
if (cut_center.get_x() < bottom_center.get_x()) {
bottom_direction = "W";
} else {
bottom_direction = "E";
}
}
} else if (bottom_aspect_ratio < 0.9) {
// Vertical direction - check if cut is up (N) or down (S) shifted
if (std::abs(cut_center.get_y() - bottom_center.get_y()) > 1) {
if (cut_center.get_y() > bottom_center.get_y()) {
bottom_direction = "N";
} else {
bottom_direction = "S";
}
}
}
// else: aspect ratio is between 0.9 and 1.1, or symmetric, remains "C" (center)
if (top_aspect_ratio > 1.1) {
// Horizontal direction - check if cut is left (W) or right (E) shifted
if (std::abs(cut_center.get_x() - top_center.get_x()) > 1) {
if (cut_center.get_x() < top_center.get_x()) {
top_direction = "W";
} else {
top_direction = "E";
}
}
} else if (top_aspect_ratio < 0.9) {
// Vertical direction - check if cut is up (N) or down (S) shifted
if (std::abs(cut_center.get_y() - top_center.get_y()) > 1) {
if (cut_center.get_y() > top_center.get_y()) {
top_direction = "N";
} else {
top_direction = "S";
}
}
}
// else: aspect ratio is between 0.9 and 1.1, or symmetric, remains "C" (center)
json_via["bottom_direction"] = bottom_direction;
json_via["top_direction"] = top_direction;
}
json_via_list.push_back(json_via);
}



Loading…
Cancel
Save
Baidu
map